summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-01-10 19:01:23 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-01-10 19:01:23 +0000
commit41e7bbcf3d375486769059090e15260dc92f16c7 (patch)
tree5c368873297b82c25a8ba866cbeda97cce94d9fc
parent4f73884441d6a5c6ba4af7e5026807822aa034a0 (diff)
parent7f6cf1d740d6f047507d8bd2bc07ab12496e8024 (diff)
downloadAdServices-aml_tz5_341510010.tar.gz
Snap for 11296156 from 7f6cf1d740d6f047507d8bd2bc07ab12496e8024 to mainline-tzdata5-releaseaml_tz5_341510050aml_tz5_341510010aml_tz5_341510010
Change-Id: I84e6c0df7ccbfafbe8dd398518474c2b7a676013
-rw-r--r--adservices/TEST_MAPPING34
-rw-r--r--adservices/apk/AdExtServicesManifest.xml4
-rw-r--r--adservices/apk/AndroidManifest.xml10
-rw-r--r--adservices/apk/java/com/android/adservices/common/AdServicesCommonService.java5
-rw-r--r--adservices/apk/java/com/android/adservices/shell/AdServicesShellCommandService.java57
-rw-r--r--adservices/apk/java/com/android/adservices/ui/UxUtil.java6
-rw-r--r--adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationActivity.java12
-rw-r--r--adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationTrigger.java66
-rw-r--r--adservices/apk/java/com/android/adservices/ui/settings/activities/AdServicesSettingsMainActivity.java3
-rw-r--r--adservices/apk/res/values-da/strings.xml2
-rw-r--r--adservices/apk/tests/notification/OWNERS1
-rw-r--r--adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java202
-rw-r--r--adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UiAutomatorTest.java4
-rw-r--r--adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UxSelectorUiAutomatorTest.java4
-rw-r--r--adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityUiAutomatorTest.java107
-rw-r--r--adservices/apk/tests/settings/OWNERS1
-rw-r--r--adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java282
-rw-r--r--adservices/apk/tests/settingsgaota/OWNERS1
-rw-r--r--adservices/apk/tests/settingsgaota/src/com/android/adservices/ui/settingsga/SettingsActivityUiAutomatorTest.java569
-rw-r--r--adservices/apk/tests/settingsgaota/src/com/android/adservices/ui/settingsga/SettingsGaUiAutomatorTest.java74
-rw-r--r--adservices/apk/tests/settingsgauxselector/OWNERS2
-rw-r--r--adservices/apk/tests/settingsgauxselector/src/com/android/adservices/ui/settingsga/SettingsRvcUxSelectorUiAutomatorTest.java4
-rw-r--r--adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java97
-rw-r--r--adservices/apk/unittest/src/com/android/adservices/topics/TopicsServiceTest.java96
-rw-r--r--adservices/clients/java/android/adservices/clients/measurement/MeasurementClient.java237
-rw-r--r--adservices/framework/Android.bp2
-rw-r--r--adservices/framework/java/android/adservices/adid/AdIdCompatibleManager.java6
-rw-r--r--adservices/framework/java/android/adservices/adselection/SignedContextualAds.java2
-rw-r--r--adservices/framework/java/android/adservices/appsetid/AppSetIdManager.java7
-rw-r--r--adservices/framework/java/android/adservices/common/AdServicesPermissions.java8
-rw-r--r--adservices/framework/java/android/adservices/shell/IShellCommand.aidl33
-rw-r--r--adservices/framework/java/android/adservices/shell/IShellCommandCallback.aidl27
-rw-r--r--adservices/framework/java/android/adservices/shell/ShellCommandParam.aidl20
-rw-r--r--adservices/framework/java/android/adservices/shell/ShellCommandParam.java69
-rw-r--r--adservices/framework/java/android/adservices/shell/ShellCommandResult.aidl20
-rw-r--r--adservices/framework/java/android/adservices/shell/ShellCommandResult.java136
-rw-r--r--adservices/framework/java/android/adservices/signals/ProtectedSignalsManager.java4
-rw-r--r--adservices/framework/java/com/android/adservices/AdServicesCommon.java5
-rw-r--r--adservices/framework/java/com/android/adservices/AndroidServiceBinder.java4
-rw-r--r--adservices/framework/java/com/android/adservices/LogUtil.java35
-rw-r--r--adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt1
-rw-r--r--adservices/linter/java/android/adservices/lint/PreconditionsCheckStateDetector.kt57
-rw-r--r--adservices/linter/tests/java/android/adservices/lint/test/PreconditionsCheckStateDetectorTest.kt141
-rw-r--r--adservices/samples/topics/sampleapp1/Android.bp4
-rw-r--r--adservices/samples/topics/sampleapp1/java/com/example/adservices/samples/topics/sampleapp1/MainActivity.java42
-rw-r--r--adservices/samples/topics/sampleapp2/Android.bp4
-rw-r--r--adservices/samples/topics/sampleapp2/java/com/example/adservices/samples/topics/sampleapp2/MainActivity.java85
-rw-r--r--adservices/samples/topics/sampleapp3/Android.bp4
-rw-r--r--adservices/samples/topics/sampleapp3/java/com/example/adservices/samples/topics/sampleapp3/MainActivity.java85
-rw-r--r--adservices/samples/topics/sampleapp4/Android.bp4
-rw-r--r--adservices/samples/topics/sampleapp4/java/com/example/adservices/samples/topics/sampleapp4/MainActivity.java84
-rw-r--r--adservices/samples/topics/sampleapp5/Android.bp4
-rw-r--r--adservices/samples/topics/sampleapp5/java/com/example/adservices/samples/topics/sampleapp5/MainActivity.java83
-rw-r--r--adservices/samples/topics/sampleapp6/Android.bp4
-rw-r--r--adservices/samples/topics/sampleapp6/java/com/example/adservices/samples/topics/sampleapp6/MainActivity.java82
-rw-r--r--adservices/samples/topics/sampleappwithnoperm/Android.bp4
-rw-r--r--adservices/samples/topics/sampleappwithnoperm/java/com/example/adservices/samples/topics/sampleappwithnoperm/MainActivity.java86
-rw-r--r--adservices/samples/topics/sampleappwithoptoutall/Android.bp4
-rw-r--r--adservices/samples/topics/sampleappwithoptoutall/java/com/example/adservices/samples/topics/sampleappwithoptoutall/MainActivity.java86
-rw-r--r--adservices/service-core/Android.bp5
-rw-r--r--adservices/service-core/java/com/android/adservices/data/adselection/EncryptionKeyDao.java2
-rw-r--r--adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDao.java3
-rw-r--r--adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDbHelper.java6
-rw-r--r--adservices/service-core/java/com/android/adservices/data/measurement/MeasurementTables.java35
-rw-r--r--adservices/service-core/java/com/android/adservices/data/measurement/SqliteObjectMapper.java9
-rw-r--r--adservices/service-core/java/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV31.java71
-rw-r--r--adservices/service-core/java/com/android/adservices/data/signals/DBSignalsUpdateMetadata.java81
-rw-r--r--adservices/service-core/java/com/android/adservices/data/signals/EncoderLogicHandler.java6
-rw-r--r--adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDao.java79
-rw-r--r--adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDatabase.java6
-rw-r--r--adservices/service-core/java/com/android/adservices/service/Flags.java154
-rw-r--r--adservices/service-core/java/com/android/adservices/service/FlagsConstants.java42
-rw-r--r--adservices/service-core/java/com/android/adservices/service/PhFlags.java206
-rw-r--r--adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java45
-rw-r--r--adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionServiceImpl.java54
-rw-r--r--adservices/service-core/java/com/android/adservices/service/adselection/OnDeviceAdSelectionRunner.java15
-rw-r--r--adservices/service-core/java/com/android/adservices/service/adselection/TrustedServerAdSelectionRunner.java10
-rw-r--r--adservices/service-core/java/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManager.java95
-rw-r--r--adservices/service-core/java/com/android/adservices/service/adselection/signature/ThreadUnsafeByteArrayOutputStream.java4
-rw-r--r--adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentStorageManager.java6
-rw-r--r--adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentWorker.java167
-rw-r--r--adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchDao.java48
-rw-r--r--adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorker.java9
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/AdServicesCommonServiceImpl.java6
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/AppManifestConfig.java42
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigCall.java153
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigHelper.java61
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigMetricsLogger.java92
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/FledgeAuthorizationFilter.java39
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/PackageChangedReceiver.java4
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/PermissionHelper.java10
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java2
-rw-r--r--adservices/service-core/java/com/android/adservices/service/consent/AdServicesStorageManager.java16
-rw-r--r--adservices/service-core/java/com/android/adservices/service/consent/AppConsentForRStorageManager.java266
-rw-r--r--adservices/service-core/java/com/android/adservices/service/consent/AppConsentStorageManager.java119
-rw-r--r--adservices/service-core/java/com/android/adservices/service/consent/ConsentCompositeStorage.java658
-rw-r--r--adservices/service-core/java/com/android/adservices/service/consent/ConsentConstants.java4
-rw-r--r--adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java31
-rw-r--r--adservices/service-core/java/com/android/adservices/service/consent/ConsentManagerV2.java1445
-rw-r--r--adservices/service-core/java/com/android/adservices/service/consent/ConsentMigrationUtils.java193
-rw-r--r--adservices/service-core/java/com/android/adservices/service/consent/IConsentStorage.java26
-rw-r--r--adservices/service-core/java/com/android/adservices/service/customaudience/CustomAudienceServiceImpl.java14
-rw-r--r--adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java2
-rw-r--r--adservices/service-core/java/com/android/adservices/service/encryptionkey/EncryptionKey.java15
-rw-r--r--adservices/service-core/java/com/android/adservices/service/enrollment/EnrollmentData.java15
-rw-r--r--adservices/service-core/java/com/android/adservices/service/exception/ConsentStorageDeferException.java26
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/PrivacyParams.java5
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/Source.java83
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/attribution/AttributionJobHandler.java40
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/noising/ImpressionNoiseUtil.java66
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/noising/SourceNoiseHandler.java143
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRedirect.java51
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRedirects.java126
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistration.java22
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunner.java34
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncSourceFetcher.java15
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncTriggerFetcher.java13
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistration.java1
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/registration/FetcherUtil.java9
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java6
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java16
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportApi.java1
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportingJobHandler.java10
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegate.java264
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportingJobHandler.java10
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/reporting/ReportingStatus.java8
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/util/Enrollment.java1
-rw-r--r--adservices/service-core/java/com/android/adservices/service/shell/AdServicesShellCommandHandler.java33
-rw-r--r--adservices/service-core/java/com/android/adservices/service/shell/ShellCommandServiceImpl.java59
-rw-r--r--adservices/service-core/java/com/android/adservices/service/signals/PeriodicEncodingJobWorker.java29
-rw-r--r--adservices/service-core/java/com/android/adservices/service/signals/ProtectedSignalsServiceImpl.java6
-rw-r--r--adservices/service-core/java/com/android/adservices/service/signals/SignalsMaintenanceTasksWorker.java15
-rw-r--r--adservices/service-core/java/com/android/adservices/service/signals/UpdateProcessingOrchestrator.java9
-rw-r--r--adservices/service-core/java/com/android/adservices/service/signals/UpdateSignalsOrchestrator.java10
-rw-r--r--adservices/service-core/java/com/android/adservices/service/stats/ConsentMigrationStats.java11
-rw-r--r--adservices/service-core/java/com/android/adservices/service/topics/EncryptionManager.java5
-rw-r--r--adservices/service-core/java/com/android/adservices/service/topics/TopicsServiceImpl.java6
-rw-r--r--adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java8
-rw-r--r--adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java4
-rw-r--r--adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java2
-rw-r--r--adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/AlreadyEnrolledChannel.java7
-rw-r--r--adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/ConsentNotificationResetChannel.java3
-rw-r--r--adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/RvcPostOTAChannel.java5
-rw-r--r--adservices/service-core/schemas/com.android.adservices.data.signals.ProtectedSignalsDatabase/4.json239
-rw-r--r--adservices/service/java/com/android/server/adservices/AdServicesManagerService.java2
-rw-r--r--adservices/service/java/com/android/server/adservices/AdServicesShellCommand.java98
-rw-r--r--adservices/tests/cts/Android.bp11
-rw-r--r--adservices/tests/cts/AndroidTest.ExtServices.xml6
-rw-r--r--adservices/tests/cts/AndroidTest.Root.xml11
-rw-r--r--adservices/tests/cts/AndroidTest.xml6
-rw-r--r--adservices/tests/cts/AndroidTestDebuggable.ExtServices.xml6
-rw-r--r--adservices/tests/cts/AndroidTestDebuggable.xml6
-rw-r--r--adservices/tests/cts/adid/Android.bp8
-rw-r--r--adservices/tests/cts/adid/src/com/android/adservices/tests/adid/AdIdManagerTest.java15
-rw-r--r--adservices/tests/cts/appsetid/Android.bp6
-rw-r--r--adservices/tests/cts/assets/scenarios/data/InvalidJson.json1
-rw-r--r--adservices/tests/cts/assets/scenarios/remarketing-cuj-034.json69
-rw-r--r--adservices/tests/cts/assets/scenarios/remarketing-cuj-053.json71
-rw-r--r--adservices/tests/cts/cobalt/Android.bp8
-rw-r--r--adservices/tests/cts/endtoends/measurement/Android.bp6
-rw-r--r--adservices/tests/cts/endtoends/permissions/appoptout/Android.bp6
-rw-r--r--adservices/tests/cts/endtoends/permissions/noperm/Android.bp6
-rw-r--r--adservices/tests/cts/endtoends/permissions/notallowed/Android.bp6
-rw-r--r--adservices/tests/cts/endtoends/permissions/valid/Android.bp6
-rw-r--r--adservices/tests/cts/endtoends/topics/Android.bp5
-rw-r--r--adservices/tests/cts/endtoends/topics/appupdate/Android.bp6
-rw-r--r--adservices/tests/cts/endtoends/topics/connection/Android.bp6
-rw-r--r--adservices/tests/cts/endtoends/topics/mdd/Android.bp6
-rw-r--r--adservices/tests/cts/endtoends/topics/src/com/android/adservices/tests/cts/topics/TopicsManagerTest.java6
-rw-r--r--adservices/tests/cts/extdata/Android.bp6
-rw-r--r--adservices/tests/cts/hosttests/Android.bp2
-rw-r--r--adservices/tests/cts/hosttests/app/Android.bp1
-rw-r--r--adservices/tests/cts/sandbox/adid/Android.bp1
-rw-r--r--adservices/tests/cts/sandbox/appsetid/Android.bp1
-rw-r--r--adservices/tests/cts/sandbox/fledge/Android.bp1
-rw-r--r--adservices/tests/cts/sandbox/measurement/Android.bp1
-rw-r--r--adservices/tests/cts/sandbox/topics/Android.bp1
-rw-r--r--adservices/tests/cts/src/android/adservices/cts/CustomAudienceApiCtsTest.java599
-rw-r--r--adservices/tests/cts/src/android/adservices/cts/ForegroundCtsTestCase.java (renamed from adservices/tests/cts/src/android/adservices/cts/ForegroundCtsTest.java)36
-rw-r--r--adservices/tests/cts/src/android/adservices/cts/TestAdSelectionManagerTest.java36
-rw-r--r--adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java35
-rw-r--r--adservices/tests/cts/src/android/adservices/debuggablects/FledgeCtsDebuggableTest.java54
-rw-r--r--adservices/tests/cts/src/android/adservices/debuggablects/MeasurementCtsDebuggableTest.java9
-rw-r--r--adservices/tests/cts/src/android/adservices/rootcts/CustomAudienceBackgroundFetchTest.java26
-rw-r--r--adservices/tests/cts/ui/gaux/alreadyenrolledchannel/Android.bp60
-rw-r--r--adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidManifestExtServices.xml32
-rw-r--r--adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidTest.ExtServices.Eu.xml114
-rw-r--r--adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidTest.ExtServices.Row.xml114
-rw-r--r--adservices/tests/cts/ui/gaux/alreadyenrolledchannel/src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelEuTest.java186
-rw-r--r--adservices/tests/cts/ui/gaux/alreadyenrolledchannel/src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelRowTest.java189
-rw-r--r--adservices/tests/cts/ui/gaux/debugchannel/Android.bp89
-rw-r--r--adservices/tests/cts/ui/gaux/debugchannel/AndroidManifestExtServices.xml31
-rw-r--r--adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.ApiOff.xml104
-rw-r--r--adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.Eu.xml104
-rw-r--r--adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.Row.xml107
-rw-r--r--adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelApiOffTest.java122
-rw-r--r--adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelEuTest.java224
-rw-r--r--adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelRowTest.java227
-rw-r--r--adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/AdservicesWorkflows.java6
-rw-r--r--adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java48
-rw-r--r--adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/pages/NotificationPages.java13
-rw-r--r--adservices/tests/host/room/Android.bp1
-rw-r--r--adservices/tests/host/room/AndroidTest.xml4
-rw-r--r--adservices/tests/host/room/src/com/android/adservices/room/test/RoomDatabaseVersionBumpGuardrailTest.java37
-rw-r--r--adservices/tests/jetpack/Android.bp15
-rw-r--r--adservices/tests/jetpack/src/com/android/adservices/TestUtil.java1
-rw-r--r--adservices/tests/jetpack/src/com/android/adservices/adid/AdIdManagerJetpackTest.java5
-rw-r--r--adservices/tests/jetpack/src/com/android/adservices/appsetid/AppSetIdManagerJetpackTest.java5
-rw-r--r--adservices/tests/jetpack/src/com/android/adservices/measurement/MeasurementManagerJetpackTest.java3
-rw-r--r--adservices/tests/jetpack/src/com/android/adservices/protectedaudience/FledgeCtsDebuggableJetpackTest.java37
-rw-r--r--adservices/tests/jetpack/src/com/android/adservices/topics/TopicsManagerJetpackTest.java5
-rw-r--r--adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/AdSelectionDataE2ETest.java2
-rw-r--r--adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/GetAdSelectionDataLatency.java566
-rw-r--r--adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/ServerAuctionOneBuyerLargeCaLatency.java2
-rw-r--r--adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java19
-rw-r--r--adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java22
-rw-r--r--adservices/tests/perf/tests/src/android/adservices/test/scenario/adservices/fledge/GetAdSelectionDataLatencyMicroBenchmark.java19
-rw-r--r--adservices/tests/test-util/Android.bp1
-rw-r--r--adservices/tests/test-util/host-side/com/android/adservices/common/TestDeviceHelper.java13
-rw-r--r--adservices/tests/test-util/java/com/android/adservices/common/ExceptionFailureSyncCallback.java20
-rw-r--r--adservices/tests/test-util/java/com/android/adservices/mockito/ExtendedMockitoExpectations.java15
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/AbstractAdServicesFlagsSetterRule.java12
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java59
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java2
-rw-r--r--adservices/tests/unittest/adservices-test-utility/AndroidTest.xml9
-rw-r--r--adservices/tests/unittest/fixtures/java/android/adservices/adselection/AdSelectionConfigFixture.java5
-rw-r--r--adservices/tests/unittest/fixtures/java/android/adservices/adselection/SignedContextualAdsFixture.java143
-rw-r--r--adservices/tests/unittest/fixtures/java/android/adservices/customaudience/CustomAudienceFixture.java58
-rw-r--r--adservices/tests/unittest/fixtures/java/com/android/adservices/service/PhFlagsFixture.java104
-rw-r--r--adservices/tests/unittest/fixtures/java/com/android/adservices/service/measurement/AsyncRegistrationFixture.java6
-rw-r--r--adservices/tests/unittest/framework/src/android/adservices/adselection/SignedContextualAdsTest.java127
-rw-r--r--adservices/tests/unittest/service-core/AndroidManifest.xml1
-rw-r--r--adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchConsentWorkerTest.java379
-rw-r--r--adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchDaoTest.java41
-rw-r--r--adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorkerTest.java30
-rw-r--r--adservices/tests/unittest/service-core/assets/attribution_service_test.json34
-rw-r--r--adservices/tests/unittest/service-core/assets/measurement_app_uninstall_deletion_test.json21
-rw-r--r--adservices/tests/unittest/service-core/assets/measurement_delete_expired_test.json15
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/flex_api_with_no_origin_multiple_domain.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/registrant_not_found.json12
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain_preserve.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain_preserve.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_nor_range.json12
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_origin_but_no_range.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_but_no_origin.json12
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_and_origin.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_no_origin.json12
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_and_origin.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_no_origin.json12
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_and_origin.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_no_origin_preserve.json9
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_debug_source_storage_limit.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_large_keys.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_many_trigger_data.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_over_contributions_limit.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_three_of_three_entries.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_source.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_trigger.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_source.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_trigger.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_null_reports.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_3_conversions.json1
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2.json1
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2_w3.json1
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_install_attribution.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w1.json1
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w2.json1
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w3.json1
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_aggregatable_two_contributions.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-app_source_destination_limit.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-web_source_destination_limit.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger-reporting-origin-limit-app-app.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-app.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-web.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-app.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-different-registrant.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-same-registrant.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-app.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-web.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-app.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-different-registrant.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-same-registrant.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_3_app_sources_3_web_triggers_3_reports.json6
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_cannot_redirect.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/basic_use_of_redirect.json8
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/basic_use_of_redirect_to_well_known.json113
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/complex_use_of_redirects.json20
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/complex_use_of_redirects_to_well_known.json287
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_1_allowed.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_2_allowed.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_disabled.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/enrollment_flag_disabled.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_debug_source_storage_limit.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_report_window.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_time_based_source_selection.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/limit_num_reports_for_click.json6
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_as_reporting_origin.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_basic_use_of_redirect.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_ip_as_reporting_origin.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/only_one_source_of_multiple_matches_can_be_attributed.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/priority_based_source_selection.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWebSource_3_sources_3_triggers_3_reports.json6
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_different_registrant.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_same_registrant.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_no_adid_no_ar_debug.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_disabled_different_registrant.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_enabled_different_registrant.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_app_and_web_matching.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_web_only_matching.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_adid_debug_api.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_ar_debug_adid_debug_api.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_debug_api_ar_debug.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_multiple_destinations.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_redirects_ignored.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_web_app_matching_debug_api_adid_ar_debug.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_1-1_app-app_matching.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_empty_object_event_trigger_data.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_null_trigger_data_null_source_event_id.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_dual_destination_source_storage_limit_debug_report.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_source_storage_limit_debug_report.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_web-web_source_storage_limit_debug_report.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_one_trigger.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_three_triggers_one_dedup.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/two_simple_matches_testing_multiplicity.json4
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_disabled_basic.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_original_source_wins_install_attribution.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_reg_has_original_xna_source_avoids_creating_derived_source.json2
-rw-r--r--adservices/tests/unittest/service-core/assets/msmt_interop_tests/event_report_windows.json289
-rw-r--r--adservices/tests/unittest/service-core/common/Android.bp33
-rw-r--r--adservices/tests/unittest/service-core/common/AndroidManifest.xml30
-rw-r--r--adservices/tests/unittest/service-core/common/AndroidTest.ExtServices.xml48
-rw-r--r--adservices/tests/unittest/service-core/common/AndroidTest.xml37
-rw-r--r--adservices/tests/unittest/service-core/common/src/com/android/adservices/errorlogging/AdServicesErrorLoggerImplTest.java (renamed from adservices/tests/unittest/service-core/src/com/android/adservices/errorlogging/AdServicesErrorLoggerImplTest.java)71
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/customaudience/DBCustomAudienceBackgroundFetchDataTest.java32
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/enrollment/EnrollmentDaoTest.java2
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/AbstractDbIntegrationTest.java3
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/DbState.java3
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDaoTest.java41
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDbSchemaTrail.java52
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/ContentValueFixtures.java9
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV30Test.java1
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV31Test.java108
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/DBSignalsUpdateMetadataTest.java112
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/EncoderLogicHandlerTest.java7
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDaoTest.java184
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDatabaseMigrationTest.java23
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/PhFlagsTest.java298
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererImplTest.java2
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererNoOpImplTest.java2
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionConfigValidatorTest.java15
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionE2ETest.java247
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionFromOutcomesE2ETest.java17
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionServiceImplTest.java178
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdsScoreGeneratorImplTest.java12
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AuctionServerE2ETest.java24
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/FrequencyCapFilteringE2ETest.java33
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OnDeviceAdSelectionRunnerTest.java136
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportAndRegisterEventE2ETest.java17
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportImpressionScriptEngineTest.java1
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/TrustedServerAdSelectionRunnerTest.java14
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/BinarySerializerSignedContextualAdsTest.java8
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManagerTest.java127
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/ThreadUnsafeByteArrayOutputStreamTest.java (renamed from adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/SafeNoCopyByteArrayOutputStreamTest.java)2
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigCallTest.java250
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigHelperTest.java107
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigMetricsLoggerTest.java305
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigParserTest.java262
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeAuthorizationFilterTest.java72
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeE2ETest.java54
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PackageChangedReceiverTest.java39
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PermissionHelperTest.java10
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/consent/ConsentMigrationUtilsTest.java78
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceEndToEndTest.java20
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceImplTest.java80
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/E2EInteropMockTest.java13
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/EventReportTest.java33
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/SourceTest.java22
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerIntegrationTest.java2
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerTest.java23
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerAttributionProbabilityTest.java335
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerTest.java67
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueJobServiceTest.java38
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunnerTest.java705
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncSourceFetcherTest.java1129
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncTriggerFetcherTest.java1149
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistrationTest.java34
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java159
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/DebugReportApiTest.java194
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegateTest.java573
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/shell/AdServicesShellCommandHandlerTest.java21
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/shell/ShellCommandServiceImplTest.java70
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/PeriodicEncodingJobWorkerTest.java52
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/ProtectedSignalsServiceImplTest.java3
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsEncodingE2ETest.java15
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsIntakeE2ETest.java4
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsMaintenanceTasksWorkerTest.java17
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateProcessingOrchestratorTest.java22
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateSignalsOrchestratorTest.java3
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/AdServicesLoggerImplTest.java396
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/StatsdAdServicesLoggerTest.java178
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/EncryptionManagerTest.java18
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/TopicsServiceImplTest.java8
-rw-r--r--adservices/tests/unittest/system-service/src/com/android/server/adservices/AdServicesShellCommandTest.java107
-rw-r--r--adservices/tests/unittest/ui/src/com/android/adservices/service/consent/AppConsentForRStorageManagerTest.java223
-rw-r--r--adservices/tests/unittest/ui/src/com/android/adservices/service/consent/ConsentCompositeStorageTest.java11
-rw-r--r--adservices/tests/unittest/ui/src/com/android/adservices/service/consent/ConsentManagerV2Test.java4635
-rw-r--r--adservices/tests/unittest/ui/src/com/android/adservices/service/ui/UxEngineTest.java4
-rw-r--r--adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/AlreadyEnrolledChannelTest.java11
-rw-r--r--adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/RvcPostOTAChannelTest.java6
-rw-r--r--apex/Android.bp1
-rw-r--r--sdksandbox/service/java/com/android/server/sdksandbox/SdkSandboxManagerService.java20
-rw-r--r--sdksandbox/tests/cts/endtoendtests/Android.bp2
-rw-r--r--sdksandbox/tests/cts/endtoendtests/AndroidTest.xml19
-rw-r--r--sdksandbox/tests/cts/endtoendtests/DisabledAndroidTest.xml21
-rw-r--r--sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/Android.bp1
-rw-r--r--sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/IMediationTestSdkApi.aidl1
-rw-r--r--sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/MediationTestSdkApiImpl.java48
-rw-r--r--sdksandbox/tests/cts/endtoendtests/src/com/android/tests/sdksandbox/endtoend/SdkSandboxMediationTest.java65
-rw-r--r--sdksandbox/tests/cts/hostside/Android.bp1
-rw-r--r--sdksandbox/tests/cts/inprocess/Android.bp5
-rw-r--r--sdksandbox/tests/cts/inprocess/src/com/android/sdksandbox/tests/cts/inprocess/SdkSandboxConfigurationTest.java90
-rw-r--r--sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java31
-rw-r--r--sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java88
-rw-r--r--sdksandbox/tests/testutils/src/android/app/sdksandbox/testutils/ProtoUtil.java161
-rw-r--r--sdksandbox/tests/testutils/src/com/android/server/sdksandbox/testutils/FakeSdkSandboxProvider.java4
-rw-r--r--sdksandbox/tests/unittest/Android.bp1
-rw-r--r--sdksandbox/tests/unittest/src/com/android/sdksandbox/SdkSandboxTest.java14
-rw-r--r--sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxManagerServiceUnitTest.java145
-rw-r--r--shared/device-side/libraries/Android.bp25
-rw-r--r--shared/device-side/libraries/java/com/android/adservices/shared/common/ApplicationContextSingleton.java15
-rw-r--r--shared/device-side/libraries/java/com/android/adservices/shared/testing/common/DumpHelper.java5
-rw-r--r--shared/device-side/libraries/java/com/android/adservices/shared/util/Preconditions.java49
-rw-r--r--shared/device-side/tests/Android.bp1
-rw-r--r--shared/device-side/tests/java/com/android/adservices/shared/storage/BooleanFileDatastoreTest.java1
-rw-r--r--shared/device-side/tests/java/com/android/adservices/shared/util/PreconditionsTest.java56
454 files changed, 21735 insertions, 7414 deletions
diff --git a/adservices/TEST_MAPPING b/adservices/TEST_MAPPING
index cd6c7f89c..795b16f7e 100644
--- a/adservices/TEST_MAPPING
+++ b/adservices/TEST_MAPPING
@@ -172,6 +172,24 @@
]
},
{
+ // Install com.google.android.adservices.apex and run AdServicesServiceCoreCommonUnitTests.
+ "name": "AdServicesServiceCoreCommonUnitTests[com.google.android.adservices.apex]",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ // Install com.google.android.adservices.apex and run AdExtServicesServiceCoreCommonUnitTests.
+ "name": "AdExtServicesServiceCoreCommonUnitTests[com.google.android.extservices.apex]",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
// Install com.google.android.adservices.apex and run AdServicesServiceCoreAppSearchUnitTests.
"name": "AdServicesServiceCoreAppSearchUnitTests[com.google.android.adservices.apex]",
"options": [
@@ -635,6 +653,14 @@
]
},
{
+ "name": "AdServicesServiceCoreCommonUnitTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
"name": "AdServicesServiceCoreAppSearchUnitTests",
"options": [
{
@@ -651,9 +677,7 @@
]
},
{
- // Install com.google.android.adservices.apex and run
- // AdServicesServiceCoreMeasurementUnitTests.
- "name": "AdServicesServiceCoreMeasurementUnitTests[com.google.android.adservices.apex]",
+ "name": "AdServicesServiceCoreMeasurementUnitTests",
"options": [
{
"exclude-annotation": "androidx.test.filters.FlakyTest"
@@ -661,9 +685,7 @@
]
},
{
- // Install com.google.android.extservices.apex and run
- // AdExtServicesServiceCoreMeasurementUnitTests.
- "name": "AdExtServicesServiceCoreMeasurementUnitTests[com.google.android.extservices.apex]",
+ "name": "AdExtServicesServiceCoreMeasurementUnitTests",
"options": [
{
"exclude-annotation": "androidx.test.filters.FlakyTest"
diff --git a/adservices/apk/AdExtServicesManifest.xml b/adservices/apk/AdExtServicesManifest.xml
index 717ef8db0..c58937d6e 100644
--- a/adservices/apk/AdExtServicesManifest.xml
+++ b/adservices/apk/AdExtServicesManifest.xml
@@ -109,6 +109,10 @@
<uses-permission android:name="android.permission.ACCESS_PRIVILEGED_APP_SET_ID_COMPAT"/>
<uses-permission android:name="android.permission.ACCESS_PRIVILEGED_ADSERVICES_COBALT_UPLOAD_COMPAT" />
+ <!-- Permission to allow self calling Common Service. -->
+ <uses-permission android:name="android.permission.ACCESS_ADSERVICES_STATE_COMPAT"/>
+ <uses-permission android:name="android.permission.MODIFY_ADSERVICES_STATE_COMPAT"/>
+
<!-- Allows JobScheduler to persist jobs across reboot. -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
diff --git a/adservices/apk/AndroidManifest.xml b/adservices/apk/AndroidManifest.xml
index ad3a4cbfd..cb998df71 100644
--- a/adservices/apk/AndroidManifest.xml
+++ b/adservices/apk/AndroidManifest.xml
@@ -275,6 +275,15 @@
</intent-filter>
</service>
+ <service android:name="com.android.adservices.shell.AdServicesShellCommandService"
+ android:exported="true"
+ android:visibleToInstantApps="false"
+ >
+ <intent-filter android:priority="1">
+ <action android:name="android.adservices.SHELL_COMMAND_SERVICE"/>
+ </intent-filter>
+ </service>
+
<!-- Daily maintenance Job. -->
<service android:name="com.android.adservices.service.MaintenanceJobService"
android:permission="android.permission.BIND_JOB_SERVICE">
@@ -436,3 +445,4 @@
/>
</application>
</manifest>
+
diff --git a/adservices/apk/java/com/android/adservices/common/AdServicesCommonService.java b/adservices/apk/java/com/android/adservices/common/AdServicesCommonService.java
index 9c99aa982..f8fb54d8e 100644
--- a/adservices/apk/java/com/android/adservices/common/AdServicesCommonService.java
+++ b/adservices/apk/java/com/android/adservices/common/AdServicesCommonService.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
+import android.os.Trace;
import androidx.annotation.RequiresApi;
@@ -51,6 +52,8 @@ public class AdServicesCommonService extends Service {
@Override
public void onCreate() {
super.onCreate();
+
+ Trace.beginSection("AdServicesCommonService#Initialization");
if (mAdServicesCommonService == null) {
mAdServicesCommonService =
new AdServicesCommonServiceImpl(
@@ -80,6 +83,7 @@ public class AdServicesCommonService extends Service {
"getting exception when register consumer in AdServicesSyncUtil of "
+ e.getMessage());
}
+ Trace.endSection();
}
@Override
@@ -90,7 +94,6 @@ public class AdServicesCommonService extends Service {
// TODO(b/308009734): STOPSHIP - remove this method once the proper service is available
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- enforceCallingPermission(android.Manifest.permission.DUMP, /* message = */ "dump()");
if (args != null && args.length > 0 && args[0].equals("cmd")) {
boolean enabled = FlagsFactory.getFlags().getAdServicesShellCommandEnabled();
if (!enabled) {
diff --git a/adservices/apk/java/com/android/adservices/shell/AdServicesShellCommandService.java b/adservices/apk/java/com/android/adservices/shell/AdServicesShellCommandService.java
new file mode 100644
index 000000000..8d07378ca
--- /dev/null
+++ b/adservices/apk/java/com/android/adservices/shell/AdServicesShellCommandService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 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.shell;
+
+import android.annotation.Nullable;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import com.android.adservices.LogUtil;
+import com.android.adservices.service.FlagsFactory;
+import com.android.adservices.service.shell.ShellCommandServiceImpl;
+
+import java.util.Objects;
+
+/** Implements a service which runs the shell command in the adservices process. */
+public final class AdServicesShellCommandService extends Service {
+
+ /** The binder service. This field must only be accessed on the main thread. */
+ private ShellCommandServiceImpl mShellCommandService;
+
+ @Override
+ public void onCreate() {
+ if (!FlagsFactory.getFlags().getAdServicesShellCommandEnabled()) {
+ LogUtil.e("Shell command service is not enabled.");
+ return;
+ }
+
+ mShellCommandService = new ShellCommandServiceImpl();
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (!FlagsFactory.getFlags().getAdServicesShellCommandEnabled()) {
+ LogUtil.e("Shell command service is not enabled.");
+ return null;
+ }
+ return Objects.requireNonNull(mShellCommandService);
+ }
+
+ // TODO(b/308009734): Implement dump method.
+}
diff --git a/adservices/apk/java/com/android/adservices/ui/UxUtil.java b/adservices/apk/java/com/android/adservices/ui/UxUtil.java
index 035c3d284..9efc670f3 100644
--- a/adservices/apk/java/com/android/adservices/ui/UxUtil.java
+++ b/adservices/apk/java/com/android/adservices/ui/UxUtil.java
@@ -36,7 +36,11 @@ public class UxUtil {
/** Returns whether the device is an EEA device. */
public static boolean isEeaDevice(FragmentActivity fragmentActivity, Context context) {
return FlagsFactory.getFlags().getConsentNotificationActivityDebugMode()
- ? fragmentActivity.getIntent().getBooleanExtra("isEUDevice", /* default= */ true)
+ ? fragmentActivity
+ .getIntent()
+ .getBooleanExtra(
+ "isEUDevice",
+ /* default= */ UxStatesManager.getInstance(context).isEeaDevice())
: !ConsentManager.getInstance(context).isAdIdEnabled()
|| UxStatesManager.getInstance(context).isEeaDevice();
}
diff --git a/adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationActivity.java b/adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationActivity.java
index 9492a5188..3455cc7fd 100644
--- a/adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationActivity.java
+++ b/adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationActivity.java
@@ -107,11 +107,7 @@ public class ConsentNotificationActivity extends FragmentActivity implements UxS
@Override
public void initGA() {
- if (FlagsFactory.getFlags().getEuNotifFlowChangeEnabled()) {
- setContentView(R.layout.consent_notification_ga_v2_activity);
- } else {
- setContentView(R.layout.consent_notification_ga_activity);
- }
+ setContentView(R.layout.consent_notification_ga_v2_activity);
}
@Override
@@ -131,11 +127,7 @@ public class ConsentNotificationActivity extends FragmentActivity implements UxS
private void initFragment() {
if (FlagsFactory.getFlags().getGaUxFeatureEnabled()) {
- if (FlagsFactory.getFlags().getEuNotifFlowChangeEnabled()) {
- setContentView(R.layout.consent_notification_ga_v2_activity);
- } else {
- setContentView(R.layout.consent_notification_ga_activity);
- }
+ setContentView(R.layout.consent_notification_ga_v2_activity);
} else {
setContentView(R.layout.consent_notification_activity);
}
diff --git a/adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationTrigger.java b/adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationTrigger.java
index 98230b848..a11a5a645 100644
--- a/adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationTrigger.java
+++ b/adservices/apk/java/com/android/adservices/ui/notifications/ConsentNotificationTrigger.java
@@ -16,7 +16,6 @@
package com.android.adservices.ui.notifications;
-import static com.android.adservices.service.FlagsConstants.KEY_EU_NOTIF_FLOW_CHANGE_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_GA_UX_FEATURE_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_NOTIFICATION_DISMISSED_ON_CLICK;
import static com.android.adservices.service.FlagsConstants.KEY_RECORD_MANUAL_INTERACTION_ENABLED;
@@ -37,7 +36,6 @@ import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import com.android.adservices.api.R;
-import com.android.adservices.service.FlagsFactory;
import com.android.adservices.service.consent.AdServicesApiType;
import com.android.adservices.service.consent.ConsentManager;
import com.android.adservices.service.stats.UiStatsLogger;
@@ -127,12 +125,7 @@ public class ConsentNotificationTrigger {
if (isUxStatesReady(context)) {
switch (UxUtil.getUx(context)) {
case GA_UX:
- if (UxStatesManager.getInstance(context)
- .getFlag(KEY_EU_NOTIF_FLOW_CHANGE_ENABLED)) {
- notification = getGaV2ConsentNotification(context, isEuDevice);
- } else {
- notification = getGaConsentNotification(context, isEuDevice);
- }
+ notification = getGaV2ConsentNotification(context, isEuDevice);
break;
// Both U18_UX and RVC_UX are showing U18 Notification
case U18_UX:
@@ -143,15 +136,11 @@ public class ConsentNotificationTrigger {
notification = getConsentNotification(context, isEuDevice);
break;
default:
- notification = getGaConsentNotification(context, isEuDevice);
+ notification = getGaV2ConsentNotification(context, isEuDevice);
}
} else {
if (gaUxFeatureEnabled) {
- if (FlagsFactory.getFlags().getEuNotifFlowChangeEnabled()) {
- notification = getGaV2ConsentNotification(context, isEuDevice);
- } else {
- notification = getGaConsentNotification(context, isEuDevice);
- }
+ notification = getGaV2ConsentNotification(context, isEuDevice);
} else {
notification = getConsentNotification(context, isEuDevice);
}
@@ -252,54 +241,7 @@ public class ConsentNotificationTrigger {
.setContentIntent(pendingIntent);
return notification.build();
}
-
- /**
- * Returns a {@link NotificationCompat.Builder} which can be used to display consent
- * notification to the user when GaUxFeature flag is enabled.
- *
- * @param context {@link Context} which is used to prepare a {@link NotificationCompat}.
- */
- private static Notification getGaConsentNotification(
- @NonNull Context context, boolean isEuDevice) {
- Intent intent = new Intent(context, ConsentNotificationActivity.class);
-
- PendingIntent pendingIntent =
- PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_IMMUTABLE);
- NotificationCompat.BigTextStyle textStyle =
- new NotificationCompat.BigTextStyle()
- .bigText(
- isEuDevice
- ? context.getString(
- R.string.notificationUI_notification_ga_content_eu)
- : context.getString(
- R.string.notificationUI_notification_ga_content));
- NotificationCompat.Builder notification =
- new NotificationCompat.Builder(context, CHANNEL_ID)
- .setSmallIcon(R.drawable.ic_info_icon)
- .setContentTitle(
- context.getString(
- isEuDevice
- ? R.string.notificationUI_notification_ga_title_eu
- : R.string.notificationUI_notification_ga_title))
- .setContentText(
- context.getString(
- isEuDevice
- ? R.string.notificationUI_notification_ga_content_eu
- : R.string.notificationUI_notification_ga_content))
- .setStyle(textStyle)
- .setPriority(NOTIFICATION_PRIORITY)
- .setAutoCancel(true)
- .setContentIntent(pendingIntent);
-
- if (isEuDevice
- && !UxStatesManager.getInstance(context)
- .getFlag(KEY_NOTIFICATION_DISMISSED_ON_CLICK)) {
- notification.setAutoCancel(false);
- }
-
- return notification.build();
- }
-
+
/**
* Returns a {@link NotificationCompat.Builder} which can be used to display consent
* notification to the user.
diff --git a/adservices/apk/java/com/android/adservices/ui/settings/activities/AdServicesSettingsMainActivity.java b/adservices/apk/java/com/android/adservices/ui/settings/activities/AdServicesSettingsMainActivity.java
index ee9067980..619978aad 100644
--- a/adservices/apk/java/com/android/adservices/ui/settings/activities/AdServicesSettingsMainActivity.java
+++ b/adservices/apk/java/com/android/adservices/ui/settings/activities/AdServicesSettingsMainActivity.java
@@ -19,6 +19,7 @@ import static com.android.adservices.ui.UxUtil.isUxStatesReady;
import android.os.Build;
import android.os.Bundle;
+import android.os.Trace;
import androidx.annotation.RequiresApi;
import androidx.lifecycle.ViewModelProvider;
@@ -58,6 +59,7 @@ public class AdServicesSettingsMainActivity extends AdServicesBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
+ Trace.beginSection("AdServicesSettingsMainActivity#OnCreate");
// Only for main view, we want to use the most up to date OTA strings on the device to
// create the ResourcesLoader.
if (FlagsFactory.getFlags().getUiOtaStringsFeatureEnabled()) {
@@ -70,6 +72,7 @@ public class AdServicesSettingsMainActivity extends AdServicesBaseActivity {
if (!isUxStatesReady(this)) {
initMainFragment();
}
+ Trace.endSection();
}
private void initMainFragment() {
diff --git a/adservices/apk/res/values-da/strings.xml b/adservices/apk/res/values-da/strings.xml
index ee2f09319..5f0eea93e 100644
--- a/adservices/apk/res/values-da/strings.xml
+++ b/adservices/apk/res/values-da/strings.xml
@@ -557,7 +557,7 @@
<string name="topic10320" msgid="5279440074507438174">"Onlinefællesskaber"</string>
<string name="topic10321" msgid="7018890132742820265">"Clipart og animerede GIF-billeder"</string>
<string name="topic10322" msgid="1585737438943011532">"Dating og personlige annoncer"</string>
- <string name="topic10323" msgid="962863497957179646">"Feedtilføjelser og sociale bogmærker"</string>
+ <string name="topic10323" msgid="962863497957179646">"Feedaggregering og sociale bogmærker"</string>
<string name="topic10324" msgid="1425257460381023853">"Fildeling og hosting"</string>
<string name="topic10325" msgid="8698912164970408378">"Udbydere af fora og chatprogrammer"</string>
<string name="topic10326" msgid="2425798096705921796">"Microblogs"</string>
diff --git a/adservices/apk/tests/notification/OWNERS b/adservices/apk/tests/notification/OWNERS
index 9530244f7..b0f9f618b 100644
--- a/adservices/apk/tests/notification/OWNERS
+++ b/adservices/apk/tests/notification/OWNERS
@@ -6,3 +6,4 @@ tccyp@google.com
yangwangyw@google.com
albertkong@google.com
bozhaobz@google.com
+ardroid@google.com
diff --git a/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java b/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java
index 42eff2d38..20dccae4a 100644
--- a/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java
+++ b/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java
@@ -16,20 +16,19 @@
package com.android.adservices.ui.notifications;
+import static com.android.adservices.service.FlagsConstants.KEY_GA_UX_FEATURE_ENABLED;
+import static com.android.adservices.service.FlagsConstants.KEY_NOTIFICATION_DISMISSED_ON_CLICK;
+import static com.android.adservices.service.FlagsConstants.KEY_RVC_UX_ENABLED;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__DEFAULT_AD_ID_STATE__AD_ID_DISABLED;
-import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__DEFAULT_CONSENT__PP_API_DEFAULT_OPT_OUT;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__DEFAULT_CONSENT__MEASUREMENT_DEFAULT_OPT_OUT;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__DEFAULT_CONSENT__PP_API_DEFAULT_OPT_OUT;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__ENROLLMENT_CHANNEL__FIRST_CONSENT_NOTIFICATION_CHANNEL;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__ENROLLMENT_CHANNEL__RVC_POST_OTA_NOTIFICATION_CHANNEL;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__EU;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__ROW;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__UX__GA_UX;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__UX__RVC_UX;
-import static com.android.adservices.service.FlagsConstants.KEY_EU_NOTIF_FLOW_CHANGE_ENABLED;
-import static com.android.adservices.service.FlagsConstants.KEY_GA_UX_FEATURE_ENABLED;
-import static com.android.adservices.service.FlagsConstants.KEY_NOTIFICATION_DISMISSED_ON_CLICK;
-import static com.android.adservices.service.FlagsConstants.KEY_RVC_UX_ENABLED;
import static com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection.BETA_UX;
import static com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection.GA_UX;
import static com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection.RVC_UX;
@@ -129,7 +128,6 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
doReturn(false).when(mMockUxStatesManager).getFlag(any(String.class));
doReturn(GA_UX).when(mMockUxStatesManager).getUx();
doReturn(true).when(mMockUxStatesManager).getFlag(KEY_NOTIFICATION_DISMISSED_ON_CLICK);
- doReturn(false).when(mMockUxStatesManager).getFlag(KEY_EU_NOTIF_FLOW_CHANGE_ENABLED);
cancelAllPreviousNotifications();
}
@@ -141,59 +139,6 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
}
@Test
- public void testEuNotification() throws InterruptedException, UiObjectNotFoundException {
- doReturn(true).when(mMockFlags).isEeaDevice();
- doReturn(false).when(mMockUxStatesManager).getFlag(KEY_GA_UX_FEATURE_ENABLED);
- doReturn(BETA_UX).when(mMockUxStatesManager).getUx();
-
- final String expectedTitle =
- mContext.getString(R.string.notificationUI_notification_title_eu);
- final String expectedContent =
- mContext.getString(R.string.notificationUI_notification_content_eu);
-
- ConsentNotificationTrigger.showConsentNotification(mContext, true);
- Thread.sleep(1000); // wait 1s to make sure that Notification is displayed.
-
- verify(mAdServicesLogger, times(2)).logUIStats(any());
-
- verify(mConsentManager, times(2)).getDefaultConsent();
- verify(mConsentManager, times(2)).getDefaultAdIdState();
- verify(mConsentManager).disable(mContext);
- verify(mConsentManager).recordNotificationDisplayed(true);
-
- assertThat(mNotificationManager.getActiveNotifications()).hasLength(1);
- final Notification notification =
- mNotificationManager.getActiveNotifications()[0].getNotification();
- assertThat(notification.getChannelId()).isEqualTo(NOTIFICATION_CHANNEL_ID);
- assertThat(notification.extras.getCharSequence(Notification.EXTRA_TITLE).toString())
- .isEqualTo(expectedTitle);
- assertThat(notification.extras.getCharSequence(Notification.EXTRA_TEXT).toString())
- .isEqualTo(expectedContent);
- assertThat(Notification.FLAG_ONGOING_EVENT & notification.flags).isEqualTo(0);
- assertThat(Notification.FLAG_NO_CLEAR & notification.flags).isEqualTo(0);
- assertThat(Notification.FLAG_AUTO_CANCEL & notification.flags)
- .isEqualTo(Notification.FLAG_AUTO_CANCEL);
-
- sDevice.openNotification();
- sDevice.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT);
- UiObject scroller =
- sDevice.findObject(
- new UiSelector()
- .packageName("com.android.systemui")
- .resourceId("com.android.systemui:id/notification_stack_scroller"));
-
- UiSelector notificationCardSelector =
- new UiSelector().text(getString(R.string.notificationUI_notification_title_eu));
- UiObject notificationCard = scroller.getChild(notificationCardSelector);
- assertThat(notificationCard.exists()).isTrue();
-
- notificationCard.click();
- Thread.sleep(LAUNCH_TIMEOUT);
- UiObject title = getPageElement(sDevice, R.string.notificationUI_header_title_eu);
- assertThat(title.exists()).isTrue();
- }
-
- @Test
public void testEuNotification_gaUxFlagEnabled()
throws InterruptedException, UiObjectNotFoundException {
doReturn(true).when(mMockFlags).isEeaDevice();
@@ -201,9 +146,9 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
doReturn(GA_UX).when(mMockUxStatesManager).getUx();
final String expectedTitle =
- mContext.getString(R.string.notificationUI_notification_ga_title_eu);
+ mContext.getString(R.string.notificationUI_notification_ga_title_eu_v2);
final String expectedContent =
- mContext.getString(R.string.notificationUI_notification_ga_content_eu);
+ mContext.getString(R.string.notificationUI_notification_ga_content_eu_v2);
ConsentNotificationTrigger.showConsentNotification(mContext, true);
Thread.sleep(1000); // wait 1s to make sure that Notification is displayed.
@@ -237,7 +182,11 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
.isEqualTo(Notification.FLAG_AUTO_CANCEL);
sDevice.openNotification();
- sDevice.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT);
+ sDevice.wait(
+ Until.hasObject(
+ By.pkg("com.android.systemui")
+ .res("com.android.systemui:id/notification_stack_scroller")),
+ LAUNCH_TIMEOUT);
UiObject scroller =
sDevice.findObject(
@@ -248,68 +197,16 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
UiObject notificationCard =
scroller.getChild(
new UiSelector()
- .text(getString(R.string.notificationUI_notification_ga_title_eu)));
+ .text(
+ getString(
+ R.string
+ .notificationUI_notification_ga_title_eu_v2)));
assertThat(notificationCard.exists()).isTrue();
notificationCard.click();
Thread.sleep(LAUNCH_TIMEOUT);
assertThat(mNotificationManager.getActiveNotifications()).hasLength(0);
}
-
- @Test
- public void testNonEuNotifications() throws InterruptedException, UiObjectNotFoundException {
- doReturn(false).when(mMockFlags).isEeaDevice();
- doReturn(false).when(mMockUxStatesManager).getFlag(KEY_GA_UX_FEATURE_ENABLED);
- doReturn(BETA_UX).when(mMockUxStatesManager).getUx();
-
- final String expectedTitle = mContext.getString(R.string.notificationUI_notification_title);
- final String expectedContent =
- mContext.getString(R.string.notificationUI_notification_content);
-
- ConsentNotificationTrigger.showConsentNotification(mContext, false);
- Thread.sleep(1000); // wait 1s to make sure that Notification is displayed.
-
- verify(mAdServicesLogger, times(2)).logUIStats(any());
-
- verify(mConsentManager, times(2)).getDefaultConsent();
- verify(mConsentManager, times(2)).getDefaultAdIdState();
- verify(mConsentManager).enable(mContext);
- verify(mConsentManager).recordNotificationDisplayed(true);
-
- assertThat(mNotificationManager.getActiveNotifications()).hasLength(1);
- final Notification notification =
- mNotificationManager.getActiveNotifications()[0].getNotification();
- assertThat(notification.getChannelId()).isEqualTo(NOTIFICATION_CHANNEL_ID);
- assertThat(notification.extras.getCharSequence(Notification.EXTRA_TITLE).toString())
- .isEqualTo(expectedTitle);
- assertThat(notification.extras.getCharSequence(Notification.EXTRA_TEXT).toString())
- .isEqualTo(expectedContent);
- assertThat(Notification.FLAG_ONGOING_EVENT & notification.flags).isEqualTo(0);
- assertThat(Notification.FLAG_NO_CLEAR & notification.flags).isEqualTo(0);
- assertThat(Notification.FLAG_AUTO_CANCEL & notification.flags)
- .isEqualTo(Notification.FLAG_AUTO_CANCEL);
-
- sDevice.openNotification();
- sDevice.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT);
-
- UiObject scroller =
- sDevice.findObject(
- new UiSelector()
- .packageName("com.android.systemui")
- .resourceId("com.android.systemui:id/notification_stack_scroller"));
- assertThat(scroller.exists()).isTrue();
- UiObject notificationCard =
- scroller.getChild(
- new UiSelector()
- .text(getString(R.string.notificationUI_notification_title)));
- assertThat(notificationCard.exists()).isTrue();
-
- notificationCard.click();
- Thread.sleep(LAUNCH_TIMEOUT);
- UiObject title = getPageElement(sDevice, R.string.notificationUI_header_title);
- assertThat(title.exists()).isTrue();
- }
-
@Test
public void testNonEuNotifications_gaUxEnabled() throws InterruptedException {
doReturn(false).when(mMockFlags).isEeaDevice();
@@ -317,9 +214,9 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
doReturn(GA_UX).when(mMockUxStatesManager).getUx();
final String expectedTitle =
- mContext.getString(R.string.notificationUI_notification_ga_title);
+ mContext.getString(R.string.notificationUI_notification_ga_title_v2);
final String expectedContent =
- mContext.getString(R.string.notificationUI_notification_ga_content);
+ mContext.getString(R.string.notificationUI_notification_ga_content_v2);
ConsentNotificationTrigger.showConsentNotification(mContext, false);
Thread.sleep(1000); // wait 1s to make sure that Notification is displayed.
@@ -362,9 +259,9 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
doReturn(false).when(mMockUxStatesManager).getFlag(KEY_NOTIFICATION_DISMISSED_ON_CLICK);
final String expectedTitle =
- mContext.getString(R.string.notificationUI_notification_ga_title_eu);
+ mContext.getString(R.string.notificationUI_notification_ga_title_eu_v2);
final String expectedContent =
- mContext.getString(R.string.notificationUI_notification_ga_content_eu);
+ mContext.getString(R.string.notificationUI_notification_ga_content_eu_v2);
ConsentNotificationTrigger.showConsentNotification(mContext, true);
Thread.sleep(1000); // wait 1s to make sure that Notification is displayed.
@@ -394,11 +291,16 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
.isEqualTo(Notification.FLAG_ONGOING_EVENT);
assertThat(Notification.FLAG_NO_CLEAR & notification.flags)
.isEqualTo(Notification.FLAG_NO_CLEAR);
- assertThat(Notification.FLAG_AUTO_CANCEL & notification.flags).isEqualTo(0);
+ assertThat(Notification.FLAG_AUTO_CANCEL & notification.flags)
+ .isEqualTo(Notification.FLAG_AUTO_CANCEL);
assertThat(notification.actions).isNull();
sDevice.openNotification();
- sDevice.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT);
+ sDevice.wait(
+ Until.hasObject(
+ By.pkg("com.android.systemui")
+ .res("com.android.systemui:id/notification_stack_scroller")),
+ LAUNCH_TIMEOUT);
UiObject scroller =
sDevice.findObject(
@@ -412,7 +314,7 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
UiSelector notificationCardSelector =
new UiSelector()
.textContains(
- getString(R.string.notificationUI_notification_ga_title_eu)
+ getString(R.string.notificationUI_notification_ga_title_eu_v2)
.substring(0, 15));
if (scroller.exists()) {
notificationCard = scroller.getChild(notificationCardSelector);
@@ -424,7 +326,7 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
notificationCard.click();
Thread.sleep(LAUNCH_TIMEOUT);
- assertThat(mNotificationManager.getActiveNotifications()).hasLength(1);
+ assertThat(mNotificationManager.getActiveNotifications()).hasLength(0);
}
@Test
@@ -438,13 +340,12 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
doReturn(GA_UX).when(mMockUxStatesManager).getUx();
doReturn(true).when(mMockUxStatesManager).getFlag(KEY_GA_UX_FEATURE_ENABLED);
- doReturn(false).when(mMockUxStatesManager).getFlag(KEY_EU_NOTIF_FLOW_CHANGE_ENABLED);
doReturn(false).when(mMockUxStatesManager).getFlag(KEY_NOTIFICATION_DISMISSED_ON_CLICK);
final String expectedTitle =
- mContext.getString(R.string.notificationUI_notification_ga_title_eu);
+ mContext.getString(R.string.notificationUI_notification_ga_title_eu_v2);
final String expectedContent =
- mContext.getString(R.string.notificationUI_notification_ga_content_eu);
+ mContext.getString(R.string.notificationUI_notification_ga_content_eu_v2);
ConsentNotificationTrigger.showConsentNotification(mContext, true);
Thread.sleep(1000); // wait 1s to make sure that Notification is displayed.
@@ -473,12 +374,17 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
.isEqualTo(Notification.FLAG_ONGOING_EVENT);
assertThat(Notification.FLAG_NO_CLEAR & notification.flags)
.isEqualTo(Notification.FLAG_NO_CLEAR);
- assertThat(Notification.FLAG_AUTO_CANCEL & notification.flags).isEqualTo(0);
+ assertThat(Notification.FLAG_AUTO_CANCEL & notification.flags)
+ .isEqualTo(Notification.FLAG_AUTO_CANCEL);
assertThat(notification.actions).isNull();
// verify that notification was displayed
sDevice.openNotification();
- sDevice.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT);
+ sDevice.wait(
+ Until.hasObject(
+ By.pkg("com.android.systemui")
+ .res("com.android.systemui:id/notification_stack_scroller")),
+ LAUNCH_TIMEOUT);
UiObject scroller =
sDevice.findObject(
new UiSelector()
@@ -491,7 +397,7 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
UiSelector notificationCardSelector =
new UiSelector()
.textContains(
- getString(R.string.notificationUI_notification_ga_title_eu)
+ getString(R.string.notificationUI_notification_ga_title_eu_v2)
.substring(0, 15));
if (scroller.exists()) {
notificationCard = scroller.getChild(notificationCardSelector);
@@ -504,13 +410,15 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
// click the notification and verify that notification still exists (wasn't dismissed)
notificationCard.click();
Thread.sleep(LAUNCH_TIMEOUT);
- assertThat(mNotificationManager.getActiveNotifications()).hasLength(1);
+ assertThat(mNotificationManager.getActiveNotifications()).hasLength(0);
// go to confirmation page and verify that notification was dismissed
UiObject leftControlButton =
- getPageElement(sDevice, R.string.notificationUI_left_control_button_text_eu);
+ getPageElement(
+ sDevice, R.string.notificationUI_confirmation_left_control_button_text);
UiObject rightControlButton =
- getPageElement(sDevice, R.string.notificationUI_right_control_button_ga_text_eu);
+ getPageElement(
+ sDevice, R.string.notificationUI_confirmation_right_control_button_text);
UiObject moreButton = getPageElement(sDevice, R.string.notificationUI_more_button_text);
verifyControlsAndMoreButtonAreDisplayed(leftControlButton, rightControlButton, moreButton);
Thread.sleep(LAUNCH_TIMEOUT);
@@ -615,7 +523,11 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
.isEqualTo(Notification.FLAG_AUTO_CANCEL);
sDevice.openNotification();
- sDevice.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT);
+ sDevice.wait(
+ Until.hasObject(
+ By.pkg("com.android.systemui")
+ .res("com.android.systemui:id/notification_stack_scroller")),
+ LAUNCH_TIMEOUT);
UiObject scroller =
sDevice.findObject(
@@ -662,13 +574,13 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
final String expectedTitle =
mContext.getString(
isEeaDevice
- ? R.string.notificationUI_notification_ga_title_eu
- : R.string.notificationUI_notification_ga_title);
+ ? R.string.notificationUI_notification_ga_title_eu_v2
+ : R.string.notificationUI_notification_ga_title_v2);
final String expectedContent =
mContext.getString(
isEeaDevice
- ? R.string.notificationUI_notification_ga_content_eu
- : R.string.notificationUI_notification_ga_content);
+ ? R.string.notificationUI_notification_ga_content_eu_v2
+ : R.string.notificationUI_notification_ga_content_v2);
ConsentNotificationTrigger.showConsentNotification(mContext, isEeaDevice);
Thread.sleep(1000); // wait 1s to make sure that Notification is displayed.
@@ -736,7 +648,11 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
.isEqualTo(Notification.FLAG_AUTO_CANCEL);
sDevice.openNotification();
- sDevice.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT);
+ sDevice.wait(
+ Until.hasObject(
+ By.pkg("com.android.systemui")
+ .res("com.android.systemui:id/notification_stack_scroller")),
+ LAUNCH_TIMEOUT);
UiObject scroller =
sDevice.findObject(
@@ -751,9 +667,9 @@ public final class ConsentNotificationTriggerTest extends AdServicesExtendedMock
getString(
isEeaDevice
? R.string
- .notificationUI_notification_ga_title_eu
+ .notificationUI_notification_ga_title_eu_v2
: R.string
- .notificationUI_notification_ga_title)));
+ .notificationUI_notification_ga_title_v2)));
assertThat(notificationCard.exists()).isTrue();
notificationCard.click();
diff --git a/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UiAutomatorTest.java b/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UiAutomatorTest.java
index 06bee04fa..c58676854 100644
--- a/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UiAutomatorTest.java
+++ b/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UiAutomatorTest.java
@@ -15,7 +15,6 @@
*/
package com.android.adservices.ui.notifications;
-import static com.android.adservices.service.FlagsConstants.KEY_EU_NOTIF_FLOW_CHANGE_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_GA_UX_FEATURE_ENABLED;
import static com.google.common.truth.Truth.assertThat;
@@ -73,8 +72,7 @@ public class NotificationActivityGAV2UiAutomatorTest {
public final AdServicesFlagsSetterRule flags =
AdServicesFlagsSetterRule.forGlobalKillSwitchDisabledTests()
.setCompatModeFlags()
- .setFlag(KEY_GA_UX_FEATURE_ENABLED, true)
- .setFlag(KEY_EU_NOTIF_FLOW_CHANGE_ENABLED, true);
+ .setFlag(KEY_GA_UX_FEATURE_ENABLED, true);
@BeforeClass
public static void classSetup() throws InterruptedException {
diff --git a/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UxSelectorUiAutomatorTest.java b/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UxSelectorUiAutomatorTest.java
index ffbb73a66..0fd5f7fea 100644
--- a/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UxSelectorUiAutomatorTest.java
+++ b/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityGAV2UxSelectorUiAutomatorTest.java
@@ -16,7 +16,6 @@
package com.android.adservices.ui.notifications;
import static com.android.adservices.service.FlagsConstants.KEY_ENABLE_AD_SERVICES_SYSTEM_API;
-import static com.android.adservices.service.FlagsConstants.KEY_EU_NOTIF_FLOW_CHANGE_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_GA_UX_FEATURE_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_U18_UX_ENABLED;
@@ -75,8 +74,7 @@ public class NotificationActivityGAV2UxSelectorUiAutomatorTest {
.setCompatModeFlags()
.setFlag(KEY_ENABLE_AD_SERVICES_SYSTEM_API, true)
.setFlag(KEY_GA_UX_FEATURE_ENABLED, true)
- .setFlag(KEY_U18_UX_ENABLED, true)
- .setFlag(KEY_EU_NOTIF_FLOW_CHANGE_ENABLED, true);
+ .setFlag(KEY_U18_UX_ENABLED, true);
@BeforeClass
public static void classSetup() throws InterruptedException {
diff --git a/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityUiAutomatorTest.java b/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityUiAutomatorTest.java
index 261f44282..ce4cc0077 100644
--- a/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityUiAutomatorTest.java
+++ b/adservices/apk/tests/notification/src/com/android/adservices/ui/notifications/NotificationActivityUiAutomatorTest.java
@@ -84,7 +84,6 @@ public final class NotificationActivityUiAutomatorTest extends AdServicesExtende
public void setup() throws UiObjectNotFoundException, IOException {
mContext = spy(appContext.get());
- doReturn(false).when(mMockFlags).getEuNotifFlowChangeEnabled();
doReturn(true).when(mMockFlags).getUIDialogsFeatureEnabled();
doReturn(true).when(mMockFlags).isUiFeatureTypeLoggingEnabled();
doReturn(true).when(mMockFlags).getRecordManualInteractionEnabled();
@@ -113,68 +112,6 @@ public final class NotificationActivityUiAutomatorTest extends AdServicesExtende
AdservicesTestHelper.killAdservicesProcess(mContext);
}
-
- @Test
- @FlakyTest(bugId = 302607350)
- public void moreButtonTest() throws Exception {
- startActivity(true);
- UiObject leftControlButton =
- getElement(R.string.notificationUI_left_control_button_text_eu);
- UiObject rightControlButton =
- getElement(R.string.notificationUI_right_control_button_text_eu);
- UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
- while (moreButton.exists()) {
- moreButton.click();
- Thread.sleep(2000);
- }
- assertThat(leftControlButton.exists()).isTrue();
- assertThat(rightControlButton.exists()).isTrue();
- assertThat(moreButton.exists()).isFalse();
- }
-
- @Test
- public void acceptedConfirmationScreenTest() throws Exception {
- doReturn(false).when(mMockFlags).getGaUxFeatureEnabled();
-
- startActivity(true);
- UiObject leftControlButton =
- getElement(R.string.notificationUI_left_control_button_text_eu);
- UiObject rightControlButton =
- getElement(R.string.notificationUI_right_control_button_text_eu);
- UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
- while (moreButton.exists()) {
- moreButton.click();
- Thread.sleep(2000);
- }
- assertThat(leftControlButton.exists()).isTrue();
- assertThat(rightControlButton.exists()).isTrue();
- assertThat(moreButton.exists()).isFalse();
-
- rightControlButton.click();
- UiObject acceptedTitle = getElement(R.string.notificationUI_confirmation_accept_title);
- assertThat(acceptedTitle.exists()).isTrue();
- }
-
- @Test
- @FlakyTest(bugId = 302607350)
- public void notificationEuGaTest() throws Exception {
- doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
- doReturn("GA_UX").when(mMockFlags).getDebugUx();
-
- startActivity(true);
-
- UiObject notificationEuGaTitle = getElement(R.string.notificationUI_header_ga_title_eu);
- assertThat(notificationEuGaTitle.exists()).isTrue();
-
- UiObject leftControlButton =
- getElement(R.string.notificationUI_left_control_button_text_eu);
- UiObject rightControlButton =
- getElement(R.string.notificationUI_right_control_button_ga_text_eu);
- UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
-
- verifyControlsAndMoreButtonAreDisplayed(leftControlButton, rightControlButton, moreButton);
- }
-
@Test
@FlakyTest(bugId = 302607350)
public void notificationRowGaTest() throws Exception {
@@ -192,59 +129,29 @@ public final class NotificationActivityUiAutomatorTest extends AdServicesExtende
}
@Test
- public void acceptedConfirmationScreenGaTest() throws Exception {
- doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
- doReturn("GA_UX").when(mMockFlags).getDebugUx();
-
- startActivity(true);
-
- UiObject leftControlButton =
- getElement(R.string.notificationUI_left_control_button_text_eu);
- UiObject rightControlButton =
- getElement(R.string.notificationUI_right_control_button_ga_text_eu);
- UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
-
- verifyControlsAndMoreButtonAreDisplayed(leftControlButton, rightControlButton, moreButton);
-
- rightControlButton.click();
-
- UiObject acceptedTitle = getElement(R.string.notificationUI_fledge_measurement_title);
- assertThat(acceptedTitle.exists()).isTrue();
- UiObject leftControlButtonOnSecondPage =
- getElement(R.string.notificationUI_confirmation_left_control_button_text);
- UiObject rightControlButtonOnSecondPage =
- getElement(R.string.notificationUI_confirmation_right_control_button_text);
- UiObject moreButtonOnSecondPage = getElement(R.string.notificationUI_more_button_text);
- verifyControlsAndMoreButtonAreDisplayed(
- leftControlButtonOnSecondPage,
- rightControlButtonOnSecondPage,
- moreButtonOnSecondPage);
- }
-
- @Test
@FlakyTest(bugId = 302607350)
- public void declinedConfirmationScreenGaTest() throws Exception {
+ public void notificationEuGaTest() throws Exception {
doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
doReturn("GA_UX").when(mMockFlags).getDebugUx();
startActivity(true);
UiObject leftControlButton =
- getElement(R.string.notificationUI_left_control_button_text_eu);
+ getElement(R.string.notificationUI_confirmation_left_control_button_text);
UiObject rightControlButton =
- getElement(R.string.notificationUI_right_control_button_ga_text_eu);
+ getElement(R.string.notificationUI_confirmation_right_control_button_text);
UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
verifyControlsAndMoreButtonAreDisplayed(leftControlButton, rightControlButton, moreButton);
- leftControlButton.click();
+ rightControlButton.click();
- UiObject acceptedTitle = getElement(R.string.notificationUI_fledge_measurement_title);
+ UiObject acceptedTitle = getElement(R.string.notificationUI_header_ga_title_eu_v2);
assertThat(acceptedTitle.exists()).isTrue();
UiObject leftControlButtonOnSecondPage =
- getElement(R.string.notificationUI_confirmation_left_control_button_text);
+ getElement(R.string.notificationUI_left_control_button_text_eu_v2);
UiObject rightControlButtonOnSecondPage =
- getElement(R.string.notificationUI_confirmation_right_control_button_text);
+ getElement(R.string.notificationUI_right_control_button_ga_text_eu_v2);
UiObject moreButtonOnSecondPage = getElement(R.string.notificationUI_more_button_text);
verifyControlsAndMoreButtonAreDisplayed(
leftControlButtonOnSecondPage,
diff --git a/adservices/apk/tests/settings/OWNERS b/adservices/apk/tests/settings/OWNERS
index 9530244f7..b0f9f618b 100644
--- a/adservices/apk/tests/settings/OWNERS
+++ b/adservices/apk/tests/settings/OWNERS
@@ -6,3 +6,4 @@ tccyp@google.com
yangwangyw@google.com
albertkong@google.com
bozhaobz@google.com
+ardroid@google.com
diff --git a/adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java b/adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java
index f8ec1d3f6..0df5e26eb 100644
--- a/adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java
+++ b/adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java
@@ -22,21 +22,26 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.Intent;
+import android.os.RemoteException;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
+import com.android.adservices.LogUtil;
import com.android.adservices.api.R;
import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
+import com.android.adservices.common.AdservicesTestHelper;
import com.android.adservices.common.RequiresSdkLevelAtLeastT;
import com.android.adservices.data.topics.Topic;
import com.android.adservices.service.Flags;
@@ -70,10 +75,13 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
private static final String PRIVACY_SANDBOX_TEST_PACKAGE = "android.test.adservices.ui.MAIN";
private static final int LAUNCH_TIMEOUT = 5000;
+ private static final Context sContext = ApplicationProvider.getApplicationContext();
private static UiDevice sDevice;
- @Mock private ConsentManager mConsentManager;
- @Mock private Flags mMockFlags;
+ @Mock
+ private ConsentManager mConsentManager;
+ @Mock
+ private Flags mMockFlags;
@Before
public void setup() throws Exception {
@@ -82,6 +90,7 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
// UiDialogFragmentEnable flag should be on for this test
doReturn(true).when(mMockFlags).getUiDialogFragmentEnabled();
doReturn(true).when(mMockFlags).getUIDialogsFeatureEnabled();
+ doReturn(true).when(mMockFlags).getRecordManualInteractionEnabled();
List<Topic> tempList = new ArrayList<>();
tempList.add(Topic.create(10001, 1, 1));
tempList.add(Topic.create(10002, 1, 1));
@@ -135,15 +144,20 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
doNothing().when(mConsentManager).disable(any(Context.class));
doReturn(GA_UX).when(mConsentManager).getUx();
- startActivityFromHomeAndCheckMainSwitch();
+ try {
+ startActivityFromHomeAndCheckMainSwitch();
+ } catch (RemoteException e) {
+ LogUtil.e("RemoteException from setOrientation.");
+ }
}
- private void startActivityFromHomeAndCheckMainSwitch() {
+ private void startActivityFromHomeAndCheckMainSwitch() throws RemoteException {
// Initialize UiDevice instance
sDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// Start from the home screen
sDevice.pressHome();
+ sDevice.setOrientationNatural();
// Wait for launcher
final String launcherPackage = sDevice.getLauncherPackageName();
@@ -164,12 +178,13 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
@After
public void teardown() {
ApkTestUtil.takeScreenshot(sDevice, getClass().getSimpleName() + "_" + getTestName() + "_");
+ AdservicesTestHelper.killAdservicesProcess(sContext);
}
@Test
- public void optOutDialogTest() throws Exception {
- UiObject consentSwitch = ApkTestUtil.getConsentSwitch(sDevice);
- assertThat(consentSwitch.exists()).isTrue();
+ public void optOutDialogTest() {
+ UiObject2 consentSwitch = ApkTestUtil.getConsentSwitch2(sDevice);
+ assertThat(consentSwitch).isNotNull();
// guarantee in on state
if (!consentSwitch.isChecked()) {
@@ -178,24 +193,28 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
// click switch
consentSwitch.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_title);
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_opt_out_title);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel
negativeText.click();
+ // Retrieve a new instance to avoid android.support.test.uiautomator.StaleObjectException.
+ consentSwitch = ApkTestUtil.getConsentSwitch2(sDevice);
// click switch
consentSwitch.click();
- dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_title);
- UiObject positiveText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_opt_out_title);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_opt_out_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// confirm
positiveText.click();
}
@@ -203,35 +222,37 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
@Test
public void blockTopicDialogTest() throws Exception {
// open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
- UiObject blockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_topic_title, 0);
- assertThat(blockTopicText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_topics_title);
+ UiObject2 blockTopicText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_block_topic_title, 0);
+ assertThat(blockTopicText).isNotNull();
// click block
blockTopicText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_topic_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_block_topic_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_topic_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_topic_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
- verify(mConsentManager).revokeConsentForTopic(any(Topic.class));
- blockTopicText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_topic_title, 0);
- assertThat(blockTopicText.exists()).isTrue();
+ verify(mConsentManager, timeout(1000)).revokeConsentForTopic(any(Topic.class));
+ blockTopicText = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_block_topic_title, 0);
+ assertThat(blockTopicText).isNotNull();
// click block again
blockTopicText.click();
- dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_topic_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_topic_message);
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel and verify it has still only been called once
negativeText.click();
@@ -241,59 +262,62 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
@Test
public void unblockTopicDialogTest() throws Exception {
// open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_topics_title);
// open blocked topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_topics_title);
- UiObject unblockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_topic_title, 0);
- assertThat(unblockTopicText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_blocked_topics_title);
+ UiObject2 unblockTopicText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_unblock_topic_title,
+ 0);
+ assertThat(unblockTopicText).isNotNull();
// click unblock
unblockTopicText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_topic_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_unblock_topic_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext,
sDevice, R.string.settingsUI_dialog_unblock_topic_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
verify(mConsentManager).restoreConsentForTopic(any(Topic.class));
- unblockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_topic_title, 0);
- assertThat(unblockTopicText.exists()).isTrue();
+ unblockTopicText = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_unblock_topic_title, 0);
+ assertThat(unblockTopicText).isNotNull();
}
@Test
public void resetTopicDialogTest() throws Exception {
// open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_topics_title);
// click reset
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_topics_title);
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_topic_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_reset_topic_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_reset_topics_title);
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_topic_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_topic_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
- verify(mConsentManager).resetTopics();
+ verify(mConsentManager, timeout(1000)).resetTopics();
// click reset again
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_topics_title);
- dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_topic_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_reset_topics_title);
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_topic_message);
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel and verify it has still only been called once
negativeText.click();
@@ -305,39 +329,44 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
public void blockAppDialogTest() throws Exception {
// perform a gentle swipe so scroll won't miss the text close to the
// bottom of the current screen.
- UiObject appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_title);
- if(!appsTitle.exists()){
+ UiObject2 appsTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_apps_title);
+ if (appsTitle == null) {
ApkTestUtil.gentleSwipe(sDevice);
}
// open apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title);
- UiObject blockAppText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title, 0);
- assertThat(blockAppText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_apps_title);
+ UiObject2 blockAppText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_block_app_title, 0);
+ assertThat(blockAppText).isNotNull();
// click block
blockAppText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_message);
- UiObject positiveText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_app_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_app_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
- verify(mConsentManager).revokeConsentForApp(any(App.class));
- blockAppText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title, 0);
- assertThat(blockAppText.exists()).isTrue();
+ verify(mConsentManager, timeout(1000)).revokeConsentForApp(any(App.class));
+ blockAppText = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_block_app_title, 0);
+ assertThat(blockAppText).isNotNull();
// click block again
blockAppText.click();
- dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_app_message);
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel and verify it has still only been called once
negativeText.click();
@@ -346,71 +375,78 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
@Test
public void unblockAppDialogTest() throws Exception {
- UiObject appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_title);
- if(!appsTitle.exists()){
+ UiObject2 appsTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_apps_title);
+ if (appsTitle == null) {
ApkTestUtil.gentleSwipe(sDevice);
}
// open apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title);
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_apps_title);
// perform a gentle swipe so scroll won't miss the text close to the
// bottom of the current screen.
ApkTestUtil.gentleSwipe(sDevice);
// open blocked apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_apps_title);
- UiObject unblockAppText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_app_title, 0);
- assertThat(unblockAppText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_blocked_apps_title);
+ UiObject2 unblockAppText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_unblock_app_title, 0);
+ assertThat(unblockAppText).isNotNull();
// click unblock
unblockAppText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_app_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_unblock_app_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_unblock_app_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_unblock_app_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
verify(mConsentManager).restoreConsentForApp(any(App.class));
- unblockAppText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_app_title, 0);
- assertThat(unblockAppText.exists()).isTrue();
+ unblockAppText = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_unblock_app_title, 0);
+ assertThat(unblockAppText).isNotNull();
}
@Test
public void resetAppDialogTest() throws Exception {
- UiObject appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_title);
- if(!appsTitle.exists()){
+ UiObject2 appsTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_apps_title);
+ if (appsTitle != null) {
ApkTestUtil.gentleSwipe(sDevice);
}
// open apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title);
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_apps_title);
// click reset
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_apps_title);
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_message);
- UiObject positiveText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_reset_apps_title);
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_app_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_app_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
- verify(mConsentManager).resetApps();
+ verify(mConsentManager, timeout(1000)).resetApps();
// click reset again
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_apps_title);
- dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_reset_apps_title);
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_app_message);
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel and verify it has still only been called once
negativeText.click();
diff --git a/adservices/apk/tests/settingsgaota/OWNERS b/adservices/apk/tests/settingsgaota/OWNERS
index 9530244f7..b0f9f618b 100644
--- a/adservices/apk/tests/settingsgaota/OWNERS
+++ b/adservices/apk/tests/settingsgaota/OWNERS
@@ -6,3 +6,4 @@ tccyp@google.com
yangwangyw@google.com
albertkong@google.com
bozhaobz@google.com
+ardroid@google.com
diff --git a/adservices/apk/tests/settingsgaota/src/com/android/adservices/ui/settingsga/SettingsActivityUiAutomatorTest.java b/adservices/apk/tests/settingsgaota/src/com/android/adservices/ui/settingsga/SettingsActivityUiAutomatorTest.java
deleted file mode 100644
index 46dd56ef3..000000000
--- a/adservices/apk/tests/settingsgaota/src/com/android/adservices/ui/settingsga/SettingsActivityUiAutomatorTest.java
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
- * 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.ui.settingsga;
-
-import static com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection.BETA_UX;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.FlakyTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject;
-import androidx.test.uiautomator.UiObjectNotFoundException;
-import androidx.test.uiautomator.Until;
-
-import com.android.adservices.api.R;
-import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
-import com.android.adservices.common.AdservicesTestHelper;
-import com.android.adservices.data.topics.Topic;
-import com.android.adservices.service.Flags;
-import com.android.adservices.service.FlagsFactory;
-import com.android.adservices.service.common.BackgroundJobsManager;
-import com.android.adservices.service.consent.AdServicesApiConsent;
-import com.android.adservices.service.consent.AdServicesApiType;
-import com.android.adservices.service.consent.App;
-import com.android.adservices.service.consent.ConsentManager;
-import com.android.adservices.service.ui.data.UxStatesManager;
-import com.android.adservices.ui.util.ApkTestUtil;
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
-import com.android.modules.utils.build.SdkLevel;
-import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic;
-
-import com.google.common.collect.ImmutableList;
-
-import org.junit.After;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-@SpyStatic(FlagsFactory.class)
-@SpyStatic(BackgroundJobsManager.class)
-@SpyStatic(ConsentManager.class)
-@SpyStatic(UxStatesManager.class)
-@RunWith(AndroidJUnit4.class)
-public final class SettingsActivityUiAutomatorTest extends AdServicesExtendedMockitoTestCase {
-
- private static final String PRIVACY_SANDBOX_TEST_PACKAGE = "android.test.adservices.ui.MAIN";
- private static final int LAUNCH_TIMEOUT = 5_000;
-
- private static UiDevice sDevice;
-
- private String mTestName;
- private ConsentManager mConsentManager;
- @Mock private Flags mMockFlags;
- @Mock private UxStatesManager mUxStatesManager;
-
- @Before
- public void setup() throws UiObjectNotFoundException, IOException {
- Assume.assumeTrue(SdkLevel.isAtLeastS());
-
- // Mock static method FlagsFactory.getFlags() to return Mock Flags.
- ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags);
- doReturn(false).when(mMockFlags).getUiDialogFragmentEnabled();
- doReturn(true).when(mMockFlags).getUIDialogsFeatureEnabled();
- // prepare objects used by static mocking
- mConsentManager = mock(ConsentManager.class);
- List<Topic> tempList = new ArrayList<>();
- tempList.add(Topic.create(10001, 1, 1));
- tempList.add(Topic.create(10002, 1, 1));
- tempList.add(Topic.create(10003, 1, 1));
- ImmutableList<Topic> topicsList = ImmutableList.copyOf(tempList);
- doReturn(topicsList).when(mConsentManager).getKnownTopicsWithConsent();
-
- tempList = new ArrayList<>();
- tempList.add(Topic.create(10004, 1, 1));
- tempList.add(Topic.create(10005, 1, 1));
- ImmutableList<Topic> blockedTopicsList = ImmutableList.copyOf(tempList);
- doReturn(blockedTopicsList).when(mConsentManager).getTopicsWithRevokedConsent();
-
- List<App> appTempList = new ArrayList<>();
- appTempList.add(App.create("app1"));
- appTempList.add(App.create("app2"));
- ImmutableList<App> appsList = ImmutableList.copyOf(appTempList);
- doReturn(appsList).when(mConsentManager).getKnownAppsWithConsent();
-
- appTempList = new ArrayList<>();
- appTempList.add(App.create("app3"));
- ImmutableList<App> blockedAppsList = ImmutableList.copyOf(appTempList);
- doReturn(blockedAppsList).when(mConsentManager).getAppsWithRevokedConsent();
-
- doNothing().when(mConsentManager).resetTopicsAndBlockedTopics();
- doNothing().when(mConsentManager).resetTopics();
- doNothing().when(mConsentManager).revokeConsentForTopic(any(Topic.class));
- doNothing().when(mConsentManager).restoreConsentForTopic(any(Topic.class));
- try {
- doNothing().when(mConsentManager).resetAppsAndBlockedApps();
- doNothing().when(mConsentManager).resetApps();
- doNothing().when(mConsentManager).revokeConsentForApp(any(App.class));
- doNothing().when(mConsentManager).restoreConsentForApp(any(App.class));
- } catch (IOException e) {
- e.printStackTrace();
- }
- doNothing().when(mConsentManager).resetMeasurement();
-
- ExtendedMockito.doNothing()
- .when(() -> BackgroundJobsManager.scheduleAllBackgroundJobs(any(Context.class)));
- ExtendedMockito.doReturn(mConsentManager)
- .when(() -> ConsentManager.getInstance(any(Context.class)));
- doReturn(AdServicesApiConsent.GIVEN).when(mConsentManager).getConsent();
- doReturn(AdServicesApiConsent.GIVEN)
- .when(mConsentManager)
- .getConsent(AdServicesApiType.TOPICS);
- doReturn(AdServicesApiConsent.GIVEN)
- .when(mConsentManager)
- .getConsent(AdServicesApiType.FLEDGE);
- doReturn(AdServicesApiConsent.GIVEN)
- .when(mConsentManager)
- .getConsent(AdServicesApiType.MEASUREMENTS);
-
- doNothing().when(mConsentManager).enable(any(Context.class));
- doNothing().when(mConsentManager).disable(any(Context.class));
-
- // Mock BETA_UX for testing.
- ExtendedMockito.doReturn(mUxStatesManager)
- .when(() -> UxStatesManager.getInstance(any(Context.class)));
- doReturn(false).when(mMockFlags).getConsentNotificationActivityDebugMode();
- doReturn(BETA_UX).when(mUxStatesManager).getUx();
- doReturn(BETA_UX).when(mConsentManager).getUx();
-
- startActivityFromHomeAndCheckMainSwitch();
- }
-
- private void startActivityFromHomeAndCheckMainSwitch() throws UiObjectNotFoundException {
- // Initialize UiDevice instance
- sDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-
- // Start from the home screen
- sDevice.pressHome();
-
- // Wait for launcher
- final String launcherPackage = sDevice.getLauncherPackageName();
- assertThat(launcherPackage).isNotNull();
- sDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
-
- // launch app
- Context context = ApplicationProvider.getApplicationContext();
- Intent intent = new Intent(PRIVACY_SANDBOX_TEST_PACKAGE);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
-
- // Wait for the app to appear
- sDevice.wait(
- Until.hasObject(By.pkg(PRIVACY_SANDBOX_TEST_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
- }
-
- @After
- public void teardown() {
- ApkTestUtil.takeScreenshot(sDevice, getClass().getSimpleName() + "_" + mTestName + "_");
-
- AdservicesTestHelper.killAdservicesProcess(ApplicationProvider.getApplicationContext());
- }
-
- @Test
- public void optOutDialogTest() throws UiObjectNotFoundException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
-
- UiObject consentSwitch = ApkTestUtil.getConsentSwitch(sDevice);
- assertThat(consentSwitch.exists()).isTrue();
-
- // click switch
- consentSwitch.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_title);
- UiObject positiveText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
-
- // confirm
- positiveText.click();
-
- // click switch
- consentSwitch.click();
- dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_title);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
-
- // cancel
- negativeText.click();
- }
-
- @Test
- public void blockTopicDialogTest() throws UiObjectNotFoundException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
- // open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
- UiObject blockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_topic_title, 0);
- assertThat(blockTopicText.exists()).isTrue();
-
- // click block
- blockTopicText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_topic_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_block_topic_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
-
- // confirm
- positiveText.click();
- verify(mConsentManager).revokeConsentForTopic(any(Topic.class));
- blockTopicText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_topic_title, 0);
- assertThat(blockTopicText.exists()).isTrue();
-
- // click block again
- blockTopicText.click();
- dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_topic_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
-
- // cancel and verify it has still only been called once
- negativeText.click();
- verify(mConsentManager).revokeConsentForTopic(any(Topic.class));
- }
-
- @Test
- public void unblockTopicDialogTest() throws UiObjectNotFoundException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
- // open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
-
- // open blocked topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_topics_title);
- UiObject unblockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_topic_title, 0);
- assertThat(unblockTopicText.exists()).isTrue();
-
- // click unblock
- unblockTopicText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_topic_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_unblock_topic_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
-
- // confirm
- positiveText.click();
- verify(mConsentManager).restoreConsentForTopic(any(Topic.class));
- unblockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_topic_title, 0);
- assertThat(unblockTopicText.exists()).isTrue();
- }
-
- @Test
- public void resetMeasurementDialogTest() throws UiObjectNotFoundException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
- doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
-
- startActivityFromHomeAndCheckMainSwitch();
- // open measurement view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_measurement_view_title);
-
- // click reset
- clickResetBtn();
-
- // click reset again
- clickResetBtn();
-
- verify(mConsentManager, times(2)).resetMeasurement();
- }
-
- @Test
- public void resetTopicDialogTest() throws UiObjectNotFoundException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
- // open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
-
- // click reset
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_topics_title);
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_topic_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_reset_topic_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
-
- // confirm
- positiveText.click();
- verify(mConsentManager).resetTopics();
-
- // click reset again
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_topics_title);
- dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_topic_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
-
- // cancel and verify it has still only been called once
- negativeText.click();
- verify(mConsentManager).resetTopics();
- }
-
- @Test
- public void blockAppDialogTest() throws UiObjectNotFoundException, IOException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
-
- UiObject appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_title);
- if (!appsTitle.exists()) {
- ApkTestUtil.gentleSwipe(sDevice);
- }
-
- // open apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title);
- UiObject blockAppText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title, 0);
- assertThat(blockAppText.exists()).isTrue();
-
- // click block
- blockAppText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_message);
- UiObject positiveText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
-
- // confirm
- positiveText.click();
- verify(mConsentManager).revokeConsentForApp(any(App.class));
- blockAppText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title, 0);
- assertThat(blockAppText.exists()).isTrue();
-
- // click block again
- blockAppText.click();
- dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
-
- // cancel and verify it has still only been called once
- negativeText.click();
- verify(mConsentManager).revokeConsentForApp(any(App.class));
- }
-
- @Test
- public void unblockAppDialogTest() throws UiObjectNotFoundException, IOException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
-
- UiObject appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_title);
- if (!appsTitle.exists()) {
- ApkTestUtil.gentleSwipe(sDevice);
- }
-
- // open apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title);
-
- // perform a gentle swipe so scroll won't miss the text close to the
- // bottom of the current screen.
- ApkTestUtil.gentleSwipe(sDevice);
-
- // open blocked apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_apps_title);
- UiObject unblockAppText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_app_title, 0);
- assertThat(unblockAppText.exists()).isTrue();
-
- // click unblock
- unblockAppText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_app_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_unblock_app_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
-
- // confirm
- positiveText.click();
- verify(mConsentManager).restoreConsentForApp(any(App.class));
- unblockAppText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_app_title, 0);
- assertThat(unblockAppText.exists()).isTrue();
- }
-
- @Test
- public void resetAppDialogTest() throws UiObjectNotFoundException, IOException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
-
- // perform a gentle swipe so scroll won't miss the text close to the
- // bottom of the current screen.
- UiObject appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_title);
- if (!appsTitle.exists()) {
- ApkTestUtil.gentleSwipe(sDevice);
- }
-
- // open apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title);
-
- // click reset
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_apps_title);
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_message);
- UiObject positiveText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
-
- // confirm
- positiveText.click();
- verify(mConsentManager).resetApps();
-
- // click reset again
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_apps_title);
- dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
-
- // cancel and verify it has still only been called once
- negativeText.click();
- verify(mConsentManager).resetApps();
- }
-
- @Test
- public void disableMeasurementTest() throws UiObjectNotFoundException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
-
- doReturn(false).when(mMockFlags).getGaUxFeatureEnabled();
- // start the activity again to reflect the GaUxFeature flag change
- startActivityFromHomeAndCheckMainSwitch();
- // the entry point of ads measurement should be hidden
- UiObject adsMeasurementTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_measurement_view_title);
- assertThat(adsMeasurementTitle.exists()).isFalse();
- }
-
- @Test
- @FlakyTest(bugId = 295896410, detail = "UX test time out in presubmit")
- public void disableDialogFeatureTest() throws UiObjectNotFoundException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
-
- doReturn(false).when(mMockFlags).getUIDialogsFeatureEnabled();
-
- UiObject consentSwitch = ApkTestUtil.getConsentSwitch(sDevice);
- assertThat(consentSwitch.exists()).isTrue();
-
- // click switch
- consentSwitch.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_title);
- assertThat(dialogTitle.exists()).isFalse();
-
- // open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
- UiObject blockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_topic_title, 0);
- assertThat(blockTopicText.exists()).isTrue();
-
- // block topic
- blockTopicText.click();
- dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_topic_message);
- assertThat(dialogTitle.exists()).isFalse();
- verify(mConsentManager).revokeConsentForTopic(any(Topic.class));
-
- // reset topic
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_topics_title);
- dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_topic_message);
- assertThat(dialogTitle.exists()).isFalse();
- verify(mConsentManager).resetTopics();
-
- // open unblock topic view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_topics_title);
- UiObject unblockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_topic_title, 0);
- assertThat(unblockTopicText.exists()).isTrue();
-
- // click unblock
- unblockTopicText.click();
- dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_topic_message);
- assertThat(dialogTitle.exists()).isFalse();
- verify(mConsentManager).restoreConsentForTopic(any(Topic.class));
- }
-
- /**
- * Test for the Button to show blocked topics when the list of Topics is Empty The Button should
- * be disabled if blocked topics is empty
- */
- @Test
- public void blockedTopicsWhenEmptyStateButtonTest() throws UiObjectNotFoundException {
- // Topics UI is not available on R
- Assume.assumeTrue(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S);
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
-
- // Return an empty topics list
- doReturn(ImmutableList.of()).when(mConsentManager).getKnownTopicsWithConsent();
- // Return a non-empty blocked topics list
- List<Topic> tempList = new ArrayList<>();
- tempList.add(Topic.create(10004, 1, 1));
- tempList.add(Topic.create(10005, 1, 1));
- ImmutableList<Topic> blockedTopicsList = ImmutableList.copyOf(tempList);
- doReturn(blockedTopicsList).when(mConsentManager).getTopicsWithRevokedConsent();
- // navigate to topics page
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
- UiObject blockedTopicsWhenEmptyStateButton =
- ApkTestUtil.scrollTo(sDevice, R.string.settingsUI_blocked_topics_title);
- assertThat(blockedTopicsWhenEmptyStateButton.isEnabled()).isTrue();
- }
-
- public void clickResetBtn() throws UiObjectNotFoundException {
- // R Msmt UI is not scrollable
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
- ApkTestUtil.click(
- sDevice,
- com.android.adservices.api.R.string.settingsUI_measurement_view_reset_title);
- } else {
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_measurement_view_reset_title);
- }
- }
-}
diff --git a/adservices/apk/tests/settingsgaota/src/com/android/adservices/ui/settingsga/SettingsGaUiAutomatorTest.java b/adservices/apk/tests/settingsgaota/src/com/android/adservices/ui/settingsga/SettingsGaUiAutomatorTest.java
index 3b3b5f406..5848168b1 100644
--- a/adservices/apk/tests/settingsgaota/src/com/android/adservices/ui/settingsga/SettingsGaUiAutomatorTest.java
+++ b/adservices/apk/tests/settingsgaota/src/com/android/adservices/ui/settingsga/SettingsGaUiAutomatorTest.java
@@ -69,14 +69,14 @@ public class SettingsGaUiAutomatorTest {
.setFlag(KEY_ENABLE_AD_SERVICES_SYSTEM_API, false);
@Before
- public void setup() {
+ public void setup() throws RemoteException {
Assume.assumeTrue(SdkLevel.isAtLeastS());
// Initialize UiDevice instance
sDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// Start from the home screen
sDevice.pressHome();
-
+ sDevice.setOrientationNatural();
// Wait for launcher
final String launcherPackage = sDevice.getLauncherPackageName();
assertThat(launcherPackage).isNotNull();
@@ -86,65 +86,10 @@ public class SettingsGaUiAutomatorTest {
@After
public void teardown() {
ApkTestUtil.takeScreenshot(sDevice, getClass().getSimpleName() + "_" + mTestName + "_");
-
AdservicesTestHelper.killAdservicesProcess(sContext);
}
@Test
- public void mainPageGaUxFlagEnableToDisableFlipTest() throws UiObjectNotFoundException {
- mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
- ShellUtils.runShellCommand("device_config put adservices ga_ux_enabled true");
-
- ApkTestUtil.launchSettingView(sContext, sDevice, LAUNCH_TIMEOUT);
- // beta switch shouldn't exist
- UiObject mainSwitch =
- sDevice.findObject(new UiSelector().className("android.widget.Switch"));
- mainSwitch.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
- assertThat(mainSwitch.exists()).isFalse();
-
- // make sure all the GA elements are there
- scrollTo(R.string.settingsUI_topics_ga_title);
- UiObject topicsButton =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_topics_ga_title);
- topicsButton.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
- assertThat(topicsButton.exists()).isTrue();
-
- scrollTo(R.string.settingsUI_apps_ga_title);
- UiObject appButton = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_ga_title);
- appButton.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
- assertThat(appButton.exists()).isTrue();
-
- scrollTo(R.string.settingsUI_measurement_view_title);
- UiObject measurementButton =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_measurement_view_title);
- appButton.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
- assertThat(measurementButton.exists()).isTrue();
-
- sDevice.pressHome();
- ShellUtils.runShellCommand("device_config put adservices ga_ux_enabled false");
-
- ApkTestUtil.launchSettingView(sContext, sDevice, LAUNCH_TIMEOUT);
- // beta switch should exist
- mainSwitch = sDevice.findObject(new UiSelector().className("android.widget.Switch"));
- mainSwitch.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
- assertThat(mainSwitch.exists()).isTrue();
-
- // make sure all the GA elements are gone
- topicsButton = ApkTestUtil.getElement(sDevice, R.string.settingsUI_topics_ga_title);
- topicsButton.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
- assertThat(topicsButton.exists()).isFalse();
-
- appButton = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_ga_title);
- appButton.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
- assertThat(appButton.exists()).isFalse();
-
- measurementButton =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_measurement_view_title);
- measurementButton.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
- assertThat(measurementButton.exists()).isFalse();
- }
-
- @Test
public void mainPageGaUxFlagDisableToEnableFlipTest() throws UiObjectNotFoundException {
mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
ShellUtils.runShellCommand("device_config put adservices ga_ux_enabled false");
@@ -291,9 +236,6 @@ public class SettingsGaUiAutomatorTest {
// 3) check if Topics API is enabled
ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_ga_title);
sDevice.waitForIdle();
- // rotate device to test rotating as well
- sDevice.setOrientationLeft();
- sDevice.setOrientationNatural();
topicsToggle = sDevice.findObject(new UiSelector().className("android.widget.Switch"));
topicsToggle.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
assertThat(topicsToggle.isChecked()).isTrue();
@@ -335,9 +277,7 @@ public class SettingsGaUiAutomatorTest {
// 3) check if Fledge API is enabled
ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_ga_title);
sDevice.waitForIdle();
- // rotate device to test rotating as well
- sDevice.setOrientationLeft();
- sDevice.setOrientationNatural();
+
fledgeToggle = sDevice.findObject(new UiSelector().className("android.widget.Switch"));
fledgeToggle.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
assertThat(fledgeToggle.isChecked()).isTrue();
@@ -379,9 +319,7 @@ public class SettingsGaUiAutomatorTest {
// 3) check if Measurement API is enabled
ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_measurement_view_title);
sDevice.waitForIdle();
- // rotate device to test rotating as well
- sDevice.setOrientationLeft();
- sDevice.setOrientationNatural();
+
measurementToggle = sDevice.findObject(new UiSelector().className("android.widget.Switch"));
measurementToggle.waitForExists(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT);
assertThat(measurementToggle.isChecked()).isTrue();
@@ -453,10 +391,6 @@ public class SettingsGaUiAutomatorTest {
ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_title);
assertThat(dialogTitle.exists()).isTrue();
-
- sDevice.setOrientationRight();
- assertThat(dialogTitle.exists()).isTrue();
- sDevice.setOrientationNatural();
}
@Test
diff --git a/adservices/apk/tests/settingsgauxselector/OWNERS b/adservices/apk/tests/settingsgauxselector/OWNERS
index 4559e4fb5..b0f9f618b 100644
--- a/adservices/apk/tests/settingsgauxselector/OWNERS
+++ b/adservices/apk/tests/settingsgauxselector/OWNERS
@@ -6,4 +6,4 @@ tccyp@google.com
yangwangyw@google.com
albertkong@google.com
bozhaobz@google.com
-
+ardroid@google.com
diff --git a/adservices/apk/tests/settingsgauxselector/src/com/android/adservices/ui/settingsga/SettingsRvcUxSelectorUiAutomatorTest.java b/adservices/apk/tests/settingsgauxselector/src/com/android/adservices/ui/settingsga/SettingsRvcUxSelectorUiAutomatorTest.java
index 352a1dcee..e8cbe676b 100644
--- a/adservices/apk/tests/settingsgauxselector/src/com/android/adservices/ui/settingsga/SettingsRvcUxSelectorUiAutomatorTest.java
+++ b/adservices/apk/tests/settingsgauxselector/src/com/android/adservices/ui/settingsga/SettingsRvcUxSelectorUiAutomatorTest.java
@@ -19,7 +19,7 @@ import static com.android.adservices.service.FlagsConstants.KEY_CONSENT_NOTIFICA
import static com.android.adservices.service.FlagsConstants.KEY_DEBUG_UX;
import static com.android.adservices.service.FlagsConstants.KEY_ENABLE_AD_SERVICES_SYSTEM_API;
import static com.android.adservices.service.FlagsConstants.KEY_GA_UX_FEATURE_ENABLED;
-import static com.android.adservices.service.FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED;
+import static com.android.adservices.service.FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_RVC_UX_ENABLED;
import static com.google.common.truth.Truth.assertThat;
@@ -71,7 +71,7 @@ public class SettingsRvcUxSelectorUiAutomatorTest {
.setFlag(KEY_ENABLE_AD_SERVICES_SYSTEM_API, true)
.setFlag(KEY_CONSENT_NOTIFICATION_ACTIVITY_DEBUG_MODE, true)
.setFlag(KEY_RVC_UX_ENABLED, true)
- .setFlag(KEY_RVC_NOTIFICATION_ENABLED, true)
+ .setFlag(KEY_RVC_POST_OTA_NOTIFICATION_ENABLED, true)
.setFlag(KEY_GA_UX_FEATURE_ENABLED, true)
.setFlag(KEY_DEBUG_UX, "RVC_UX")
.setCompatModeFlags();
diff --git a/adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java b/adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java
index e90cb8895..bc18c4e0f 100644
--- a/adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java
+++ b/adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java
@@ -16,17 +16,22 @@
package com.android.adservices.ui.util;
+import static com.google.common.truth.Truth.assertThat;
+
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.graphics.Point;
import android.net.Uri;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiScrollable;
import androidx.test.uiautomator.UiSelector;
@@ -40,12 +45,16 @@ import java.io.File;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
+import java.util.List;
import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
/** Util class for APK tests. */
public class ApkTestUtil {
private static final String PRIVACY_SANDBOX_UI = "android.adservices.ui.SETTINGS";
+ private static final String ANDROID_WIDGET_SCROLLVIEW = "android.widget.ScrollView";
private static final int WINDOW_LAUNCH_TIMEOUT = 1000;
private static final int SCROLL_TIMEOUT = 500;
public static final int PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS = 1000;
@@ -80,6 +89,23 @@ public class ApkTestUtil {
return consentSwitch;
}
+ public static UiObject2 getConsentSwitch2(UiDevice device) {
+ UiObject2 consentSwitch =
+ device.wait(
+ Until.findObject(By.clazz("android.widget.Switch")),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ // Swipe the screen by the width of the toggle so it's not blocked by the nav bar on AOSP
+ // devices.
+ device.swipe(
+ consentSwitch.getVisibleBounds().centerX(),
+ 500,
+ consentSwitch.getVisibleBounds().centerX(),
+ 0,
+ 100);
+
+ return consentSwitch;
+ }
+
/** Returns the UiObject corresponding to a resource ID. */
public static UiObject getElement(UiDevice device, int resId) {
UiObject obj = device.findObject(new UiSelector().text(getString(resId)));
@@ -95,6 +121,11 @@ public class ApkTestUtil {
return ApplicationProvider.getApplicationContext().getResources().getString(resourceId);
}
+ /** Returns the string corresponding to a resource ID. */
+ public static String getString(Context context, int resourceId) {
+ return context.getResources().getString(resourceId);
+ }
+
/** Click the top left of the UiObject corresponding to a resource ID after scrolling. */
public static void scrollToAndClick(UiDevice device, int resId)
throws UiObjectNotFoundException {
@@ -103,18 +134,29 @@ public class ApkTestUtil {
obj.clickTopLeft();
}
+ public static void scrollToAndClick(Context context, UiDevice device, int resId)
+ throws InterruptedException {
+ UiObject2 obj = scrollTo(context, device, resId);
+ clickTopLeft(obj);
+ }
+
public static void click(UiDevice device, int resId) throws UiObjectNotFoundException {
UiObject obj = device.findObject(new UiSelector().text(getString(resId)));
// objects may be partially hidden by the status bar and nav bars.
obj.clickTopLeft();
}
- public static void gentleSwipe(UiDevice device) throws UiObjectNotFoundException {
- UiScrollable scrollView =
- new UiScrollable(
- new UiSelector().scrollable(true).className("android.widget.ScrollView"));
+ public static void clickTopLeft(UiObject2 obj) {
+ assertThat(obj).isNotNull();
+ obj.click(new Point(obj.getVisibleBounds().top, obj.getVisibleBounds().left));
+ }
- scrollView.scrollForward(100);
+ public static void gentleSwipe(UiDevice device) {
+ device.waitForWindowUpdate(null, WINDOW_LAUNCH_TIMEOUT);
+ UiObject2 scrollView = device.wait(
+ Until.findObject(By.scrollable(true).clazz(ANDROID_WIDGET_SCROLLVIEW)),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ scrollView.scroll(Direction.DOWN, /* percent */ 0.25F);
}
/** Returns the UiObject corresponding to a resource ID after scrolling. */
@@ -128,11 +170,26 @@ public class ApkTestUtil {
try {
Thread.sleep(SCROLL_TIMEOUT);
} catch (InterruptedException e) {
- LogUtil.e("InterruptedException:", e.getMessage());
+ LogUtil.e("InterruptedException: %s", e.getMessage());
}
return obj;
}
+ public static UiObject2 scrollTo(Context context, UiDevice device, int resId) {
+ device.waitForWindowUpdate(null, WINDOW_LAUNCH_TIMEOUT);
+ UiObject2 scrollView = device.wait(
+ Until.findObject(By.scrollable(true).clazz(ANDROID_WIDGET_SCROLLVIEW)),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ String targetStr = getString(context, resId);
+ scrollView.scrollUntil(
+ Direction.DOWN,
+ Until.findObject(By.text(Pattern.compile(targetStr, Pattern.CASE_INSENSITIVE))));
+ scrollView.scrollUntil(
+ Direction.UP,
+ Until.findObject(By.text(Pattern.compile(targetStr, Pattern.CASE_INSENSITIVE))));
+ return getElement(context, device, resId);
+ }
+
/** Returns the string corresponding to a resource ID and index. */
public static UiObject getElement(UiDevice device, int resId, int index) {
UiObject obj = device.findObject(new UiSelector().text(getString(resId)).instance(index));
@@ -145,6 +202,34 @@ public class ApkTestUtil {
}
/** Returns the UiObject corresponding to a resource ID. */
+ public static UiObject2 getElement(Context context, UiDevice device, int resId) {
+ String targetStr = getString(context, resId);
+ UiObject2 obj =
+ device.wait(
+ Until.findObject(By.text(targetStr)),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ if (obj == null) {
+ obj = device.findObject(By.text(targetStr.toUpperCase(Locale.getDefault())));
+ }
+ return obj;
+ }
+
+ /** Returns the string corresponding to a resource ID and index. */
+ public static UiObject2 getElement(Context context, UiDevice device, int resId, int index) {
+ String targetStr = getString(context, resId);
+ List<UiObject2> objs =
+ device.wait(
+ Until.findObjects(By.text(targetStr)),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ if (objs == null) {
+ return device.wait(
+ Until.findObjects(By.text(targetStr.toUpperCase(Locale.getDefault()))),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS).get(index);
+ }
+ return objs.get(index);
+ }
+
+ /** Returns the UiObject corresponding to a resource ID. */
public static UiObject getPageElement(UiDevice device, int resId) {
return device.findObject(new UiSelector().text(getString(resId)));
}
diff --git a/adservices/apk/unittest/src/com/android/adservices/topics/TopicsServiceTest.java b/adservices/apk/unittest/src/com/android/adservices/topics/TopicsServiceTest.java
index e1f4abb44..e3c0b1c50 100644
--- a/adservices/apk/unittest/src/com/android/adservices/topics/TopicsServiceTest.java
+++ b/adservices/apk/unittest/src/com/android/adservices/topics/TopicsServiceTest.java
@@ -30,6 +30,7 @@ import android.os.IBinder;
import androidx.test.core.app.ApplicationProvider;
+import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.download.MddJobService;
import com.android.adservices.service.Flags;
@@ -45,56 +46,40 @@ import com.android.adservices.service.stats.AdServicesLoggerImpl;
import com.android.adservices.service.topics.EpochJobService;
import com.android.adservices.service.topics.TopicsWorker;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic;
-import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
import java.util.function.Supplier;
/** Unit test for {@link com.android.adservices.topics.TopicsService}. */
-public class TopicsServiceTest {
- @SuppressWarnings("unused")
- private static final String TAG = "TopicsServiceTest";
-
- @Mock TopicsWorker mMockTopicsWorker;
- @Mock ConsentManager mMockConsentManager;
- @Mock EnrollmentDao mMockEnrollmentDao;
- @Mock AppImportanceFilter mMockAppImportanceFilter;
- @Mock Flags mMockFlags;
- @Mock AdServicesApiConsent mMockAdServicesApiConsent;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- }
+@SpyStatic(FlagsFactory.class)
+@SpyStatic(TopicsWorker.class)
+@SpyStatic(ConsentManager.class)
+@SpyStatic(AdServicesLoggerImpl.class)
+@SpyStatic(MaintenanceJobService.class)
+@SpyStatic(EncryptionKeyJobService.class)
+@SpyStatic(EpochJobService.class)
+@SpyStatic(MddJobService.class)
+@SpyStatic(EnrollmentDao.class)
+@SpyStatic(AppImportanceFilter.class)
+@SpyStatic(PackageChangedReceiver.class)
+public final class TopicsServiceTest extends AdServicesExtendedMockitoTestCase {
+
+ @Mock private TopicsWorker mMockTopicsWorker;
+ @Mock private ConsentManager mMockConsentManager;
+ @Mock private EnrollmentDao mMockEnrollmentDao;
+ @Mock private AppImportanceFilter mMockAppImportanceFilter;
+ @Mock private Flags mMockFlags;
+ @Mock private AdServicesApiConsent mMockAdServicesApiConsent;
@Test
public void testBindableTopicsService_killswitchOff() {
- // Start a mockitoSession to mock static method
- MockitoSession session =
- ExtendedMockito.mockitoSession()
- .spyStatic(FlagsFactory.class)
- .spyStatic(TopicsWorker.class)
- .spyStatic(ConsentManager.class)
- .spyStatic(AdServicesLoggerImpl.class)
- .spyStatic(MaintenanceJobService.class)
- .spyStatic(EncryptionKeyJobService.class)
- .spyStatic(EpochJobService.class)
- .spyStatic(MddJobService.class)
- .spyStatic(EnrollmentDao.class)
- .spyStatic(AppImportanceFilter.class)
- .spyStatic(PackageChangedReceiver.class)
- .startMocking();
-
- try {
// Killswitch is off.
doReturn(false).when(mMockFlags).getTopicsKillSwitch();
- // Mock static method FlagsFactory.getFlags() to return Mock Flags.
- ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags);
+ extendedMockito.mockGetFlags(mMockFlags);
ExtendedMockito.doReturn(mMockTopicsWorker)
.when(() -> TopicsWorker.getInstance(any(Context.class)));
@@ -135,31 +120,19 @@ public class TopicsServiceTest {
spyTopicsService.onCreate();
IBinder binder = spyTopicsService.onBind(getIntentForTopicsService());
assertNotNull(binder);
- } finally {
- session.finishMocking();
- }
}
@Test
public void testBindableTopicsService_killswitchOn() {
- // Start a mockitoSession to mock static method
- MockitoSession session =
- ExtendedMockito.mockitoSession().spyStatic(FlagsFactory.class).startMocking();
-
- try {
// Killswitch is on.
doReturn(true).when(mMockFlags).getTopicsKillSwitch();
- // Mock static method FlagsFactory.getFlags() to return Mock Flags.
- ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags);
+ extendedMockito.mockGetFlags(mMockFlags);
TopicsService topicsService = new TopicsService();
topicsService.onCreate();
IBinder binder = topicsService.onBind(getIntentForTopicsService());
assertNull(binder);
- } finally {
- session.finishMocking();
- }
}
/**
@@ -168,28 +141,10 @@ public class TopicsServiceTest {
*/
@Test
public void testBindableTopicsService_killswitchOffGaUxFeatureFlagOn() {
- // Start a mockitoSession to mock static method
- MockitoSession session =
- ExtendedMockito.mockitoSession()
- .spyStatic(FlagsFactory.class)
- .spyStatic(TopicsWorker.class)
- .spyStatic(ConsentManager.class)
- .spyStatic(AdServicesLoggerImpl.class)
- .spyStatic(MaintenanceJobService.class)
- .spyStatic(EncryptionKeyJobService.class)
- .spyStatic(EpochJobService.class)
- .spyStatic(MddJobService.class)
- .spyStatic(EnrollmentDao.class)
- .spyStatic(AppImportanceFilter.class)
- .spyStatic(PackageChangedReceiver.class)
- .startMocking();
-
- try {
// Killswitch is off.
doReturn(false).when(mMockFlags).getTopicsKillSwitch();
- // Mock static method FlagsFactory.getFlags() to return Mock Flags.
- ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags);
+ extendedMockito.mockGetFlags(mMockFlags);
ExtendedMockito.doReturn(mMockTopicsWorker)
.when(() -> TopicsWorker.getInstance(any(Context.class)));
@@ -231,9 +186,6 @@ public class TopicsServiceTest {
IBinder binder = spyTopicsService.onBind(getIntentForTopicsService());
assertNotNull(binder);
verifyMethodExecutionOnUserConsentGiven();
- } finally {
- session.finishMocking();
- }
}
private Intent getIntentForTopicsService() {
diff --git a/adservices/clients/java/android/adservices/clients/measurement/MeasurementClient.java b/adservices/clients/java/android/adservices/clients/measurement/MeasurementClient.java
index 639ffd38d..a70270de6 100644
--- a/adservices/clients/java/android/adservices/clients/measurement/MeasurementClient.java
+++ b/adservices/clients/java/android/adservices/clients/measurement/MeasurementClient.java
@@ -16,7 +16,6 @@
package android.adservices.clients.measurement;
-import android.adservices.common.AdServicesOutcomeReceiver;
import android.adservices.measurement.DeletionRequest;
import android.adservices.measurement.MeasurementManager;
import android.adservices.measurement.WebSourceRegistrationRequest;
@@ -58,20 +57,82 @@ public class MeasurementClient {
@NonNull
public ListenableFuture<Void> registerSource(
@NonNull Uri attributionSource, @Nullable InputEvent inputEvent) {
+ Objects.requireNonNull(attributionSource);
+
+ return Build.VERSION.SDK_INT > Build.VERSION_CODES.R
+ ? registerSourceForSPlus(attributionSource, inputEvent)
+ : registerSourceForR(attributionSource, inputEvent);
+ }
+
+ /**
+ * Invokes the {@code registerTrigger} method of {@link MeasurementManager}, and returns a Void
+ * future.
+ */
+ @NonNull
+ public ListenableFuture<Void> registerTrigger(@NonNull Uri trigger) {
+ Objects.requireNonNull(trigger);
+
+ return Build.VERSION.SDK_INT > Build.VERSION_CODES.R
+ ? registerTriggerForSPlus(trigger)
+ : registerTriggerForR(trigger);
+ }
+
+ /**
+ * Invokes the {@code registerWebSource} method of {@link MeasurementManager}, and returns a
+ * Void future.
+ */
+ @NonNull
+ public ListenableFuture<Void> registerWebSource(@NonNull WebSourceRegistrationRequest request) {
+ Objects.requireNonNull(request);
+
+ return Build.VERSION.SDK_INT > Build.VERSION_CODES.R
+ ? registerWebSourceForSPlus(request)
+ : registerWebSourceForR(request);
+ }
+
+ /**
+ * Invokes the {@code registerWebTrigger} method of {@link MeasurementManager}, and returns a
+ * Void future.
+ */
+ @NonNull
+ public ListenableFuture<Void> registerWebTrigger(
+ @NonNull WebTriggerRegistrationRequest request) {
+ Objects.requireNonNull(request);
+
+ return Build.VERSION.SDK_INT > Build.VERSION_CODES.R
+ ? registerWebTriggerForSPlus(request)
+ : registerWebTriggerForR(request);
+ }
+
+ /**
+ * Invokes the {@code registerWebTrigger} method of {@link MeasurementManager} with a null
+ * callback, and returns a Void future if successful, or an {@link Exception} if unsuccessful.
+ */
+ @NonNull
+ public ListenableFuture<Void> deleteRegistrations(@NonNull DeletionRequest request) {
+ Objects.requireNonNull(request);
+
+ return Build.VERSION.SDK_INT > Build.VERSION_CODES.R
+ ? deleteRegistrationsForSPlus(request)
+ : deleteRegistrationsForR(request);
+ }
+
+ private ListenableFuture<Void> registerSourceForSPlus(
+ Uri attributionSource, InputEvent inputEvent) {
return CallbackToFutureAdapter.getFuture(
completer -> {
mMeasurementManager.registerSource(
attributionSource,
inputEvent,
mExecutor,
- new AdServicesOutcomeReceiver<>() {
+ new android.os.OutcomeReceiver<>() {
@Override
- public void onResult(@NonNull Object ignoredResult) {
+ public void onResult(Object ignoredResult) {
completer.set(null);
}
@Override
- public void onError(@NonNull Exception error) {
+ public void onError(Exception error) {
completer.setException(error);
}
});
@@ -81,18 +142,61 @@ public class MeasurementClient {
});
}
- /**
- * Invokes the {@code registerTrigger} method of {@link MeasurementManager}, and returns a Void
- * future.
- */
- @NonNull
- public ListenableFuture<Void> registerTrigger(@NonNull Uri trigger) {
+ private ListenableFuture<Void> registerSourceForR(
+ Uri attributionSource, InputEvent inputEvent) {
+ return CallbackToFutureAdapter.getFuture(
+ completer -> {
+ mMeasurementManager.registerSource(
+ attributionSource,
+ inputEvent,
+ mExecutor,
+ new android.adservices.common.AdServicesOutcomeReceiver<>() {
+ @Override
+ public void onResult(Object ignoredResult) {
+ completer.set(null);
+ }
+
+ @Override
+ public void onError(Exception error) {
+ completer.setException(error);
+ }
+ });
+ // This value is used only for debug purposes: it will be used in toString()
+ // of returned future or error cases.
+ return "registerSource";
+ });
+ }
+
+ private ListenableFuture<Void> registerTriggerForSPlus(Uri trigger) {
+ return CallbackToFutureAdapter.getFuture(
+ completer -> {
+ mMeasurementManager.registerTrigger(
+ trigger,
+ mExecutor,
+ new android.os.OutcomeReceiver<>() {
+ @Override
+ public void onResult(Object ignoredResult) {
+ completer.set(null);
+ }
+
+ @Override
+ public void onError(Exception error) {
+ completer.setException(error);
+ }
+ });
+ // This value is used only for debug purposes: it will be used in toString()
+ // of returned future or error cases.
+ return "registerTrigger";
+ });
+ }
+
+ private ListenableFuture<Void> registerTriggerForR(Uri trigger) {
return CallbackToFutureAdapter.getFuture(
completer -> {
mMeasurementManager.registerTrigger(
trigger,
mExecutor,
- new AdServicesOutcomeReceiver<>() {
+ new android.adservices.common.AdServicesOutcomeReceiver<>() {
@Override
public void onResult(@NonNull Object ignoredResult) {
completer.set(null);
@@ -108,25 +212,21 @@ public class MeasurementClient {
return "registerTrigger";
});
}
- /**
- * Invokes the {@code registerWebSource} method of {@link MeasurementManager}, and returns a
- * Void future.
- */
- @NonNull
- public ListenableFuture<Void> registerWebSource(@NonNull WebSourceRegistrationRequest request) {
+
+ private ListenableFuture<Void> registerWebSourceForSPlus(WebSourceRegistrationRequest request) {
return CallbackToFutureAdapter.getFuture(
completer -> {
mMeasurementManager.registerWebSource(
request,
mExecutor,
- new AdServicesOutcomeReceiver<>() {
+ new android.os.OutcomeReceiver<>() {
@Override
- public void onResult(@NonNull Object ignoredResult) {
+ public void onResult(Object ignoredResult) {
completer.set(null);
}
@Override
- public void onError(@NonNull Exception error) {
+ public void onError(Exception error) {
completer.setException(error);
}
});
@@ -136,26 +236,44 @@ public class MeasurementClient {
});
}
- /**
- * Invokes the {@code registerWebTrigger} method of {@link MeasurementManager}, and returns a
- * Void future.
- */
- @NonNull
- public ListenableFuture<Void> registerWebTrigger(
- @NonNull WebTriggerRegistrationRequest request) {
+ private ListenableFuture<Void> registerWebSourceForR(WebSourceRegistrationRequest request) {
+ return CallbackToFutureAdapter.getFuture(
+ completer -> {
+ mMeasurementManager.registerWebSource(
+ request,
+ mExecutor,
+ new android.adservices.common.AdServicesOutcomeReceiver<>() {
+ @Override
+ public void onResult(Object ignoredResult) {
+ completer.set(null);
+ }
+
+ @Override
+ public void onError(Exception error) {
+ completer.setException(error);
+ }
+ });
+ // This value is used only for debug purposes: it will be used in toString()
+ // of returned future or error cases.
+ return "registerWebSource";
+ });
+ }
+
+ private ListenableFuture<Void> registerWebTriggerForSPlus(
+ WebTriggerRegistrationRequest request) {
return CallbackToFutureAdapter.getFuture(
completer -> {
mMeasurementManager.registerWebTrigger(
request,
mExecutor,
- new AdServicesOutcomeReceiver<>() {
+ new android.os.OutcomeReceiver<>() {
@Override
- public void onResult(@NonNull Object ignoredResult) {
+ public void onResult(Object ignoredResult) {
completer.set(null);
}
@Override
- public void onError(@NonNull Exception error) {
+ public void onError(Exception error) {
completer.setException(error);
}
});
@@ -165,25 +283,66 @@ public class MeasurementClient {
});
}
- /**
- * Invokes the {@code registerWebTrigger} method of {@link MeasurementManager} with a null
- * callback, and returns a Void future if successful, or an {@link Exception} if unsuccessful.
- */
- @NonNull
- public ListenableFuture<Void> deleteRegistrations(@NonNull DeletionRequest request) {
+ private ListenableFuture<Void> registerWebTriggerForR(WebTriggerRegistrationRequest request) {
+ return CallbackToFutureAdapter.getFuture(
+ completer -> {
+ mMeasurementManager.registerWebTrigger(
+ request,
+ mExecutor,
+ new android.adservices.common.AdServicesOutcomeReceiver<>() {
+ @Override
+ public void onResult(Object ignoredResult) {
+ completer.set(null);
+ }
+
+ @Override
+ public void onError(Exception error) {
+ completer.setException(error);
+ }
+ });
+ // This value is used only for debug purposes: it will be used in toString()
+ // of returned future or error cases.
+ return "registerWebTrigger";
+ });
+ }
+
+ private ListenableFuture<Void> deleteRegistrationsForSPlus(DeletionRequest request) {
return CallbackToFutureAdapter.getFuture(
completer -> {
mMeasurementManager.deleteRegistrations(
request,
mExecutor,
- new AdServicesOutcomeReceiver<>() {
+ new android.os.OutcomeReceiver<>() {
@Override
- public void onResult(@NonNull Object ignoredResult) {
+ public void onResult(Object ignoredResult) {
completer.set(null);
}
@Override
- public void onError(@NonNull Exception error) {
+ public void onError(Exception error) {
+ completer.setException(error);
+ }
+ });
+ // This value is used only for debug purposes: it will be used in toString()
+ // of returned future or error cases.
+ return "deleteRegistrations";
+ });
+ }
+
+ private ListenableFuture<Void> deleteRegistrationsForR(DeletionRequest request) {
+ return CallbackToFutureAdapter.getFuture(
+ completer -> {
+ mMeasurementManager.deleteRegistrations(
+ request,
+ mExecutor,
+ new android.adservices.common.AdServicesOutcomeReceiver<>() {
+ @Override
+ public void onResult(Object ignoredResult) {
+ completer.set(null);
+ }
+
+ @Override
+ public void onError(Exception error) {
completer.setException(error);
}
});
diff --git a/adservices/framework/Android.bp b/adservices/framework/Android.bp
index 4b1b7859a..e854efb64 100644
--- a/adservices/framework/Android.bp
+++ b/adservices/framework/Android.bp
@@ -37,6 +37,7 @@ java_sdk_library {
"modules-utils-preconditions",
"framework-sdksandbox.impl",
"androidx.annotation_annotation",
+ "error_prone_annotations",
],
sdk_version: "module_current",
min_sdk_version: "30",
@@ -59,6 +60,7 @@ java_library {
"modules-utils-preconditions",
"framework-sdksandbox.impl",
"androidx.annotation_annotation",
+ "error_prone_annotations",
],
min_sdk_version: "30",
defaults: ["framework-module-defaults"],
diff --git a/adservices/framework/java/android/adservices/adid/AdIdCompatibleManager.java b/adservices/framework/java/android/adservices/adid/AdIdCompatibleManager.java
index 4a11d7600..d6aed3e05 100644
--- a/adservices/framework/java/android/adservices/adid/AdIdCompatibleManager.java
+++ b/adservices/framework/java/android/adservices/adid/AdIdCompatibleManager.java
@@ -16,6 +16,7 @@
package android.adservices.adid;
import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID;
+import static android.adservices.common.AdServicesStatusUtils.ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE;
import android.adservices.common.AdServicesOutcomeReceiver;
import android.adservices.common.AdServicesStatusUtils;
@@ -87,6 +88,11 @@ public class AdIdCompatibleManager {
IAdIdService service = null;
try {
service = mServiceBinder.getService();
+
+ // Throw ISE and set it to the callback when service is not available
+ if (service == null) {
+ throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE);
+ }
} catch (RuntimeException e) {
LogUtil.e(e, "Failed binding to AdId service");
executor.execute(() -> callback.onError(e));
diff --git a/adservices/framework/java/android/adservices/adselection/SignedContextualAds.java b/adservices/framework/java/android/adservices/adselection/SignedContextualAds.java
index c52ebd4bb..7a86553f9 100644
--- a/adservices/framework/java/android/adservices/adselection/SignedContextualAds.java
+++ b/adservices/framework/java/android/adservices/adselection/SignedContextualAds.java
@@ -28,7 +28,7 @@ import java.util.List;
import java.util.Objects;
/**
- * Contains a buyer supplied {@link ContextualAds} bundle and its signature.
+ * Contains a buyer supplied {@link AdWithBid} bundle and its signature.
*
* <p>Instances of this class are created by SDKs to be injected as part of {@link
* AdSelectionConfig} and passed to {@link AdSelectionManager#selectAds}
diff --git a/adservices/framework/java/android/adservices/appsetid/AppSetIdManager.java b/adservices/framework/java/android/adservices/appsetid/AppSetIdManager.java
index b305dbb18..c85184dbb 100644
--- a/adservices/framework/java/android/adservices/appsetid/AppSetIdManager.java
+++ b/adservices/framework/java/android/adservices/appsetid/AppSetIdManager.java
@@ -15,6 +15,8 @@
*/
package android.adservices.appsetid;
+import static android.adservices.common.AdServicesStatusUtils.ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE;
+
import android.adservices.common.AdServicesStatusUtils;
import android.adservices.common.CallerMetadata;
import android.adservices.common.SandboxedSdkContextUtils;
@@ -106,6 +108,11 @@ public class AppSetIdManager {
IAppSetIdService service = null;
try {
service = mServiceBinder.getService();
+
+ // Throw ISE and set it to the callback when service is not available
+ if (service == null) {
+ throw new IllegalStateException(ILLEGAL_STATE_EXCEPTION_ERROR_MESSAGE);
+ }
} catch (RuntimeException e) {
LogUtil.e(e, "Failed binding to AppSetId service");
executor.execute(() -> callback.onError(e));
diff --git a/adservices/framework/java/android/adservices/common/AdServicesPermissions.java b/adservices/framework/java/android/adservices/common/AdServicesPermissions.java
index 2a94c711b..140359b1d 100644
--- a/adservices/framework/java/android/adservices/common/AdServicesPermissions.java
+++ b/adservices/framework/java/android/adservices/common/AdServicesPermissions.java
@@ -36,14 +36,6 @@ public class AdServicesPermissions {
public static final String ACCESS_ADSERVICES_CUSTOM_AUDIENCE =
"android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCE";
- /**
- * This permission needs to be declared by the caller of Protected Signals APIs.
- *
- * @hide
- */
- public static final String ACCESS_ADSERVICES_PROTECTED_SIGNALS =
- "android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS";
-
/** This permission needs to be declared by the caller of Advertising ID APIs. */
public static final String ACCESS_ADSERVICES_AD_ID =
"android.permission.ACCESS_ADSERVICES_AD_ID";
diff --git a/adservices/framework/java/android/adservices/shell/IShellCommand.aidl b/adservices/framework/java/android/adservices/shell/IShellCommand.aidl
new file mode 100644
index 000000000..2b6bd81cf
--- /dev/null
+++ b/adservices/framework/java/android/adservices/shell/IShellCommand.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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 android.adservices.shell;
+
+import android.adservices.shell.IShellCommandCallback;
+import android.adservices.shell.ShellCommandParam;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Shell Service.
+ *
+ * {@hide}
+ */
+oneway interface IShellCommand {
+ /**
+ * Runs the shell command and returns the result through callback.
+ */
+ void runShellCommand(in ShellCommandParam request, in IShellCommandCallback callback);
+} \ No newline at end of file
diff --git a/adservices/framework/java/android/adservices/shell/IShellCommandCallback.aidl b/adservices/framework/java/android/adservices/shell/IShellCommandCallback.aidl
new file mode 100644
index 000000000..7a86fbb0c
--- /dev/null
+++ b/adservices/framework/java/android/adservices/shell/IShellCommandCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 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 android.adservices.shell;
+
+import android.adservices.shell.ShellCommandResult;
+
+/**
+ * Callback from the runShellCommand request.
+ * {@hide}
+ */
+oneway interface IShellCommandCallback {
+ void onResult(in ShellCommandResult result);
+} \ No newline at end of file
diff --git a/adservices/framework/java/android/adservices/shell/ShellCommandParam.aidl b/adservices/framework/java/android/adservices/shell/ShellCommandParam.aidl
new file mode 100644
index 000000000..440947220
--- /dev/null
+++ b/adservices/framework/java/android/adservices/shell/ShellCommandParam.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2023 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 android.adservices.shell;
+
+/** {@hide} */
+parcelable ShellCommandParam; \ No newline at end of file
diff --git a/adservices/framework/java/android/adservices/shell/ShellCommandParam.java b/adservices/framework/java/android/adservices/shell/ShellCommandParam.java
new file mode 100644
index 000000000..18b628d8e
--- /dev/null
+++ b/adservices/framework/java/android/adservices/shell/ShellCommandParam.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 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 android.adservices.shell;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Represents request which contains command and args as an input to runShellCommand API.
+ *
+ * @hide
+ */
+public class ShellCommandParam implements Parcelable {
+
+ /* Array containing command name with all the args */
+ private final String[] mCommandArgs;
+
+ public ShellCommandParam(String... commandArgs) {
+ mCommandArgs = Objects.requireNonNull(commandArgs);
+ }
+
+ private ShellCommandParam(Parcel in) {
+ this(in.createStringArray());
+ }
+
+ public static final Creator<ShellCommandParam> CREATOR =
+ new Parcelable.Creator<>() {
+ @Override
+ public ShellCommandParam createFromParcel(Parcel in) {
+ return new ShellCommandParam(in);
+ }
+
+ @Override
+ public ShellCommandParam[] newArray(int size) {
+ return new ShellCommandParam[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStringArray(mCommandArgs);
+ }
+
+ /** Get the command name with all the args as a list. */
+ public String[] getCommandArgs() {
+ return mCommandArgs;
+ }
+}
diff --git a/adservices/framework/java/android/adservices/shell/ShellCommandResult.aidl b/adservices/framework/java/android/adservices/shell/ShellCommandResult.aidl
new file mode 100644
index 000000000..821fcbc38
--- /dev/null
+++ b/adservices/framework/java/android/adservices/shell/ShellCommandResult.aidl
@@ -0,0 +1,20 @@
+
+/*
+ * Copyright (C) 2023 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 android.adservices.shell;
+
+/** {@hide} */
+parcelable ShellCommandResult; \ No newline at end of file
diff --git a/adservices/framework/java/android/adservices/shell/ShellCommandResult.java b/adservices/framework/java/android/adservices/shell/ShellCommandResult.java
new file mode 100644
index 000000000..442c67e58
--- /dev/null
+++ b/adservices/framework/java/android/adservices/shell/ShellCommandResult.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2023 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 android.adservices.shell;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Represents the response from the runShellCommand API.
+ *
+ * @hide
+ */
+public class ShellCommandResult implements Parcelable {
+
+ private static final int RESULT_OK = 0;
+
+ private final int mResultCode;
+ @Nullable private final String mOut;
+ @Nullable private final String mErr;
+
+ private ShellCommandResult(int resultCode, @Nullable String out, @Nullable String err) {
+ mResultCode = resultCode;
+ mOut = out;
+ mErr = err;
+ }
+
+ private ShellCommandResult(Parcel in) {
+ this(in.readInt(), in.readString(), in.readString());
+ }
+
+ private ShellCommandResult(Builder builder) {
+ this(builder.mResultCode, builder.mOut, builder.mErr);
+ }
+
+ public static final Creator<ShellCommandResult> CREATOR =
+ new Parcelable.Creator<>() {
+ @Override
+ public ShellCommandResult createFromParcel(Parcel in) {
+ Objects.requireNonNull(in);
+ return new ShellCommandResult(in);
+ }
+
+ @Override
+ public ShellCommandResult[] newArray(int size) {
+ return new ShellCommandResult[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ Objects.requireNonNull(dest);
+ dest.writeInt(mResultCode);
+ dest.writeString(mOut);
+ dest.writeString(mErr);
+ }
+
+ /** Returns the command status. */
+ public int getResultCode() {
+ return mResultCode;
+ }
+
+ /** Returns {@code true} if {@link #getResultCode} is greater than equal to 0. */
+ public boolean isSuccess() {
+ return getResultCode() >= 0;
+ }
+
+ /** Returns the output of the shell command result. */
+ @Nullable
+ public String getOut() {
+ return mOut;
+ }
+
+ /** Returns the error message associated with this response. */
+ @Nullable
+ public String getErr() {
+ return mErr;
+ }
+
+ /**
+ * Builder for {@link ShellCommandResult}.
+ *
+ * @hide
+ */
+ public static final class Builder {
+ private int mResultCode = RESULT_OK;
+ @Nullable private String mOut;
+ @Nullable private String mErr;
+
+ public Builder() {}
+
+ /** Sets the Status Code. */
+ public Builder setResultCode(int resultCode) {
+ mResultCode = resultCode;
+ return this;
+ }
+
+ /** Sets the shell command output in case of success. */
+ public Builder setOut(@Nullable String out) {
+ mOut = out;
+ return this;
+ }
+
+ /** Sets the error message in case of command failure. */
+ public Builder setErr(@Nullable String err) {
+ mErr = err;
+ return this;
+ }
+
+ /** Builds a {@link ShellCommandResult} object. */
+ public ShellCommandResult build() {
+ return new ShellCommandResult(this);
+ }
+ }
+}
diff --git a/adservices/framework/java/android/adservices/signals/ProtectedSignalsManager.java b/adservices/framework/java/android/adservices/signals/ProtectedSignalsManager.java
index c0b54d956..ffbb084e4 100644
--- a/adservices/framework/java/android/adservices/signals/ProtectedSignalsManager.java
+++ b/adservices/framework/java/android/adservices/signals/ProtectedSignalsManager.java
@@ -16,7 +16,7 @@
package android.adservices.signals;
-import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS;
+import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE;
import android.adservices.common.AdServicesStatusUtils;
import android.adservices.common.FledgeErrorResponse;
@@ -181,7 +181,7 @@ public class ProtectedSignalsManager {
* <p>This call fails with an {@link IllegalStateException} if an internal service error is
* encountered.
*/
- @RequiresPermission(ACCESS_ADSERVICES_PROTECTED_SIGNALS)
+ @RequiresPermission(ACCESS_ADSERVICES_CUSTOM_AUDIENCE)
public void updateSignals(
@NonNull UpdateSignalsRequest updateSignalsRequest,
@NonNull @CallbackExecutor Executor executor,
diff --git a/adservices/framework/java/com/android/adservices/AdServicesCommon.java b/adservices/framework/java/com/android/adservices/AdServicesCommon.java
index 5fae08509..18b324691 100644
--- a/adservices/framework/java/com/android/adservices/AdServicesCommon.java
+++ b/adservices/framework/java/com/android/adservices/AdServicesCommon.java
@@ -26,6 +26,7 @@ import java.util.List;
// TODO(b/295321663): need to split constants into AdServicesCommonConstants so they can be used by
// host-side test artifacts.
+
/**
* Common constants for AdServices
*
@@ -82,6 +83,10 @@ public class AdServicesCommon {
public static final String ACTION_AD_SERVICES_COBALT_UPLOAD_SERVICE =
AdServicesCobaltUploadService.SERVICE_INTERFACE;
+ /** Intent action to discover the Shell Command service in the APK. */
+ public static final String ACTION_SHELL_COMMAND_SERVICE =
+ "android.adservices.SHELL_COMMAND_SERVICE";
+
// Used to differentiate between AdServices APK package name and AdExtServices APK package name.
// The AdExtServices APK package name suffix is android.ext.services.
public static final String ADSERVICES_APK_PACKAGE_NAME_SUFFIX = "android.adservices.api";
diff --git a/adservices/framework/java/com/android/adservices/AndroidServiceBinder.java b/adservices/framework/java/com/android/adservices/AndroidServiceBinder.java
index 280be9a2c..b8ce7dd2a 100644
--- a/adservices/framework/java/com/android/adservices/AndroidServiceBinder.java
+++ b/adservices/framework/java/com/android/adservices/AndroidServiceBinder.java
@@ -27,6 +27,7 @@ import static com.android.adservices.AdServicesCommon.ACTION_APPSETID_PROVIDER_S
import static com.android.adservices.AdServicesCommon.ACTION_APPSETID_SERVICE;
import static com.android.adservices.AdServicesCommon.ACTION_CUSTOM_AUDIENCE_SERVICE;
import static com.android.adservices.AdServicesCommon.ACTION_MEASUREMENT_SERVICE;
+import static com.android.adservices.AdServicesCommon.ACTION_SHELL_COMMAND_SERVICE;
import static com.android.adservices.AdServicesCommon.ACTION_TOPICS_SERVICE;
import static com.android.adservices.AdServicesCommon.SYSTEM_PROPERTY_FOR_DEBUGGING_FEATURE_RAM_LOW;
@@ -221,7 +222,8 @@ class AndroidServiceBinder<T> extends ServiceBinder<T> {
&& !mServiceIntentAction.equals(ACTION_APPSETID_PROVIDER_SERVICE)
&& !mServiceIntentAction.equals(ACTION_AD_SERVICES_COBALT_UPLOAD_SERVICE)
&& !mServiceIntentAction.equals(ACTION_AD_SERVICES_COMMON_SERVICE)
- && !mServiceIntentAction.equals(ACTION_AD_EXT_DATA_STORAGE_SERVICE)) {
+ && !mServiceIntentAction.equals(ACTION_AD_EXT_DATA_STORAGE_SERVICE)
+ && !mServiceIntentAction.equals(ACTION_SHELL_COMMAND_SERVICE)) {
LogUtil.e("Bad service intent action: " + mServiceIntentAction);
return null;
}
diff --git a/adservices/framework/java/com/android/adservices/LogUtil.java b/adservices/framework/java/com/android/adservices/LogUtil.java
index 6c6121be7..968b3e811 100644
--- a/adservices/framework/java/com/android/adservices/LogUtil.java
+++ b/adservices/framework/java/com/android/adservices/LogUtil.java
@@ -18,6 +18,9 @@ package com.android.adservices;
import android.util.Log;
+import com.google.errorprone.annotations.FormatMethod;
+import com.google.errorprone.annotations.FormatString;
+
import java.util.Locale;
/**
@@ -38,7 +41,8 @@ public class LogUtil {
}
/** Log the message as VERBOSE. Return The number of bytes written. */
- public static int v(String format, Object... params) {
+ @FormatMethod
+ public static int v(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
String msg = format(format, params);
return Log.v(TAG, msg);
@@ -55,7 +59,8 @@ public class LogUtil {
}
/** Log the message as DEBUG. Return The number of bytes written. */
- public static int d(String format, Object... params) {
+ @FormatMethod
+ public static int d(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
String msg = format(format, params);
return Log.d(TAG, msg);
@@ -64,7 +69,8 @@ public class LogUtil {
}
/** Log the message as DEBUG. Return The number of bytes written. */
- public static int d(Throwable tr, String format, Object... params) {
+ @FormatMethod
+ public static int d(Throwable tr, @FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
String msg = format(format, params);
return Log.d(TAG, msg, tr);
@@ -81,7 +87,8 @@ public class LogUtil {
}
/** Log the message as INFO. Return The number of bytes written */
- public static int i(String format, Object... params) {
+ @FormatMethod
+ public static int i(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.INFO)) {
String msg = format(format, params);
return Log.i(TAG, msg);
@@ -98,7 +105,8 @@ public class LogUtil {
}
/** Log the message as WARNING. Return The number of bytes written */
- public static int w(String format, Object... params) {
+ @FormatMethod
+ public static int w(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.WARN)) {
String msg = format(format, params);
return Log.w(TAG, msg);
@@ -115,7 +123,8 @@ public class LogUtil {
}
/** Log the message as ERROR. Return The number of bytes written */
- public static int e(String format, Object... params) {
+ @FormatMethod
+ public static int e(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.ERROR)) {
String msg = format(format, params);
return Log.e(TAG, msg);
@@ -138,12 +147,14 @@ public class LogUtil {
}
/** Log the message as ERROR. Return The number of bytes written */
- public static int e(Throwable tr, String format, Object... params) {
+ @FormatMethod
+ public static int e(Throwable tr, @FormatString String format, Object... params) {
return Log.isLoggable(TAG, Log.ERROR) ? e(tr, format(format, params)) : 0;
}
/** Log the message as WARNING. Return The number of bytes written */
- public static int w(Throwable tr, String format, Object... params) {
+ @FormatMethod
+ public static int w(Throwable tr, @FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.WARN)) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
String msg = format(format, params);
@@ -165,7 +176,9 @@ public class LogUtil {
*/
@Deprecated
public static int d(String msg, Throwable tr) {
- return d(tr, msg);
+ @SuppressWarnings("FormatStringAnnotation")
+ int result = d(tr, msg);
+ return result;
}
/**
@@ -176,7 +189,9 @@ public class LogUtil {
*/
@Deprecated
public static int w(String msg, Throwable tr) {
- return w(tr, msg);
+ @SuppressWarnings("FormatStringAnnotation")
+ int result = w(tr, msg);
+ return result;
}
/**
diff --git a/adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt b/adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt
index dea6c6ffb..7fe96278c 100644
--- a/adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt
+++ b/adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt
@@ -30,6 +30,7 @@ class AdServicesLintCheckerIssueRegistry : IssueRegistry() {
BackCompatJobServiceDetector.ISSUE,
BackCompatNewFileDetector.ISSUE,
RoomDatabaseMigrationDetector.ISSUE,
+ PreconditionsCheckStateDetector.ISSUE,
)
override val api: Int
diff --git a/adservices/linter/java/android/adservices/lint/PreconditionsCheckStateDetector.kt b/adservices/linter/java/android/adservices/lint/PreconditionsCheckStateDetector.kt
new file mode 100644
index 000000000..96c995fd3
--- /dev/null
+++ b/adservices/linter/java/android/adservices/lint/PreconditionsCheckStateDetector.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 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 android.adservices.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+
+class PreconditionsCheckStateDetector : Detector(), SourceCodeScanner {
+ override fun getApplicableMethodNames(): List<String>? {
+ return listOf("checkState")
+ }
+
+ override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+ if (method.name == "checkState" && method.containingClass?.qualifiedName ==
+ "com.android.internal.util.Preconditions" && method.parameterList.parametersCount >= 3) {
+ context.report(issue = ISSUE, location = context.getNameLocation(node),
+ message = "DO NOT USE com.android.internal.util.Preconditions.CheckState(boolean, String, Object...)" +
+ " because it is not available in R-. Use Preconditions.CheckState(boolean, String, Object...) " +
+ "from adservices-shared-util instead.")
+ }
+ }
+
+ companion object {
+ val ISSUE = Issue.create(
+ id = "AvoidPreconditions.CheckState",
+ briefDescription = "DO NOT USE Preconditions.CheckState",
+ explanation = """
+ DO NOT USE com.android.internal.util.Preconditions.CheckState(boolean, String, Object...)
+ because it is not available in R-. Use Preconditions.CheckState(boolean, String, Object...) from adservices-shared-util instead.
+ """,
+ category = Category.COMPLIANCE,
+ severity = Severity.ERROR,
+ implementation = Implementation(PreconditionsCheckStateDetector::class.java, Scope.JAVA_FILE_SCOPE))
+ }
+} \ No newline at end of file
diff --git a/adservices/linter/tests/java/android/adservices/lint/test/PreconditionsCheckStateDetectorTest.kt b/adservices/linter/tests/java/android/adservices/lint/test/PreconditionsCheckStateDetectorTest.kt
new file mode 100644
index 000000000..a579d4949
--- /dev/null
+++ b/adservices/linter/tests/java/android/adservices/lint/test/PreconditionsCheckStateDetectorTest.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2023 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 android.adservices.lint.test
+
+import android.adservices.lint.BackCompatNewFileDetector
+import android.adservices.lint.PreconditionsCheckStateDetector
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestLintTask
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class PreconditionsCheckStateDetectorTest : LintDetectorTest() {
+ override fun getDetector(): Detector = PreconditionsCheckStateDetector()
+
+ override fun getIssues(): List<Issue> = listOf(PreconditionsCheckStateDetector.ISSUE)
+
+ override fun lint(): TestLintTask = super.lint().allowMissingSdk(true)
+
+ override fun allowCompilationErrors(): Boolean {
+ // Some of these unit tests are still relying on source code that references
+ // unresolved symbols etc.
+ return true
+ }
+
+ @Test
+ fun applicableMethodCalls_throws() {
+ lint().files(java("""
+package com.android.adservices;
+
+import com.android.internal.util.Preconditions;
+
+public final class FakeClass {
+ public FakeClass() {
+ Preconditions.checkState(
+ true,
+ fakeStringFormat,
+ fakeObject);
+ }
+}
+ """).indented(),
+ *stubs)
+ .issues(PreconditionsCheckStateDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/com/android/adservices/FakeClass.java:7: Error: DO NOT USE com.android.internal.util.Preconditions.CheckState(boolean, String, Object...) because it is not available in R-. Use Preconditions.CheckState(boolean, String, Object...) from adservices-shared-util instead. [AvoidPreconditions.CheckState]
+ Preconditions.checkState(
+ ~~~~~~~~~~
+1 errors, 0 warnings
+ """.trimIndent())
+ }
+
+ @Test
+ fun applicableMethodCalls_noPreconditionsCheckState_pass() {
+ lint().files(java("""
+package com.android.adservices;
+
+import com.android.internal.util.Preconditions;
+
+public final class FakeClass {
+ public FakeClass() {
+ Preconditions.checkArgument( // Use other method from Preconditions class will not trigger lint errors.
+ true,
+ fakeString,
+ fakeObject);
+ }
+}
+ """).indented(),
+ *stubs)
+ .issues(BackCompatNewFileDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun applicableMethodCalls_usingSharedUtilClass_pass() {
+ lint().files(java("""
+package com.android.adservices;
+
+import com.android.adservices.shared.util.Preconditions;
+
+public final class FakeClass {
+ public FakeClass() {
+ Preconditions.checkState( // Use checkState from Helper class will not trigger lint errors.
+ true,
+ fakeStringFormat,
+ fakeObject);
+ }
+}
+ """).indented(),
+ *stubs)
+ .issues(BackCompatNewFileDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ private val preconditionsClassStub: TestFile =
+ java("""
+ package com.android.internal.util;
+
+ public class Preconditions {
+ public static void checkState(boolean b, String errorMessageTemplate, Object o1) {
+ }
+ }
+ """).indented()
+
+ private val helperClassWithCheckStateStub: TestFile =
+ java("""
+ package com.android.adservices.shared.util;
+
+ public class Preconditions {
+ public static void checkState(boolean b, String errorMessageTemplate, Object o1) {
+ }
+ }
+ """).indented()
+
+ private val stubs =
+ arrayOf(
+ preconditionsClassStub,
+ helperClassWithCheckStateStub
+ )
+} \ No newline at end of file
diff --git a/adservices/samples/topics/sampleapp1/Android.bp b/adservices/samples/topics/sampleapp1/Android.bp
index a320f3617..f254f53da 100644
--- a/adservices/samples/topics/sampleapp1/Android.bp
+++ b/adservices/samples/topics/sampleapp1/Android.bp
@@ -28,11 +28,15 @@ android_app {
],
static_libs: [
"adservices-clients",
+ "adservices-service-core",
"androidx.appcompat_appcompat",
"androidx-constraintlayout_constraintlayout",
"com.google.android.material_material",
"androidx.concurrent_concurrent-futures",
],
+ jni_libs: [
+ "libhpke_jni",
+ ],
resource_dirs: ["res"],
platform_apis: true,
min_sdk_version: "30",
diff --git a/adservices/samples/topics/sampleapp1/java/com/example/adservices/samples/topics/sampleapp1/MainActivity.java b/adservices/samples/topics/sampleapp1/java/com/example/adservices/samples/topics/sampleapp1/MainActivity.java
index 68b1c77e9..6cbe1935c 100644
--- a/adservices/samples/topics/sampleapp1/java/com/example/adservices/samples/topics/sampleapp1/MainActivity.java
+++ b/adservices/samples/topics/sampleapp1/java/com/example/adservices/samples/topics/sampleapp1/MainActivity.java
@@ -18,6 +18,7 @@ package com.example.adservices.samples.topics.sampleapp1;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.EncryptedTopic;
import android.adservices.topics.GetTopicsResponse;
import android.adservices.topics.Topic;
import android.content.Context;
@@ -31,6 +32,9 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
+import com.android.adservices.HpkeJni;
+
+import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -39,6 +43,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -56,6 +61,12 @@ public class MainActivity extends AppCompatActivity {
private static final String TAG = "SampleApp1";
private static final String RB_SETTING_APP_INTENT = "android.adservices.ui.SETTINGS";
private static final List<String> SDK_NAMES = new ArrayList<>(Arrays.asList("SdkName1"));
+ // Test constants for testing encryption
+ private static final String TEST_PRIVATE_KEY_BASE64 =
+ "f86EzLmGaVmc+PwjJk5ADPE4ijQvliWf0CQyY/Zyy7I=";
+ private static final byte[] DECODED_PRIVATE_KEY =
+ Base64.getDecoder().decode(TEST_PRIVATE_KEY_BASE64);
+ private static final byte[] EMPTY_CONTEXT_INFO = new byte[] {};
private Button mTopicsClientButton;
private Button mTopicsPreviewButton;
private TextView mResultTextView;
@@ -108,6 +119,21 @@ public class MainActivity extends AppCompatActivity {
return sb.toString();
}
+ private String getDecryptedTopics(List<EncryptedTopic> arr) {
+ StringBuilder sb = new StringBuilder();
+ int index = 1;
+ for (EncryptedTopic encryptedTopic : arr) {
+ byte[] cipherText =
+ Bytes.concat(
+ encryptedTopic.getEncapsulatedKey(),
+ encryptedTopic.getEncryptedTopic());
+ byte[] decryptedText =
+ HpkeJni.decrypt(DECODED_PRIVATE_KEY, cipherText, EMPTY_CONTEXT_INFO);
+ sb.append(index++).append(". ").append(new String(decryptedText)).append(NEWLINE);
+ }
+ return sb.toString();
+ }
+
@SuppressWarnings("NewApi")
private void getTopics(String sdkName, boolean shouldRecordObservation) {
// On R, Privacy Sandbox is initially disabled.
@@ -139,6 +165,9 @@ public class MainActivity extends AppCompatActivity {
public void onSuccess(GetTopicsResponse result) {
Log.d(TAG, "GetTopics for sdk " + sdkName + " succeeded!");
String topics = getTopics(result.getTopics());
+ String encryptedTopicsDecrypted =
+ getDecryptedTopics(result.getEncryptedTopics());
+
mHandler.post(
new Runnable() {
@Override
@@ -149,9 +178,22 @@ public class MainActivity extends AppCompatActivity {
+ NEWLINE
+ topics
+ NEWLINE);
+ mResultTextView.append(
+ sdkName
+ + "'s encrypted topics, decrypted: "
+ + NEWLINE
+ + encryptedTopicsDecrypted
+ + NEWLINE);
}
});
Log.d(TAG, sdkName + "'s topics: " + NEWLINE + topics + NEWLINE);
+ Log.d(
+ TAG,
+ sdkName
+ + "'s encrypted topics, decrypted: "
+ + NEWLINE
+ + encryptedTopicsDecrypted
+ + NEWLINE);
}
@Override
diff --git a/adservices/samples/topics/sampleapp2/Android.bp b/adservices/samples/topics/sampleapp2/Android.bp
index d128f18ed..9494490b9 100644
--- a/adservices/samples/topics/sampleapp2/Android.bp
+++ b/adservices/samples/topics/sampleapp2/Android.bp
@@ -28,11 +28,15 @@ android_app {
],
static_libs: [
"adservices-clients",
+ "adservices-service-core",
"androidx.appcompat_appcompat",
"androidx-constraintlayout_constraintlayout",
"com.google.android.material_material",
"androidx.concurrent_concurrent-futures",
],
+ jni_libs: [
+ "libhpke_jni",
+ ],
resource_dirs: ["res"],
platform_apis: true,
min_sdk_version: "30",
diff --git a/adservices/samples/topics/sampleapp2/java/com/example/adservices/samples/topics/sampleapp2/MainActivity.java b/adservices/samples/topics/sampleapp2/java/com/example/adservices/samples/topics/sampleapp2/MainActivity.java
index 4abb6d7fd..e946e2958 100644
--- a/adservices/samples/topics/sampleapp2/java/com/example/adservices/samples/topics/sampleapp2/MainActivity.java
+++ b/adservices/samples/topics/sampleapp2/java/com/example/adservices/samples/topics/sampleapp2/MainActivity.java
@@ -18,6 +18,7 @@ package com.example.adservices.samples.topics.sampleapp2;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.EncryptedTopic;
import android.adservices.topics.GetTopicsResponse;
import android.adservices.topics.Topic;
import android.os.Bundle;
@@ -28,15 +29,18 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
+import com.android.adservices.HpkeJni;
+
+import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -54,6 +58,12 @@ public class MainActivity extends AppCompatActivity {
private static final String TAG = "SampleApp";
private static final List<String> SDK_NAMES =
new ArrayList<>(Arrays.asList("SdkName1", "SdkName2"));
+ // Test constants for testing encryption
+ private static final String TEST_PRIVATE_KEY_BASE64 =
+ "f86EzLmGaVmc+PwjJk5ADPE4ijQvliWf0CQyY/Zyy7I=";
+ private static final byte[] DECODED_PRIVATE_KEY =
+ Base64.getDecoder().decode(TEST_PRIVATE_KEY_BASE64);
+ private static final byte[] EMPTY_CONTEXT_INFO = new byte[] {};
private Button mTopicsClientButton;
private TextView mResultTextView;
private AdvertisingTopicsClient mAdvertisingTopicsClient;
@@ -91,25 +101,42 @@ public class MainActivity extends AppCompatActivity {
public void onSuccess(GetTopicsResponse result) {
Log.d(TAG, "GetTopics for sdk " + sdkName + " succeeded!");
String topics = getTopics(result.getTopics());
+ String encryptedTopicsDecrypted =
+ getDecryptedTopics(result.getEncryptedTopics());
+
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ sdkName
+ + "'s topics: "
+ + NEWLINE
+ + topics
+ + NEWLINE);
+ mResultTextView.append(
+ sdkName
+ + "'s encrypted topics,"
+ + " decrypted: "
+ + NEWLINE
+ + encryptedTopicsDecrypted
+ + NEWLINE);
+ }
+ });
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
+ Log.d(
+ TAG,
sdkName
+ "'s topics: "
+ NEWLINE
+ topics
+ NEWLINE);
- }
- });
-
Log.d(
TAG,
sdkName
- + "'s topics: "
+ + "'s encrypted topics, decrypted: "
+ NEWLINE
- + topics
+ + encryptedTopicsDecrypted
+ NEWLINE);
}
@@ -126,17 +153,18 @@ public class MainActivity extends AppCompatActivity {
+ ": "
+ t.getMessage());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
- "Failed to getTopics for sdk "
- + sdkName
- + ": "
- + t.toString()
- + NEWLINE);
- }
- });
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ "Failed to getTopics for sdk "
+ + sdkName
+ + ": "
+ + t.toString()
+ + NEWLINE);
+ }
+ });
}
},
directExecutor());
@@ -152,4 +180,19 @@ public class MainActivity extends AppCompatActivity {
}
return sb.toString();
}
+
+ private String getDecryptedTopics(List<EncryptedTopic> arr) {
+ StringBuilder sb = new StringBuilder();
+ int index = 1;
+ for (EncryptedTopic encryptedTopic : arr) {
+ byte[] cipherText =
+ Bytes.concat(
+ encryptedTopic.getEncapsulatedKey(),
+ encryptedTopic.getEncryptedTopic());
+ byte[] decryptedText =
+ HpkeJni.decrypt(DECODED_PRIVATE_KEY, cipherText, EMPTY_CONTEXT_INFO);
+ sb.append(index++).append(". ").append(new String(decryptedText)).append(NEWLINE);
+ }
+ return sb.toString();
+ }
}
diff --git a/adservices/samples/topics/sampleapp3/Android.bp b/adservices/samples/topics/sampleapp3/Android.bp
index 9e9d2ae64..c1cae4581 100644
--- a/adservices/samples/topics/sampleapp3/Android.bp
+++ b/adservices/samples/topics/sampleapp3/Android.bp
@@ -28,11 +28,15 @@ android_app {
],
static_libs: [
"adservices-clients",
+ "adservices-service-core",
"androidx.appcompat_appcompat",
"androidx-constraintlayout_constraintlayout",
"com.google.android.material_material",
"androidx.concurrent_concurrent-futures",
],
+ jni_libs: [
+ "libhpke_jni",
+ ],
resource_dirs: ["res"],
platform_apis: true,
min_sdk_version: "30",
diff --git a/adservices/samples/topics/sampleapp3/java/com/example/adservices/samples/topics/sampleapp3/MainActivity.java b/adservices/samples/topics/sampleapp3/java/com/example/adservices/samples/topics/sampleapp3/MainActivity.java
index 2433d130f..d2c889f24 100644
--- a/adservices/samples/topics/sampleapp3/java/com/example/adservices/samples/topics/sampleapp3/MainActivity.java
+++ b/adservices/samples/topics/sampleapp3/java/com/example/adservices/samples/topics/sampleapp3/MainActivity.java
@@ -18,6 +18,7 @@ package com.example.adservices.samples.topics.sampleapp3;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.EncryptedTopic;
import android.adservices.topics.GetTopicsResponse;
import android.adservices.topics.Topic;
import android.os.Bundle;
@@ -28,6 +29,9 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
+import com.android.adservices.HpkeJni;
+
+import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -36,6 +40,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -53,6 +58,12 @@ public class MainActivity extends AppCompatActivity {
private static final String TAG = "SampleApp";
private static final List<String> SDK_NAMES =
new ArrayList<>(Arrays.asList("SdkName2", "SdkName3"));
+ // Test constants for testing encryption
+ private static final String TEST_PRIVATE_KEY_BASE64 =
+ "f86EzLmGaVmc+PwjJk5ADPE4ijQvliWf0CQyY/Zyy7I=";
+ private static final byte[] DECODED_PRIVATE_KEY =
+ Base64.getDecoder().decode(TEST_PRIVATE_KEY_BASE64);
+ private static final byte[] EMPTY_CONTEXT_INFO = new byte[] {};
private Button mTopicsClientButton;
private TextView mResultTextView;
private AdvertisingTopicsClient mAdvertisingTopicsClient;
@@ -90,24 +101,42 @@ public class MainActivity extends AppCompatActivity {
public void onSuccess(GetTopicsResponse result) {
Log.d(TAG, "GetTopics for sdk " + sdkName + " succeeded!");
String topics = getTopics(result.getTopics());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
+ String encryptedTopicsDecrypted =
+ getDecryptedTopics(result.getEncryptedTopics());
+
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ sdkName
+ + "'s topics: "
+ + NEWLINE
+ + topics
+ + NEWLINE);
+ mResultTextView.append(
+ sdkName
+ + "'s encrypted topics,"
+ + " decrypted: "
+ + NEWLINE
+ + encryptedTopicsDecrypted
+ + NEWLINE);
+ }
+ });
+
+ Log.d(
+ TAG,
sdkName
+ "'s topics: "
+ NEWLINE
+ topics
+ NEWLINE);
- }
- });
-
Log.d(
TAG,
sdkName
- + "'s topics: "
+ + "'s encrypted topics, decrypted: "
+ NEWLINE
- + topics
+ + encryptedTopicsDecrypted
+ NEWLINE);
}
@@ -124,17 +153,18 @@ public class MainActivity extends AppCompatActivity {
+ ": "
+ t.getMessage());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
- "Failed to getTopics for sdk "
- + sdkName
- + ": "
- + t.toString()
- + NEWLINE);
- }
- });
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ "Failed to getTopics for sdk "
+ + sdkName
+ + ": "
+ + t.toString()
+ + NEWLINE);
+ }
+ });
}
},
directExecutor());
@@ -150,4 +180,19 @@ public class MainActivity extends AppCompatActivity {
}
return sb.toString();
}
+
+ private String getDecryptedTopics(List<EncryptedTopic> arr) {
+ StringBuilder sb = new StringBuilder();
+ int index = 1;
+ for (EncryptedTopic encryptedTopic : arr) {
+ byte[] cipherText =
+ Bytes.concat(
+ encryptedTopic.getEncapsulatedKey(),
+ encryptedTopic.getEncryptedTopic());
+ byte[] decryptedText =
+ HpkeJni.decrypt(DECODED_PRIVATE_KEY, cipherText, EMPTY_CONTEXT_INFO);
+ sb.append(index++).append(". ").append(new String(decryptedText)).append(NEWLINE);
+ }
+ return sb.toString();
+ }
}
diff --git a/adservices/samples/topics/sampleapp4/Android.bp b/adservices/samples/topics/sampleapp4/Android.bp
index ea06a545e..b848db7d8 100644
--- a/adservices/samples/topics/sampleapp4/Android.bp
+++ b/adservices/samples/topics/sampleapp4/Android.bp
@@ -28,11 +28,15 @@ android_app {
],
static_libs: [
"adservices-clients",
+ "adservices-service-core",
"androidx.appcompat_appcompat",
"androidx-constraintlayout_constraintlayout",
"com.google.android.material_material",
"androidx.concurrent_concurrent-futures",
],
+ jni_libs: [
+ "libhpke_jni",
+ ],
resource_dirs: ["res"],
platform_apis: true,
min_sdk_version: "30",
diff --git a/adservices/samples/topics/sampleapp4/java/com/example/adservices/samples/topics/sampleapp4/MainActivity.java b/adservices/samples/topics/sampleapp4/java/com/example/adservices/samples/topics/sampleapp4/MainActivity.java
index 03531b4d4..46ae04f79 100644
--- a/adservices/samples/topics/sampleapp4/java/com/example/adservices/samples/topics/sampleapp4/MainActivity.java
+++ b/adservices/samples/topics/sampleapp4/java/com/example/adservices/samples/topics/sampleapp4/MainActivity.java
@@ -18,6 +18,7 @@ package com.example.adservices.samples.topics.sampleapp4;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.EncryptedTopic;
import android.adservices.topics.GetTopicsResponse;
import android.adservices.topics.Topic;
import android.os.Bundle;
@@ -28,6 +29,9 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
+import com.android.adservices.HpkeJni;
+
+import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -36,6 +40,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -53,6 +58,12 @@ public class MainActivity extends AppCompatActivity {
private static final String TAG = "SampleApp";
private static final List<String> SDK_NAMES =
new ArrayList<>(Arrays.asList("SdkName3", "SdkName4"));
+ // Test constants for testing encryption
+ private static final String TEST_PRIVATE_KEY_BASE64 =
+ "f86EzLmGaVmc+PwjJk5ADPE4ijQvliWf0CQyY/Zyy7I=";
+ private static final byte[] DECODED_PRIVATE_KEY =
+ Base64.getDecoder().decode(TEST_PRIVATE_KEY_BASE64);
+ private static final byte[] EMPTY_CONTEXT_INFO = new byte[] {};
private Button mTopicsClientButton;
private TextView mResultTextView;
private AdvertisingTopicsClient mAdvertisingTopicsClient;
@@ -90,25 +101,42 @@ public class MainActivity extends AppCompatActivity {
public void onSuccess(GetTopicsResponse result) {
Log.d(TAG, "GetTopics for sdk " + sdkName + " succeeded!");
String topics = getTopics(result.getTopics());
+ String encryptedTopicsDecrypted =
+ getDecryptedTopics(result.getEncryptedTopics());
+
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ sdkName
+ + "'s topics: "
+ + NEWLINE
+ + topics
+ + NEWLINE);
+ mResultTextView.append(
+ sdkName
+ + "'s encrypted topics,"
+ + " decrypted: "
+ + NEWLINE
+ + encryptedTopicsDecrypted
+ + NEWLINE);
+ }
+ });
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
+ Log.d(
+ TAG,
sdkName
+ "'s topics: "
+ NEWLINE
+ topics
+ NEWLINE);
- }
- });
-
Log.d(
TAG,
sdkName
- + "'s topics: "
+ + "'s encrypted topics, decrypted: "
+ NEWLINE
- + topics
+ + encryptedTopicsDecrypted
+ NEWLINE);
}
@@ -125,17 +153,18 @@ public class MainActivity extends AppCompatActivity {
+ ": "
+ t.getMessage());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
- "Failed to getTopics for sdk "
- + sdkName
- + ": "
- + t.toString()
- + NEWLINE);
- }
- });
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ "Failed to getTopics for sdk "
+ + sdkName
+ + ": "
+ + t.toString()
+ + NEWLINE);
+ }
+ });
}
},
directExecutor());
@@ -151,4 +180,19 @@ public class MainActivity extends AppCompatActivity {
}
return sb.toString();
}
+
+ private String getDecryptedTopics(List<EncryptedTopic> arr) {
+ StringBuilder sb = new StringBuilder();
+ int index = 1;
+ for (EncryptedTopic encryptedTopic : arr) {
+ byte[] cipherText =
+ Bytes.concat(
+ encryptedTopic.getEncapsulatedKey(),
+ encryptedTopic.getEncryptedTopic());
+ byte[] decryptedText =
+ HpkeJni.decrypt(DECODED_PRIVATE_KEY, cipherText, EMPTY_CONTEXT_INFO);
+ sb.append(index++).append(". ").append(new String(decryptedText)).append(NEWLINE);
+ }
+ return sb.toString();
+ }
}
diff --git a/adservices/samples/topics/sampleapp5/Android.bp b/adservices/samples/topics/sampleapp5/Android.bp
index eefc38270..2e794df73 100644
--- a/adservices/samples/topics/sampleapp5/Android.bp
+++ b/adservices/samples/topics/sampleapp5/Android.bp
@@ -28,11 +28,15 @@ android_app {
],
static_libs: [
"adservices-clients",
+ "adservices-service-core",
"androidx.appcompat_appcompat",
"androidx-constraintlayout_constraintlayout",
"com.google.android.material_material",
"androidx.concurrent_concurrent-futures",
],
+ jni_libs: [
+ "libhpke_jni",
+ ],
resource_dirs: ["res"],
platform_apis: true,
min_sdk_version: "30",
diff --git a/adservices/samples/topics/sampleapp5/java/com/example/adservices/samples/topics/sampleapp5/MainActivity.java b/adservices/samples/topics/sampleapp5/java/com/example/adservices/samples/topics/sampleapp5/MainActivity.java
index 6d93fb918..0c155d2d7 100644
--- a/adservices/samples/topics/sampleapp5/java/com/example/adservices/samples/topics/sampleapp5/MainActivity.java
+++ b/adservices/samples/topics/sampleapp5/java/com/example/adservices/samples/topics/sampleapp5/MainActivity.java
@@ -18,6 +18,7 @@ package com.example.adservices.samples.topics.sampleapp5;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.EncryptedTopic;
import android.adservices.topics.GetTopicsResponse;
import android.adservices.topics.Topic;
import android.os.Bundle;
@@ -28,6 +29,9 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
+import com.android.adservices.HpkeJni;
+
+import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -36,6 +40,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -53,6 +58,11 @@ public class MainActivity extends AppCompatActivity {
private static final String TAG = "SampleApp";
private static final List<String> SDK_NAMES =
new ArrayList<>(Arrays.asList("SdkName3", "SdkName4", "SdkName5"));
+ // Test constants for testing encryption
+ private static final String PRIVATE_KEY_BASE64 = "f86EzLmGaVmc+PwjJk5ADPE4ijQvliWf0CQyY/Zyy7I=";
+ private static final byte[] DECODED_PRIVATE_KEY =
+ Base64.getDecoder().decode(PRIVATE_KEY_BASE64);
+ private static final byte[] EMPTY_CONTEXT_INFO = new byte[] {};
private Button mTopicsClientButton;
private TextView mResultTextView;
private AdvertisingTopicsClient mAdvertisingTopicsClient;
@@ -90,24 +100,41 @@ public class MainActivity extends AppCompatActivity {
public void onSuccess(GetTopicsResponse result) {
Log.d(TAG, "GetTopics for sdk " + sdkName + " succeeded!");
String topics = getTopics(result.getTopics());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
+ String encryptedTopicsDecrypted =
+ getDecryptedTopics(result.getEncryptedTopics());
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ sdkName
+ + "'s topics: "
+ + NEWLINE
+ + topics
+ + NEWLINE);
+ mResultTextView.append(
+ sdkName
+ + "'s encrypted topics,"
+ + " decrypted: "
+ + NEWLINE
+ + encryptedTopicsDecrypted
+ + NEWLINE);
+ }
+ });
+
+ Log.d(
+ TAG,
sdkName
+ "'s topics: "
+ NEWLINE
+ topics
+ NEWLINE);
- }
- });
-
Log.d(
TAG,
sdkName
- + "'s topics: "
+ + "'s encrypted topics, decrypted: "
+ NEWLINE
- + topics
+ + encryptedTopicsDecrypted
+ NEWLINE);
}
@@ -124,17 +151,18 @@ public class MainActivity extends AppCompatActivity {
+ ": "
+ t.getMessage());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
- "Failed to getTopics for sdk "
- + sdkName
- + ": "
- + t.toString()
- + NEWLINE);
- }
- });
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ "Failed to getTopics for sdk "
+ + sdkName
+ + ": "
+ + t.toString()
+ + NEWLINE);
+ }
+ });
}
},
directExecutor());
@@ -150,4 +178,19 @@ public class MainActivity extends AppCompatActivity {
}
return sb.toString();
}
+
+ private String getDecryptedTopics(List<EncryptedTopic> arr) {
+ StringBuilder sb = new StringBuilder();
+ int index = 1;
+ for (EncryptedTopic encryptedTopic : arr) {
+ byte[] cipherText =
+ Bytes.concat(
+ encryptedTopic.getEncapsulatedKey(),
+ encryptedTopic.getEncryptedTopic());
+ byte[] decryptedText =
+ HpkeJni.decrypt(DECODED_PRIVATE_KEY, cipherText, EMPTY_CONTEXT_INFO);
+ sb.append(index++).append(". ").append(new String(decryptedText)).append(NEWLINE);
+ }
+ return sb.toString();
+ }
}
diff --git a/adservices/samples/topics/sampleapp6/Android.bp b/adservices/samples/topics/sampleapp6/Android.bp
index c3a5ec7e6..298656d2f 100644
--- a/adservices/samples/topics/sampleapp6/Android.bp
+++ b/adservices/samples/topics/sampleapp6/Android.bp
@@ -28,11 +28,15 @@ android_app {
],
static_libs: [
"adservices-clients",
+ "adservices-service-core",
"androidx.appcompat_appcompat",
"androidx-constraintlayout_constraintlayout",
"com.google.android.material_material",
"androidx.concurrent_concurrent-futures",
],
+ jni_libs: [
+ "libhpke_jni",
+ ],
resource_dirs: ["res"],
platform_apis: true,
min_sdk_version: "30",
diff --git a/adservices/samples/topics/sampleapp6/java/com/example/adservices/samples/topics/sampleapp6/MainActivity.java b/adservices/samples/topics/sampleapp6/java/com/example/adservices/samples/topics/sampleapp6/MainActivity.java
index 69e2017d6..7492debcf 100644
--- a/adservices/samples/topics/sampleapp6/java/com/example/adservices/samples/topics/sampleapp6/MainActivity.java
+++ b/adservices/samples/topics/sampleapp6/java/com/example/adservices/samples/topics/sampleapp6/MainActivity.java
@@ -18,6 +18,7 @@ package com.example.adservices.samples.topics.sampleapp6;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.EncryptedTopic;
import android.adservices.topics.GetTopicsResponse;
import android.adservices.topics.Topic;
import android.os.Bundle;
@@ -28,6 +29,9 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
+import com.android.adservices.HpkeJni;
+
+import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -36,6 +40,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -54,6 +59,12 @@ public class MainActivity extends AppCompatActivity {
private static final List<String> SDK_NAMES =
new ArrayList<>(
Arrays.asList("SdkName1", "SdkName2", "SdkName3", "SdkName4", "SdkName5"));
+ // Test constants for testing encryption
+ private static final String TEST_PRIVATE_KEY_BASE64 =
+ "f86EzLmGaVmc+PwjJk5ADPE4ijQvliWf0CQyY/Zyy7I=";
+ private static final byte[] DECODED_PRIVATE_KEY =
+ Base64.getDecoder().decode(TEST_PRIVATE_KEY_BASE64);
+ private static final byte[] EMPTY_CONTEXT_INFO = new byte[] {};
private Button mTopicsClientButton;
private TextView mResultTextView;
private AdvertisingTopicsClient mAdvertisingTopicsClient;
@@ -91,23 +102,40 @@ public class MainActivity extends AppCompatActivity {
public void onSuccess(GetTopicsResponse result) {
Log.d(TAG, "GetTopics for sdk " + sdkName + " succeeded!");
String topics = getTopics(result.getTopics());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
+ String encryptedTopicsDecrypted =
+ getDecryptedTopics(result.getEncryptedTopics());
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ sdkName
+ + "'s topics: "
+ + NEWLINE
+ + topics
+ + NEWLINE);
+ mResultTextView.append(
+ sdkName
+ + "'s encrypted topics,"
+ + " decrypted: "
+ + NEWLINE
+ + encryptedTopicsDecrypted
+ + NEWLINE);
+ }
+ });
+ Log.d(
+ TAG,
sdkName
+ "'s topics: "
+ NEWLINE
+ topics
+ NEWLINE);
- }
- });
Log.d(
TAG,
sdkName
- + "'s topics: "
+ + "'s encrypted topics, decrypted: "
+ NEWLINE
- + topics
+ + encryptedTopicsDecrypted
+ NEWLINE);
}
@@ -122,17 +150,18 @@ public class MainActivity extends AppCompatActivity {
+ sdkName
+ ": "
+ sw.toString());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
- "Failed to getTopics for sdk "
- + sdkName
- + ": "
- + t.toString()
- + NEWLINE);
- }
- });
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ "Failed to getTopics for sdk "
+ + sdkName
+ + ": "
+ + t.toString()
+ + NEWLINE);
+ }
+ });
}
},
directExecutor());
@@ -148,4 +177,19 @@ public class MainActivity extends AppCompatActivity {
}
return sb.toString();
}
+
+ private String getDecryptedTopics(List<EncryptedTopic> arr) {
+ StringBuilder sb = new StringBuilder();
+ int index = 1;
+ for (EncryptedTopic encryptedTopic : arr) {
+ byte[] cipherText =
+ Bytes.concat(
+ encryptedTopic.getEncapsulatedKey(),
+ encryptedTopic.getEncryptedTopic());
+ byte[] decryptedText =
+ HpkeJni.decrypt(DECODED_PRIVATE_KEY, cipherText, EMPTY_CONTEXT_INFO);
+ sb.append(index++).append(". ").append(new String(decryptedText)).append(NEWLINE);
+ }
+ return sb.toString();
+ }
}
diff --git a/adservices/samples/topics/sampleappwithnoperm/Android.bp b/adservices/samples/topics/sampleappwithnoperm/Android.bp
index 2f3e59b1d..fbfedd590 100644
--- a/adservices/samples/topics/sampleappwithnoperm/Android.bp
+++ b/adservices/samples/topics/sampleappwithnoperm/Android.bp
@@ -28,11 +28,15 @@ android_app {
],
static_libs: [
"adservices-clients",
+ "adservices-service-core",
"androidx.appcompat_appcompat",
"androidx-constraintlayout_constraintlayout",
"com.google.android.material_material",
"androidx.concurrent_concurrent-futures",
],
+ jni_libs: [
+ "libhpke_jni",
+ ],
resource_dirs: ["res"],
platform_apis: true,
min_sdk_version: "30",
diff --git a/adservices/samples/topics/sampleappwithnoperm/java/com/example/adservices/samples/topics/sampleappwithnoperm/MainActivity.java b/adservices/samples/topics/sampleappwithnoperm/java/com/example/adservices/samples/topics/sampleappwithnoperm/MainActivity.java
index 229a4bf7d..2343bc71a 100644
--- a/adservices/samples/topics/sampleappwithnoperm/java/com/example/adservices/samples/topics/sampleappwithnoperm/MainActivity.java
+++ b/adservices/samples/topics/sampleappwithnoperm/java/com/example/adservices/samples/topics/sampleappwithnoperm/MainActivity.java
@@ -18,6 +18,7 @@ package com.example.adservices.samples.topics.sampleappwithnoperm;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.EncryptedTopic;
import android.adservices.topics.GetTopicsResponse;
import android.adservices.topics.Topic;
import android.os.Bundle;
@@ -28,14 +29,18 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
+import com.android.adservices.HpkeJni;
+
+import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import java.io.StringWriter;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -53,6 +58,12 @@ public class MainActivity extends AppCompatActivity {
private static final String TAG = "SampleApp";
private static final List<String> SDK_NAMES =
new ArrayList<>(Arrays.asList("SdkName1", "SdkName2"));
+ // Test constants for testing encryption
+ private static final String TEST_PRIVATE_KEY_BASE64 =
+ "f86EzLmGaVmc+PwjJk5ADPE4ijQvliWf0CQyY/Zyy7I=";
+ private static final byte[] DECODED_PRIVATE_KEY =
+ Base64.getDecoder().decode(TEST_PRIVATE_KEY_BASE64);
+ private static final byte[] EMPTY_CONTEXT_INFO = new byte[] {};
private Button mTopicsClientButton;
private TextView mResultTextView;
private AdvertisingTopicsClient mAdvertisingTopicsClient;
@@ -89,25 +100,42 @@ public class MainActivity extends AppCompatActivity {
public void onSuccess(GetTopicsResponse result) {
Log.d(TAG, "GetTopics for sdk " + sdkName + " succeeded!");
String topics = getTopics(result.getTopics());
+ String encryptedTopicsDecrypted =
+ getDecryptedTopics(result.getEncryptedTopics());
+
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ sdkName
+ + "'s topics: "
+ + NEWLINE
+ + topics
+ + NEWLINE);
+ mResultTextView.append(
+ sdkName
+ + "'s encrypted topics,"
+ + " decrypted: "
+ + NEWLINE
+ + encryptedTopicsDecrypted
+ + NEWLINE);
+ }
+ });
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
+ Log.d(
+ TAG,
sdkName
+ "'s topics: "
+ NEWLINE
+ topics
+ NEWLINE);
- }
- });
-
Log.d(
TAG,
sdkName
- + "'s topics: "
+ + "'s encrypted topics, decrypted: "
+ NEWLINE
- + topics
+ + encryptedTopicsDecrypted
+ NEWLINE);
}
@@ -124,17 +152,18 @@ public class MainActivity extends AppCompatActivity {
+ ": "
+ t.getMessage());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
- "Failed to getTopics for sdk "
- + sdkName
- + ": "
- + t.toString()
- + NEWLINE);
- }
- });
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ "Failed to getTopics for sdk "
+ + sdkName
+ + ": "
+ + t.toString()
+ + NEWLINE);
+ }
+ });
}
},
directExecutor());
@@ -150,4 +179,19 @@ public class MainActivity extends AppCompatActivity {
}
return sb.toString();
}
+
+ private String getDecryptedTopics(List<EncryptedTopic> arr) {
+ StringBuilder sb = new StringBuilder();
+ int index = 1;
+ for (EncryptedTopic encryptedTopic : arr) {
+ byte[] cipherText =
+ Bytes.concat(
+ encryptedTopic.getEncapsulatedKey(),
+ encryptedTopic.getEncryptedTopic());
+ byte[] decryptedText =
+ HpkeJni.decrypt(DECODED_PRIVATE_KEY, cipherText, EMPTY_CONTEXT_INFO);
+ sb.append(index++).append(". ").append(new String(decryptedText)).append(NEWLINE);
+ }
+ return sb.toString();
+ }
}
diff --git a/adservices/samples/topics/sampleappwithoptoutall/Android.bp b/adservices/samples/topics/sampleappwithoptoutall/Android.bp
index fa7910917..02970f432 100644
--- a/adservices/samples/topics/sampleappwithoptoutall/Android.bp
+++ b/adservices/samples/topics/sampleappwithoptoutall/Android.bp
@@ -28,11 +28,15 @@ android_app {
],
static_libs: [
"adservices-clients",
+ "adservices-service-core",
"androidx.appcompat_appcompat",
"androidx-constraintlayout_constraintlayout",
"com.google.android.material_material",
"androidx.concurrent_concurrent-futures",
],
+ jni_libs: [
+ "libhpke_jni",
+ ],
resource_dirs: ["res"],
platform_apis: true,
min_sdk_version: "30",
diff --git a/adservices/samples/topics/sampleappwithoptoutall/java/com/example/adservices/samples/topics/sampleappwithoptoutall/MainActivity.java b/adservices/samples/topics/sampleappwithoptoutall/java/com/example/adservices/samples/topics/sampleappwithoptoutall/MainActivity.java
index e65d42ea4..e1208e724 100644
--- a/adservices/samples/topics/sampleappwithoptoutall/java/com/example/adservices/samples/topics/sampleappwithoptoutall/MainActivity.java
+++ b/adservices/samples/topics/sampleappwithoptoutall/java/com/example/adservices/samples/topics/sampleappwithoptoutall/MainActivity.java
@@ -18,6 +18,7 @@ package com.example.adservices.samples.topics.sampleappwithoptoutall;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import android.adservices.clients.topics.AdvertisingTopicsClient;
+import android.adservices.topics.EncryptedTopic;
import android.adservices.topics.GetTopicsResponse;
import android.adservices.topics.Topic;
import android.os.Bundle;
@@ -28,14 +29,18 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
+import com.android.adservices.HpkeJni;
+
+import com.google.common.primitives.Bytes;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import java.io.StringWriter;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -53,6 +58,12 @@ public class MainActivity extends AppCompatActivity {
private static final String TAG = "SampleApp";
private static final List<String> SDK_NAMES =
new ArrayList<>(Arrays.asList("SdkName1", "SdkName2"));
+ // Test constants for testing encryption
+ private static final String TEST_PRIVATE_KEY_BASE64 =
+ "f86EzLmGaVmc+PwjJk5ADPE4ijQvliWf0CQyY/Zyy7I=";
+ private static final byte[] DECODED_PRIVATE_KEY =
+ Base64.getDecoder().decode(TEST_PRIVATE_KEY_BASE64);
+ private static final byte[] EMPTY_CONTEXT_INFO = new byte[] {};
private Button mTopicsClientButton;
private TextView mResultTextView;
private AdvertisingTopicsClient mAdvertisingTopicsClient;
@@ -89,25 +100,42 @@ public class MainActivity extends AppCompatActivity {
public void onSuccess(GetTopicsResponse result) {
Log.d(TAG, "GetTopics for sdk " + sdkName + " succeeded!");
String topics = getTopics(result.getTopics());
+ String encryptedTopicsDecrypted =
+ getDecryptedTopics(result.getEncryptedTopics());
+
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ sdkName
+ + "'s topics: "
+ + NEWLINE
+ + topics
+ + NEWLINE);
+ mResultTextView.append(
+ sdkName
+ + "'s encrypted topics,"
+ + " decrypted: "
+ + NEWLINE
+ + encryptedTopicsDecrypted
+ + NEWLINE);
+ }
+ });
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
+ Log.d(
+ TAG,
sdkName
+ "'s topics: "
+ NEWLINE
+ topics
+ NEWLINE);
- }
- });
-
Log.d(
TAG,
sdkName
- + "'s topics: "
+ + "'s encrypted topics, decrypted: "
+ NEWLINE
- + topics
+ + encryptedTopicsDecrypted
+ NEWLINE);
}
@@ -124,17 +152,18 @@ public class MainActivity extends AppCompatActivity {
+ ": "
+ t.getMessage());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mResultTextView.append(
- "Failed to getTopics for sdk "
- + sdkName
- + ": "
- + t.toString()
- + NEWLINE);
- }
- });
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.append(
+ "Failed to getTopics for sdk "
+ + sdkName
+ + ": "
+ + t.toString()
+ + NEWLINE);
+ }
+ });
}
},
directExecutor());
@@ -150,4 +179,19 @@ public class MainActivity extends AppCompatActivity {
}
return sb.toString();
}
+
+ private String getDecryptedTopics(List<EncryptedTopic> arr) {
+ StringBuilder sb = new StringBuilder();
+ int index = 1;
+ for (EncryptedTopic encryptedTopic : arr) {
+ byte[] cipherText =
+ Bytes.concat(
+ encryptedTopic.getEncapsulatedKey(),
+ encryptedTopic.getEncryptedTopic());
+ byte[] decryptedText =
+ HpkeJni.decrypt(DECODED_PRIVATE_KEY, cipherText, EMPTY_CONTEXT_INFO);
+ sb.append(index++).append(". ").append(new String(decryptedText)).append(NEWLINE);
+ }
+ return sb.toString();
+ }
}
diff --git a/adservices/service-core/Android.bp b/adservices/service-core/Android.bp
index be523ebc5..e74241e52 100644
--- a/adservices/service-core/Android.bp
+++ b/adservices/service-core/Android.bp
@@ -201,7 +201,10 @@ cc_library_shared {
shared_libs: ["liblog",],
static_libs: ["libact", "libcrypto_static"],
version_script: "jni/version-script.lds",
- apex_available: ["com.android.adservices", "com.android.extservices"],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.adservices",
+ "com.android.extservices"],
visibility: [
"//packages/modules/AdServices:__subpackages__",
"//packages/modules/ExtServices:__subpackages__",
diff --git a/adservices/service-core/java/com/android/adservices/data/adselection/EncryptionKeyDao.java b/adservices/service-core/java/com/android/adservices/data/adselection/EncryptionKeyDao.java
index 6b32c9f41..bd0ac8b4b 100644
--- a/adservices/service-core/java/com/android/adservices/data/adselection/EncryptionKeyDao.java
+++ b/adservices/service-core/java/com/android/adservices/data/adselection/EncryptionKeyDao.java
@@ -24,7 +24,7 @@ import androidx.room.Query;
import java.time.Instant;
import java.util.List;
-/** Dao to manage access to entities in the EncryptionKey table. */
+/** Dao to manage access to entities in the Auction Server Encryption Key table. */
@Dao
public abstract class EncryptionKeyDao {
/**
diff --git a/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDao.java b/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDao.java
index 4722f4f1d..78f7c18b5 100644
--- a/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDao.java
+++ b/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDao.java
@@ -2761,6 +2761,9 @@ class MeasurementDao implements IMeasurementDao {
values.put(
MeasurementTables.AsyncRegistrationContract.REQUEST_POST_BODY,
asyncRegistration.getPostBody());
+ values.put(
+ MeasurementTables.AsyncRegistrationContract.REDIRECT_BEHAVIOR,
+ asyncRegistration.getRedirectBehavior().name());
long rowId =
mSQLTransaction
.getDatabase()
diff --git a/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDbHelper.java b/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDbHelper.java
index 30697186a..398f4f661 100644
--- a/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDbHelper.java
+++ b/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementDbHelper.java
@@ -50,6 +50,7 @@ import com.android.adservices.data.measurement.migration.MeasurementDbMigratorV2
import com.android.adservices.data.measurement.migration.MeasurementDbMigratorV28;
import com.android.adservices.data.measurement.migration.MeasurementDbMigratorV29;
import com.android.adservices.data.measurement.migration.MeasurementDbMigratorV30;
+import com.android.adservices.data.measurement.migration.MeasurementDbMigratorV31;
import com.android.adservices.data.measurement.migration.MeasurementDbMigratorV7;
import com.android.adservices.data.measurement.migration.MeasurementDbMigratorV8;
import com.android.adservices.data.measurement.migration.MeasurementDbMigratorV9;
@@ -69,7 +70,7 @@ import java.util.stream.Stream;
public class MeasurementDbHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME =
FileCompatUtils.getAdservicesFilename("adservices_msmt.db");
- public static final int CURRENT_DATABASE_VERSION = 30;
+ public static final int CURRENT_DATABASE_VERSION = 31;
public static final int OLD_DATABASE_FINAL_VERSION = 6;
private static MeasurementDbHelper sSingleton = null;
@@ -171,7 +172,8 @@ public class MeasurementDbHelper extends SQLiteOpenHelper {
new MeasurementDbMigratorV27(),
new MeasurementDbMigratorV28(),
new MeasurementDbMigratorV29(),
- new MeasurementDbMigratorV30());
+ new MeasurementDbMigratorV30(),
+ new MeasurementDbMigratorV31());
}
private boolean hasAllV6MeasurementTables(SQLiteDatabase db) {
diff --git a/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementTables.java b/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementTables.java
index 8e249191e..2ffd42877 100644
--- a/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementTables.java
+++ b/adservices/service-core/java/com/android/adservices/data/measurement/MeasurementTables.java
@@ -93,6 +93,7 @@ public final class MeasurementTables {
String REGISTRATION_ID = "registration_id";
String PLATFORM_AD_ID = "platform_ad_id";
String REQUEST_POST_BODY = "request_post_body";
+ String REDIRECT_BEHAVIOR = "redirect_behavior";
}
/** Contract for Source. */
@@ -327,39 +328,41 @@ public final class MeasurementTables {
public static final String CREATE_TABLE_ASYNC_REGISTRATION_LATEST =
"CREATE TABLE "
- + MeasurementTables.AsyncRegistrationContract.TABLE
+ + AsyncRegistrationContract.TABLE
+ " ("
- + MeasurementTables.AsyncRegistrationContract.ID
+ + AsyncRegistrationContract.ID
+ " TEXT PRIMARY KEY NOT NULL, "
- + MeasurementTables.AsyncRegistrationContract.REGISTRATION_URI
+ + AsyncRegistrationContract.REGISTRATION_URI
+ " TEXT, "
- + MeasurementTables.AsyncRegistrationContract.WEB_DESTINATION
+ + AsyncRegistrationContract.WEB_DESTINATION
+ " TEXT, "
- + MeasurementTables.AsyncRegistrationContract.OS_DESTINATION
+ + AsyncRegistrationContract.OS_DESTINATION
+ " TEXT, "
- + MeasurementTables.AsyncRegistrationContract.VERIFIED_DESTINATION
+ + AsyncRegistrationContract.VERIFIED_DESTINATION
+ " TEXT, "
- + MeasurementTables.AsyncRegistrationContract.TOP_ORIGIN
+ + AsyncRegistrationContract.TOP_ORIGIN
+ " TEXT, "
- + MeasurementTables.AsyncRegistrationContract.SOURCE_TYPE
+ + AsyncRegistrationContract.SOURCE_TYPE
+ " INTEGER, "
- + MeasurementTables.AsyncRegistrationContract.REGISTRANT
+ + AsyncRegistrationContract.REGISTRANT
+ " TEXT, "
- + MeasurementTables.AsyncRegistrationContract.REQUEST_TIME
+ + AsyncRegistrationContract.REQUEST_TIME
+ " INTEGER, "
- + MeasurementTables.AsyncRegistrationContract.RETRY_COUNT
+ + AsyncRegistrationContract.RETRY_COUNT
+ " INTEGER, "
- + MeasurementTables.AsyncRegistrationContract.TYPE
+ + AsyncRegistrationContract.TYPE
+ " INTEGER, "
- + MeasurementTables.AsyncRegistrationContract.DEBUG_KEY_ALLOWED
+ + AsyncRegistrationContract.DEBUG_KEY_ALLOWED
+ " INTEGER, "
- + MeasurementTables.AsyncRegistrationContract.AD_ID_PERMISSION
+ + AsyncRegistrationContract.AD_ID_PERMISSION
+ " INTEGER, "
- + MeasurementTables.AsyncRegistrationContract.REGISTRATION_ID
+ + AsyncRegistrationContract.REGISTRATION_ID
+ " TEXT NOT NULL,"
- + MeasurementTables.AsyncRegistrationContract.PLATFORM_AD_ID
+ + AsyncRegistrationContract.PLATFORM_AD_ID
+ " TEXT, "
+ AsyncRegistrationContract.REQUEST_POST_BODY
+ + " TEXT, "
+ + AsyncRegistrationContract.REDIRECT_BEHAVIOR
+ " TEXT "
+ ")";
diff --git a/adservices/service-core/java/com/android/adservices/data/measurement/SqliteObjectMapper.java b/adservices/service-core/java/com/android/adservices/data/measurement/SqliteObjectMapper.java
index 671b5db98..cb5aee7e5 100644
--- a/adservices/service-core/java/com/android/adservices/data/measurement/SqliteObjectMapper.java
+++ b/adservices/service-core/java/com/android/adservices/data/measurement/SqliteObjectMapper.java
@@ -27,6 +27,7 @@ import com.android.adservices.service.measurement.Source;
import com.android.adservices.service.measurement.Trigger;
import com.android.adservices.service.measurement.aggregation.AggregateEncryptionKey;
import com.android.adservices.service.measurement.aggregation.AggregateReport;
+import com.android.adservices.service.measurement.registration.AsyncRedirect;
import com.android.adservices.service.measurement.registration.AsyncRegistration;
import com.android.adservices.service.measurement.reporting.DebugReport;
import com.android.adservices.service.measurement.util.UnsignedLong;
@@ -471,6 +472,14 @@ public class SqliteObjectMapper {
cursor,
MeasurementTables.AsyncRegistrationContract.REQUEST_POST_BODY,
builder::setPostBody);
+ setTextColumn(
+ cursor,
+ MeasurementTables.AsyncRegistrationContract.REDIRECT_BEHAVIOR,
+ (enumValue) ->
+ builder.setRedirectBehavior(
+ enumValue == null
+ ? null
+ : AsyncRedirect.RedirectBehavior.valueOf(enumValue)));
return builder.build();
}
diff --git a/adservices/service-core/java/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV31.java b/adservices/service-core/java/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV31.java
new file mode 100644
index 000000000..72f150e0d
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV31.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 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.data.measurement.migration;
+
+import android.annotation.NonNull;
+import android.content.ContentValues;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.android.adservices.LoggerFactory;
+import com.android.adservices.data.measurement.MeasurementTables;
+import com.android.adservices.service.measurement.registration.AsyncRedirect;
+
+import java.util.Locale;
+
+/**
+ * Migrates Measurement DB to version 31. This upgrade adds one column in the async registration
+ * table to persist the configuration for redirecting Location type redirects to .well-known path.
+ */
+public class MeasurementDbMigratorV31 extends AbstractMeasurementDbMigrator {
+ public MeasurementDbMigratorV31() {
+ super(31);
+ }
+
+ @Override
+ protected void performMigration(@NonNull SQLiteDatabase db) {
+ addRedirectBehaviorColumn(db);
+ updateRedirectBehaviorForAllAsyncRegistrations(db);
+ }
+
+ private void addRedirectBehaviorColumn(SQLiteDatabase db) {
+ MigrationHelpers.addTextColumnIfAbsent(
+ db,
+ MeasurementTables.AsyncRegistrationContract.TABLE,
+ MeasurementTables.AsyncRegistrationContract.REDIRECT_BEHAVIOR);
+ }
+
+ private void updateRedirectBehaviorForAllAsyncRegistrations(@NonNull SQLiteDatabase db) {
+ ContentValues values = new ContentValues();
+ values.put(
+ MeasurementTables.AsyncRegistrationContract.REDIRECT_BEHAVIOR,
+ AsyncRedirect.RedirectBehavior.AS_IS.name());
+ long rows =
+ db.update(
+ MeasurementTables.AsyncRegistrationContract.TABLE,
+ values,
+ null,
+ new String[0]);
+ String log =
+ String.format(
+ Locale.ENGLISH,
+ "Updated %s for %d %s records",
+ MeasurementTables.AsyncRegistrationContract.REDIRECT_BEHAVIOR,
+ rows,
+ MeasurementTables.AsyncRegistrationContract.TABLE);
+ LoggerFactory.getMeasurementLogger().d(log);
+ }
+}
diff --git a/adservices/service-core/java/com/android/adservices/data/signals/DBSignalsUpdateMetadata.java b/adservices/service-core/java/com/android/adservices/data/signals/DBSignalsUpdateMetadata.java
new file mode 100644
index 000000000..67204d719
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/data/signals/DBSignalsUpdateMetadata.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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.data.signals;
+
+import android.adservices.common.AdTechIdentifier;
+
+import androidx.annotation.NonNull;
+import androidx.room.ColumnInfo;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+
+import com.google.auto.value.AutoValue;
+
+import java.time.Instant;
+
+/** Represents an entry for signals update metadata. */
+@AutoValue
+@AutoValue.CopyAnnotations
+@Entity(tableName = DBSignalsUpdateMetadata.TABLE_NAME, inheritSuperIndices = true)
+public abstract class DBSignalsUpdateMetadata {
+
+ public static final String TABLE_NAME = "signals_update_metadata";
+
+ /** The ad-tech buyer */
+ @AutoValue.CopyAnnotations
+ @ColumnInfo(name = "buyer")
+ @PrimaryKey
+ @NonNull
+ public abstract AdTechIdentifier getBuyer();
+
+ /** The last time update happened to a buyer's signals */
+ @AutoValue.CopyAnnotations
+ @ColumnInfo(name = "last_signals_updated_time")
+ public abstract Instant getLastSignalsUpdatedTime();
+
+ /**
+ * @return an instance of {@link DBSignalsUpdateMetadata}
+ */
+ public static DBSignalsUpdateMetadata create(
+ @NonNull AdTechIdentifier buyer, @NonNull Instant lastSignalsUpdatedTime) {
+ return builder().setBuyer(buyer).setLastSignalsUpdatedTime(lastSignalsUpdatedTime).build();
+ }
+
+ /**
+ * @return a builder for creating a {@link DBSignalsUpdateMetadata}
+ */
+ public static DBSignalsUpdateMetadata.Builder builder() {
+ return new AutoValue_DBSignalsUpdateMetadata.Builder();
+ }
+
+ /** Provides a builder to create an instance of {@link DBSignalsUpdateMetadata} */
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ /** For more details see {@link #getBuyer()} */
+ public abstract DBSignalsUpdateMetadata.Builder setBuyer(@NonNull AdTechIdentifier value);
+
+ /** For more details see {@link #getLastSignalsUpdatedTime()} ()} */
+ public abstract DBSignalsUpdateMetadata.Builder setLastSignalsUpdatedTime(
+ @NonNull Instant value);
+
+ /**
+ * @return an instance of {@link DBSignalsUpdateMetadata}
+ */
+ public abstract DBSignalsUpdateMetadata build();
+ }
+}
diff --git a/adservices/service-core/java/com/android/adservices/data/signals/EncoderLogicHandler.java b/adservices/service-core/java/com/android/adservices/data/signals/EncoderLogicHandler.java
index 0c21c6f57..10f2770a4 100644
--- a/adservices/service-core/java/com/android/adservices/data/signals/EncoderLogicHandler.java
+++ b/adservices/service-core/java/com/android/adservices/data/signals/EncoderLogicHandler.java
@@ -61,6 +61,7 @@ public class EncoderLogicHandler {
@NonNull private final EncoderPersistenceDao mEncoderPersistenceDao;
@NonNull private final EncoderEndpointsDao mEncoderEndpointsDao;
@NonNull private final EncoderLogicMetadataDao mEncoderLogicMetadataDao;
+ @NonNull private final ProtectedSignalsDao mProtectedSignalsDao;
@NonNull private final AdServicesHttpsClient mAdServicesHttpsClient;
@NonNull private final ListeningExecutorService mBackgroundExecutorService;
@@ -77,16 +78,19 @@ public class EncoderLogicHandler {
@NonNull EncoderPersistenceDao encoderPersistenceDao,
@NonNull EncoderEndpointsDao encoderEndpointsDao,
@NonNull EncoderLogicMetadataDao encoderLogicMetadataDao,
+ @NonNull ProtectedSignalsDao protectedSignalsDao,
@NonNull AdServicesHttpsClient httpsClient,
@NonNull ListeningExecutorService backgroundExecutorService) {
Objects.requireNonNull(encoderPersistenceDao);
Objects.requireNonNull(encoderEndpointsDao);
Objects.requireNonNull(encoderLogicMetadataDao);
+ Objects.requireNonNull(protectedSignalsDao);
Objects.requireNonNull(httpsClient);
Objects.requireNonNull(backgroundExecutorService);
mEncoderPersistenceDao = encoderPersistenceDao;
mEncoderEndpointsDao = encoderEndpointsDao;
mEncoderLogicMetadataDao = encoderLogicMetadataDao;
+ mProtectedSignalsDao = protectedSignalsDao;
mAdServicesHttpsClient = httpsClient;
mBackgroundExecutorService = backgroundExecutorService;
}
@@ -96,6 +100,7 @@ public class EncoderLogicHandler {
EncoderPersistenceDao.getInstance(context),
ProtectedSignalsDatabase.getInstance(context).getEncoderEndpointsDao(),
ProtectedSignalsDatabase.getInstance(context).getEncoderLogicMetadataDao(),
+ ProtectedSignalsDatabase.getInstance(context).protectedSignalsDao(),
new AdServicesHttpsClient(
AdServicesExecutors.getBackgroundExecutor(),
CacheProviderFactory.createNoOpCache()),
@@ -265,6 +270,7 @@ public class EncoderLogicHandler {
mEncoderLogicMetadataDao.deleteEncoder(buyer);
mEncoderPersistenceDao.deleteEncoder(buyer);
mEncoderEndpointsDao.deleteEncoderEndpoint(buyer);
+ mProtectedSignalsDao.deleteSignalsUpdateMetadata(buyer);
buyerLock.unlock();
}
}
diff --git a/adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDao.java b/adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDao.java
index f30770821..d0a4a8169 100644
--- a/adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDao.java
+++ b/adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDao.java
@@ -23,12 +23,14 @@ import androidx.annotation.NonNull;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
+import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Transaction;
import com.android.adservices.data.common.CleanupUtils;
import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.service.Flags;
+import com.android.internal.annotations.VisibleForTesting;
import java.time.Instant;
import java.util.List;
@@ -76,10 +78,17 @@ public abstract class ProtectedSignalsDao {
*/
@Transaction
public void insertAndDelete(
+ @NonNull AdTechIdentifier buyer,
+ @NonNull Instant now,
@NonNull List<DBProtectedSignal> signalsToInsert,
@NonNull List<DBProtectedSignal> signalsToDelete) {
insertSignals(signalsToInsert);
deleteSignals(signalsToDelete);
+ persistSignalsUpdateMetadata(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer)
+ .setLastSignalsUpdatedTime(now)
+ .build());
}
/**
@@ -88,7 +97,31 @@ public abstract class ProtectedSignalsDao {
* @return the number of deleted signals
*/
@Query("DELETE FROM protected_signals WHERE creationTime < :expiryTime")
- public abstract int deleteSignalsBeforeTime(@NonNull Instant expiryTime);
+ protected abstract int deleteSignalsBeforeTime(@NonNull Instant expiryTime);
+
+ /** Returns buyers with expired signals. */
+ @Query("SELECT DISTINCT buyer FROM protected_signals WHERE creationTime < :expiryTime")
+ protected abstract List<AdTechIdentifier> getBuyersWithExpiredSignals(
+ @NonNull Instant expiryTime);
+
+ /**
+ * Deletes expired signals and updates buyer metadata.
+ *
+ * @return the number of deleted signals
+ */
+ @Transaction
+ public int deleteExpiredSignalsAndUpdateSignalsUpdateMetadata(
+ @NonNull Instant expiryTime, @NonNull Instant now) {
+ List<AdTechIdentifier> buyers = getBuyersWithExpiredSignals(expiryTime);
+ for (AdTechIdentifier buyer : buyers) {
+ persistSignalsUpdateMetadata(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer)
+ .setLastSignalsUpdatedTime(now)
+ .build());
+ }
+ return deleteSignalsBeforeTime(expiryTime);
+ }
/**
* Deletes all signals belonging to disallowed buyer ad techs in a single transaction, where the
@@ -111,6 +144,9 @@ public abstract class ProtectedSignalsDao {
int numDeletedEvents = 0;
if (!buyersToRemove.isEmpty()) {
numDeletedEvents = deleteByBuyers(buyersToRemove);
+ for (AdTechIdentifier buyer : buyersToRemove) {
+ deleteSignalsUpdateMetadata(buyer);
+ }
}
return numDeletedEvents;
@@ -141,10 +177,11 @@ public abstract class ProtectedSignalsDao {
* @return the number of deleted signals
*/
@Transaction
- public int deleteAllDisallowedPackageSignals(
- @NonNull PackageManager packageManager, @NonNull Flags flags) {
+ public int deleteAllDisallowedPackageSignalsAndUpdateSignalUpdateMetadata(
+ @NonNull PackageManager packageManager, @NonNull Flags flags, @NonNull Instant now) {
Objects.requireNonNull(packageManager);
Objects.requireNonNull(flags);
+ Objects.requireNonNull(now);
List<String> sourceAppsToRemove = getAllPackages();
if (sourceAppsToRemove.isEmpty()) {
@@ -155,6 +192,14 @@ public abstract class ProtectedSignalsDao {
int numDeletedEvents = 0;
if (!sourceAppsToRemove.isEmpty()) {
+ List<AdTechIdentifier> buyers = getBuyersForPackages(sourceAppsToRemove);
+ for (AdTechIdentifier buyer : buyers) {
+ persistSignalsUpdateMetadata(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer)
+ .setLastSignalsUpdatedTime(now)
+ .build());
+ }
numDeletedEvents = deleteSignalsByPackage(sourceAppsToRemove);
// TODO(b/300661099): Collect and send telemetry on signal deletion
}
@@ -165,7 +210,8 @@ public abstract class ProtectedSignalsDao {
* Returns the list of all unique packages in the signals table.
*
* <p>This method is not meant to be called externally, but is a helper for {@link
- * #deleteAllDisallowedPackageSignals}
+ * #deleteAllDisallowedPackageSignalsAndUpdateSignalUpdateMetadata(PackageManager, Flags,
+ * Instant)}
*/
@Query("SELECT DISTINCT packageName FROM protected_signals")
protected abstract List<String> getAllPackages();
@@ -174,10 +220,33 @@ public abstract class ProtectedSignalsDao {
* Deletes all signals generated from the given packages.
*
* <p>This method is not meant to be called externally, but is a helper for {@link
- * #deleteAllDisallowedPackageSignals}
+ * #deleteAllDisallowedPackageSignalsAndUpdateSignalUpdateMetadata(PackageManager, Flags,
+ * Instant)}
*
* @return the number of deleted histogram events
*/
@Query("DELETE FROM protected_signals WHERE packageName in (:packages)")
protected abstract int deleteSignalsByPackage(@NonNull List<String> packages);
+
+ /** Returns all buyers for the given packages. */
+ @Query("SELECT DISTINCT buyer FROM protected_signals WHERE packageName in (:packages)")
+ protected abstract List<AdTechIdentifier> getBuyersForPackages(@NonNull List<String> packages);
+
+ /** Create or update a buyer metadata entry. */
+ @Insert(entity = DBSignalsUpdateMetadata.class, onConflict = OnConflictStrategy.REPLACE)
+ @VisibleForTesting
+ protected abstract long persistSignalsUpdateMetadata(
+ DBSignalsUpdateMetadata dbSignalsUpdateMetadata);
+
+ /** Returns a metadata entry according to the buyer. */
+ @Query("SELECT * FROM signals_update_metadata WHERE buyer=:buyer")
+ public abstract DBSignalsUpdateMetadata getSignalsUpdateMetadata(AdTechIdentifier buyer);
+
+ /** Delete the metadata for the buyer. */
+ @Query("DELETE FROM signals_update_metadata WHERE buyer=:buyer")
+ public abstract void deleteSignalsUpdateMetadata(AdTechIdentifier buyer);
+
+ /** Delete all metadata in the storage. */
+ @Query("DELETE FROM signals_update_metadata")
+ public abstract void deleteAllSignalsUpdateMetadata();
}
diff --git a/adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDatabase.java b/adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDatabase.java
index ee6b3bc26..d068e2a48 100644
--- a/adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDatabase.java
+++ b/adservices/service-core/java/com/android/adservices/data/signals/ProtectedSignalsDatabase.java
@@ -35,18 +35,20 @@ import java.util.Objects;
DBProtectedSignal.class,
DBEncoderEndpoint.class,
DBEncoderLogicMetadata.class,
- DBEncodedPayload.class
+ DBEncodedPayload.class,
+ DBSignalsUpdateMetadata.class,
},
autoMigrations = {
@AutoMigration(from = 1, to = 2),
@AutoMigration(from = 2, to = 3),
+ @AutoMigration(from = 3, to = 4)
},
version = ProtectedSignalsDatabase.DATABASE_VERSION)
@TypeConverters({FledgeRoomConverters.class})
public abstract class ProtectedSignalsDatabase extends RoomDatabase {
private static final Object SINGLETON_LOCK = new Object();
- public static final int DATABASE_VERSION = 3;
+ public static final int DATABASE_VERSION = 4;
public static final String DATABASE_NAME =
FileCompatUtils.getAdservicesFilename("protectedsignals.db");
diff --git a/adservices/service-core/java/com/android/adservices/service/Flags.java b/adservices/service-core/java/com/android/adservices/service/Flags.java
index 200ccec1f..774504370 100644
--- a/adservices/service-core/java/com/android/adservices/service/Flags.java
+++ b/adservices/service-core/java/com/android/adservices/service/Flags.java
@@ -117,6 +117,18 @@ public interface Flags extends CommonFlags {
}
/**
+ * Flag to override base64 public key used for encryption testing.
+ *
+ * <p>Note: Default value for this flag should not be changed from empty.
+ */
+ String TOPICS_TEST_ENCRYPTION_PUBLIC_KEY = "";
+
+ /** Returns test public key used for encrypting topics for testing. */
+ default String getTopicsTestEncryptionPublicKey() {
+ return TOPICS_TEST_ENCRYPTION_PUBLIC_KEY;
+ }
+
+ /**
* Returns the number of epochs to look back when deciding if a caller has observed a topic
* before.
*/
@@ -697,7 +709,7 @@ public interface Flags extends CommonFlags {
return MEASUREMENT_FLEX_API_MAX_INFORMATION_GAIN_EVENT;
}
- float MEASUREMENT_FLEX_API_MAX_INFORMATION_GAIN_NAVIGATION = 11.46173F;
+ float MEASUREMENT_FLEX_API_MAX_INFORMATION_GAIN_NAVIGATION = 11.5F;
/** Returns max information gain in Flexible Event API for Navigation sources */
default float getMeasurementFlexApiMaxInformationGainNavigation() {
@@ -3419,14 +3431,6 @@ public interface Flags extends CommonFlags {
return DEFAULT_ADSERVICES_VERSION_MAPPINGS;
}
- /** Default Determines whether EU notification flow change is enabled. */
- boolean DEFAULT_EU_NOTIF_FLOW_CHANGE_ENABLED = true;
-
- /** Determines whether EU notification flow change is enabled. */
- default boolean getEuNotifFlowChangeEnabled() {
- return DEFAULT_EU_NOTIF_FLOW_CHANGE_ENABLED;
- }
-
/** Default value for Measurement flexible event reporting API */
boolean MEASUREMENT_FLEXIBLE_EVENT_REPORTING_API_ENABLED = false;
@@ -3518,14 +3522,6 @@ public interface Flags extends CommonFlags {
return MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS;
}
- /** Disable early reporting windows configurability by default. */
- boolean MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS = false;
-
- /** Returns true if event reporting windows configurability is enabled, false otherwise. */
- default boolean getMeasurementEnableConfigurableEventReportingWindows() {
- return MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS;
- }
-
/**
* Default early reporting windows for VTC type source. Derived from {@link
* com.android.adservices.service.measurement.PrivacyParams#EVENT_EARLY_REPORTING_WINDOW_MILLISECONDS}.
@@ -3585,18 +3581,8 @@ public interface Flags extends CommonFlags {
return MEASUREMENT_AGGREGATE_REPORT_DELAY_CONFIG;
}
- /** Disable conversions configurability by default. */
- boolean DEFAULT_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS = false;
-
- /**
- * Returns true, if event reports max conversions configurability is enabled, false otherwise.
- */
- default boolean getMeasurementEnableVtcConfigurableMaxEventReports() {
- return DEFAULT_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS;
- }
-
- /** Disable conversions configurability by default. */
- int DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT = 2;
+ /** Default max allowed number of event reports. */
+ int DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT = 1;
/** Returns the default max allowed number of event reports. */
default int getMeasurementVtcConfigurableMaxEventReportsCount() {
@@ -3979,11 +3965,11 @@ public interface Flags extends CommonFlags {
}
/** Default RVC NOTIFICATION feature flag.. */
- boolean DEFAULT_RVC_NOTIFICATION_ENABLED = false;
+ boolean DEFAULT_RVC_POST_OTA_NOTIFICATION_ENABLED = false;
/** RVC Notification feature flag.. */
- default boolean getEnableRvcNotification() {
- return DEFAULT_RVC_NOTIFICATION_ENABLED;
+ default boolean getEnableRvcPostOtaNotification() {
+ return DEFAULT_RVC_POST_OTA_NOTIFICATION_ENABLED;
}
/** Default enableAdServices system API feature flag.. */
@@ -4100,76 +4086,6 @@ public interface Flags extends CommonFlags {
return MEASUREMENT_MIN_REPORTING_ORIGIN_UPDATE_WINDOW;
}
- float MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY = 0.0000208f;
-
- /**
- * {@link Source} Noise probability for 'Event' when both destinations (app and web) are
- * available on the source and supports install attribution.
- */
- default float getMeasurementInstallAttrDualDestinationEventNoiseProbability() {
- return MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY;
- }
-
- float MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY = 0.0170218f;
-
- /**
- * {@link Source} Noise probability for 'Navigation' when both destinations (app and web) are
- * available on the source.
- */
- default float getMeasurementDualDestinationNavigationNoiseProbability() {
- return MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY;
- }
-
- float MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY =
- MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY;
-
- /**
- * {@link Source} Noise probability for 'Navigation' when both destinations (app and web) are
- * available on the source and supports install attribution.
- */
- default float getMeasurementInstallAttrDualDestinationNavigationNoiseProbability() {
- return MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY;
- }
-
- float MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY = 0.0000042f;
-
- /**
- * {@link Source} Noise probability for 'Event' when both destinations (app and web) are
- * available on the source.
- */
- default float getMeasurementDualDestinationEventNoiseProbability() {
- return MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY;
- }
-
- float MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY = 0.0000125f;
-
- /** {@link Source} Noise probability for 'Event' which supports install attribution. */
- default float getMeasurementInstallAttrEventNoiseProbability() {
- return MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY;
- }
-
- float MEASUREMENT_EVENT_NOISE_PROBABILITY = 0.0000025f;
-
- /** {@link Source} Noise probability for 'Event'. */
- default float getMeasurementEventNoiseProbability() {
- return MEASUREMENT_EVENT_NOISE_PROBABILITY;
- }
-
- float MEASUREMENT_NAVIGATION_NOISE_PROBABILITY = 0.0024263f;
-
- /** {@link Source} Noise probability for 'Navigation'. */
- default float getMeasurementNavigationNoiseProbability() {
- return MEASUREMENT_NAVIGATION_NOISE_PROBABILITY;
- }
-
- float MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY =
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY;
-
- /** {@link Source} Noise probability for 'Navigation' which supports install attribution. */
- default float getMeasurementInstallAttrNavigationNoiseProbability() {
- return MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY;
- }
-
boolean MEASUREMENT_ENABLE_PREINSTALL_CHECK = false;
/** Returns true when pre-install check is enabled. */
@@ -4281,6 +4197,16 @@ public interface Flags extends CommonFlags {
}
/**
+ * Flag to control whether redirect registration urls should be modified to prefix the path
+ * string with .well-known
+ */
+ boolean MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH = false;
+
+ default boolean getMeasurementEnableRedirectToWellKnownPath() {
+ return MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH;
+ }
+
+ /**
* Default whether to limit logging for enrollment metrics to avoid performance issues. This
* includes not logging data that requires database queries and downloading MDD files.
*/
@@ -4499,4 +4425,28 @@ public interface Flags extends CommonFlags {
default int getBackgroundJobSamplingLoggingRate() {
return DEFAULT_BACKGROUND_JOB_SAMPLING_LOGGING_RATE;
}
+
+ /** Default value of the timeout for AppSearch write operations */
+ int DEFAULT_APPSEARCH_WRITE_TIMEOUT_MS = 3000;
+
+ /**
+ * Gets the value of the timeout for AppSearch write operations, in milliseconds.
+ *
+ * @return the timeout, in milliseconds, for AppSearch write operations
+ */
+ default int getAppSearchWriteTimeout() {
+ return DEFAULT_APPSEARCH_WRITE_TIMEOUT_MS;
+ }
+
+ /** Default value of the timeout for AppSearch read operations */
+ int DEFAULT_APPSEARCH_READ_TIMEOUT_MS = 500;
+
+ /**
+ * Gets the value of the timeout for AppSearch read operations, in milliseconds.
+ *
+ * @return the timeout, in milliseconds, for AppSearch read operations
+ */
+ default int getAppSearchReadTimeout() {
+ return DEFAULT_APPSEARCH_READ_TIMEOUT_MS;
+ }
}
diff --git a/adservices/service-core/java/com/android/adservices/service/FlagsConstants.java b/adservices/service-core/java/com/android/adservices/service/FlagsConstants.java
index 56ca5efe2..cb408cefc 100644
--- a/adservices/service-core/java/com/android/adservices/service/FlagsConstants.java
+++ b/adservices/service-core/java/com/android/adservices/service/FlagsConstants.java
@@ -94,6 +94,8 @@ public final class FlagsConstants {
public static final String KEY_TOPICS_ENCRYPTION_ENABLED = "topics_encryption_enabled";
public static final String KEY_TOPICS_DISABLE_PLAINTEXT_RESPONSE =
"topics_disable_plaintext_response";
+ public static final String KEY_TOPICS_TEST_ENCRYPTION_PUBLIC_KEY =
+ "topics_test_encryption_public_key";
// Topics classifier keys
public static final String KEY_CLASSIFIER_TYPE = "classifier_type";
@@ -284,9 +286,6 @@ public final class FlagsConstants {
public static final String KEY_MEASUREMENT_ENABLE_COARSE_EVENT_REPORT_DESTINATIONS =
"measurement_enable_coarse_event_report_destinations";
- public static final String KEY_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS =
- "measurement_enable_vtc_configurable_max_event_reports_count";
-
public static final String KEY_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT =
"measurement_vtc_configurable_max_event_reports_count";
@@ -811,6 +810,8 @@ public final class FlagsConstants {
public static final String KEY_PPAPI_APP_SIGNATURE_ALLOW_LIST =
"ppapi_app_signature_allow_list";
+ public static final String KEY_APPSEARCH_WRITE_TIMEOUT_MS = "appsearch_write_timeout_ms";
+ public static final String KEY_APPSEARCH_READ_TIMEOUT_MS = "appsearch_read_timeout_ms";
public static final String KEY_APPSEARCH_WRITER_ALLOW_LIST_OVERRIDE =
"appsearch_writer_allow_list_override";
@@ -1069,9 +1070,6 @@ public final class FlagsConstants {
public static final String KEY_MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS =
"measurement_min_event_report_delay_millis";
- public static final String KEY_MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS =
- "measurement_enable_configurable_event_reporting_windows";
-
public static final String KEY_MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS =
"measurement_event_reports_vtc_early_reporting_windows";
@@ -1134,31 +1132,8 @@ public final class FlagsConstants {
public static final String KEY_MEASUREMENT_ENABLE_API_STATUS_ALLOW_LIST_CHECK =
"measurement_enable_api_status_allow_list_check";
- public static final String
- KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY =
- "measurement_install_attr_dual_destination_event_noise_probability";
-
- public static final String KEY_MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY =
- "measurement_dual_destination_navigation_noise_probability";
-
- public static final String
- KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY =
- "measurement_install_attr_dual_destination_navigation_noise_probability";
-
- public static final String KEY_MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY =
- "measurement_dual_destination_event_noise_probability";
-
- public static final String KEY_MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY =
- "measurement_install_attr_event_noise_probability";
-
- public static final String KEY_MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY =
- "measurement_install_attr_navigation_noise_probability";
-
- public static final String KEY_MEASUREMENT_EVENT_NOISE_PROBABILITY =
- "measurement_event_noise_probability";
-
- public static final String KEY_MEASUREMENT_NAVIGATION_NOISE_PROBABILITY =
- "measurement_navigation_noise_probability";
+ public static final String KEY_MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH =
+ "measurement_enable_redirect_to_well_known_path";
// Database Schema Version Flags
public static final String KEY_ENABLE_DATABASE_SCHEMA_VERSION_8 =
@@ -1166,8 +1141,6 @@ public final class FlagsConstants {
public static final String KEY_ENABLE_DATABASE_SCHEMA_VERSION_9 =
"enable_database_schema_version_9";
- public static final String KEY_EU_NOTIF_FLOW_CHANGE_ENABLED = "eu_notif_flow_change_enabled";
-
public static final String KEY_NOTIFICATION_DISMISSED_ON_CLICK =
"notification_dmsmissed_on_click";
@@ -1175,7 +1148,8 @@ public final class FlagsConstants {
public static final String KEY_RVC_UX_ENABLED = "rvc_ux_enabled";
- public static final String KEY_RVC_NOTIFICATION_ENABLED = "rvc_notification_enabled";
+ public static final String KEY_RVC_POST_OTA_NOTIFICATION_ENABLED =
+ "rvc_post_ota_notification_enabled";
public static final String KEY_ENABLE_AD_SERVICES_SYSTEM_API = "enable_ad_services_system_api";
diff --git a/adservices/service-core/java/com/android/adservices/service/PhFlags.java b/adservices/service-core/java/com/android/adservices/service/PhFlags.java
index 28b572092..70948e5dd 100644
--- a/adservices/service-core/java/com/android/adservices/service/PhFlags.java
+++ b/adservices/service-core/java/com/android/adservices/service/PhFlags.java
@@ -16,6 +16,8 @@
package com.android.adservices.service;
+import static com.android.adservices.service.FlagsConstants.KEY_APPSEARCH_READ_TIMEOUT_MS;
+import static com.android.adservices.service.FlagsConstants.KEY_APPSEARCH_WRITE_TIMEOUT_MS;
import static com.android.adservices.service.FlagsConstants.KEY_ENCRYPTION_KEY_JOB_PERIOD_MS;
import static com.android.adservices.service.FlagsConstants.KEY_ENCRYPTION_KEY_JOB_REQUIRED_NETWORK_TYPE;
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_MEASUREMENT_REPORT_AND_REGISTER_EVENT_API_ENABLED;
@@ -245,6 +247,15 @@ public final class PhFlags extends CommonPhFlags implements Flags {
}
@Override
+ public String getTopicsTestEncryptionPublicKey() {
+ // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
+ return DeviceConfig.getString(
+ FlagsConstants.NAMESPACE_ADSERVICES,
+ /* flagName */ FlagsConstants.KEY_TOPICS_TEST_ENCRYPTION_PUBLIC_KEY,
+ /* defaultValue */ TOPICS_TEST_ENCRYPTION_PUBLIC_KEY);
+ }
+
+ @Override
public int getClassifierType() {
// The priority of applying the flag values: SystemProperties, PH (DeviceConfig), then
// hard-coded value.
@@ -3472,16 +3483,6 @@ public final class PhFlags extends CommonPhFlags implements Flags {
}
@Override
- public boolean getMeasurementEnableConfigurableEventReportingWindows() {
- // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
- return DeviceConfig.getBoolean(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants
- .KEY_MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS,
- /* defaultValue */ MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS);
- }
-
- @Override
public String getMeasurementEventReportsVtcEarlyReportingWindows() {
// The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
return DeviceConfig.getString(
@@ -3567,6 +3568,14 @@ public final class PhFlags extends CommonPhFlags implements Flags {
}
@Override
+ public boolean getMeasurementEnableRedirectToWellKnownPath() {
+ return DeviceConfig.getBoolean(
+ FlagsConstants.NAMESPACE_ADSERVICES,
+ /* flagName */ FlagsConstants.KEY_MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH,
+ /* defaultValue */ MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH);
+ }
+
+ @Override
public boolean getFledgeMeasurementReportAndRegisterEventApiEnabled() {
return DeviceConfig.getBoolean(
FlagsConstants.NAMESPACE_ADSERVICES,
@@ -4281,49 +4290,6 @@ public final class PhFlags extends CommonPhFlags implements Flags {
+ getMeasurementMinReportingOriginUpdateWindow());
writer.println(
"\t"
- + FlagsConstants
- .KEY_MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY
- + " = "
- + getMeasurementDualDestinationNavigationNoiseProbability());
- writer.println(
- "\t"
- + FlagsConstants
- .KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY
- + " = "
- + getMeasurementInstallAttrDualDestinationEventNoiseProbability());
- writer.println(
- "\t"
- + FlagsConstants
- .KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY
- + " = "
- + getMeasurementInstallAttrDualDestinationNavigationNoiseProbability());
- writer.println(
- "\t"
- + FlagsConstants.KEY_MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY
- + " = "
- + getMeasurementDualDestinationEventNoiseProbability());
- writer.println(
- "\t"
- + FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY
- + " = "
- + getMeasurementInstallAttrEventNoiseProbability());
- writer.println(
- "\t"
- + FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY
- + " = "
- + getMeasurementInstallAttrNavigationNoiseProbability());
- writer.println(
- "\t"
- + FlagsConstants.KEY_MEASUREMENT_EVENT_NOISE_PROBABILITY
- + " = "
- + getMeasurementEventNoiseProbability());
- writer.println(
- "\t"
- + FlagsConstants.KEY_MEASUREMENT_NAVIGATION_NOISE_PROBABILITY
- + " = "
- + getMeasurementNavigationNoiseProbability());
- writer.println(
- "\t"
+ FlagsConstants.KEY_MEASUREMENT_REGISTRATION_JOB_QUEUE_KILL_SWITCH
+ " = "
+ getAsyncRegistrationJobQueueKillSwitch());
@@ -4369,11 +4335,6 @@ public final class PhFlags extends CommonPhFlags implements Flags {
+ getMeasurementMinEventReportDelayMillis());
writer.println(
"\t"
- + FlagsConstants.KEY_MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS
- + " = "
- + getMeasurementEnableConfigurableEventReportingWindows());
- writer.println(
- "\t"
+ FlagsConstants.KEY_MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS
+ " = "
+ getMeasurementEventReportsVtcEarlyReportingWindows());
@@ -5154,11 +5115,6 @@ public final class PhFlags extends CommonPhFlags implements Flags {
writer.println("==== AdServices PH Flags Dump UI Related Flags ====");
writer.println(
"\t"
- + FlagsConstants.KEY_EU_NOTIF_FLOW_CHANGE_ENABLED
- + " = "
- + getEuNotifFlowChangeEnabled());
- writer.println(
- "\t"
+ FlagsConstants.KEY_UI_FEATURE_TYPE_LOGGING_ENABLED
+ " = "
+ isUiFeatureTypeLoggingEnabled());
@@ -5500,6 +5456,8 @@ public final class PhFlags extends CommonPhFlags implements Flags {
+ KEY_MEASUREMENT_ENABLE_SESSION_STABLE_KILL_SWITCHES
+ " = "
+ getMeasurementEnableSessionStableKillSwitches());
+ writer.println("\t" + KEY_APPSEARCH_WRITE_TIMEOUT_MS + " = " + getAppSearchWriteTimeout());
+ writer.println("\t" + KEY_APPSEARCH_READ_TIMEOUT_MS + " = " + getAppSearchReadTimeout());
}
@VisibleForTesting
@@ -5667,14 +5625,6 @@ public final class PhFlags extends CommonPhFlags implements Flags {
}
@Override
- public boolean getEuNotifFlowChangeEnabled() {
- return DeviceConfig.getBoolean(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants.KEY_EU_NOTIF_FLOW_CHANGE_ENABLED,
- /* defaultValue */ DEFAULT_EU_NOTIF_FLOW_CHANGE_ENABLED);
- }
-
- @Override
public boolean getNotificationDismissedOnClick() {
return DeviceConfig.getBoolean(
FlagsConstants.NAMESPACE_ADSERVICES,
@@ -5701,12 +5651,12 @@ public final class PhFlags extends CommonPhFlags implements Flags {
}
@Override
- public boolean getEnableRvcNotification() {
+ public boolean getEnableRvcPostOtaNotification() {
return getEnableAdServicesSystemApi()
&& DeviceConfig.getBoolean(
FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED,
- /* defaultValue */ DEFAULT_RVC_NOTIFICATION_ENABLED);
+ /* flagName */ FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED,
+ /* defaultValue */ DEFAULT_RVC_POST_OTA_NOTIFICATION_ENABLED);
}
@Override
@@ -5729,7 +5679,9 @@ public final class PhFlags extends CommonPhFlags implements Flags {
getRecordManualInteractionEnabled());
uxMap.put(FlagsConstants.KEY_GA_UX_FEATURE_ENABLED, getGaUxFeatureEnabled());
uxMap.put(FlagsConstants.KEY_RVC_UX_ENABLED, getEnableRvcUx());
- uxMap.put(FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED, getEnableRvcNotification());
+ uxMap.put(
+ FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED,
+ getEnableRvcPostOtaNotification());
uxMap.put(
FlagsConstants.KEY_UI_OTA_STRINGS_FEATURE_ENABLED, getUiOtaStringsFeatureEnabled());
uxMap.put(
@@ -5742,7 +5694,6 @@ public final class PhFlags extends CommonPhFlags implements Flags {
uxMap.put(
FlagsConstants.KEY_CONSENT_NOTIFICATION_ACTIVITY_DEBUG_MODE,
getConsentNotificationActivityDebugMode());
- uxMap.put(FlagsConstants.KEY_EU_NOTIF_FLOW_CHANGE_ENABLED, getEuNotifFlowChangeEnabled());
uxMap.put(FlagsConstants.KEY_U18_UX_ENABLED, getU18UxEnabled());
uxMap.put(
FlagsConstants.KEY_NOTIFICATION_DISMISSED_ON_CLICK,
@@ -5863,83 +5814,6 @@ public final class PhFlags extends CommonPhFlags implements Flags {
}
@Override
- public float getMeasurementInstallAttrDualDestinationEventNoiseProbability() {
- // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
- return DeviceConfig.getFloat(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants
- .KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY,
- /* defaultValue */ MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY);
- }
-
- @Override
- public float getMeasurementDualDestinationNavigationNoiseProbability() {
- // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
- return DeviceConfig.getFloat(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants
- .KEY_MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY,
- /* defaultValue */ MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY);
- }
-
- @Override
- public float getMeasurementInstallAttrDualDestinationNavigationNoiseProbability() {
- // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
- return DeviceConfig.getFloat(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants
- .KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY,
- /* defaultValue */ MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY);
- }
-
- @Override
- public float getMeasurementDualDestinationEventNoiseProbability() {
- // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
- return DeviceConfig.getFloat(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants
- .KEY_MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY,
- /* defaultValue */ MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY);
- }
-
- @Override
- public float getMeasurementInstallAttrEventNoiseProbability() {
- // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
- return DeviceConfig.getFloat(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY,
- /* defaultValue */ MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY);
- }
-
- @Override
- public float getMeasurementInstallAttrNavigationNoiseProbability() {
- // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
- return DeviceConfig.getFloat(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants
- .KEY_MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY,
- /* defaultValue */ MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY);
- }
-
- @Override
- public float getMeasurementEventNoiseProbability() {
- // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
- return DeviceConfig.getFloat(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants.KEY_MEASUREMENT_EVENT_NOISE_PROBABILITY,
- /* defaultValue */ MEASUREMENT_EVENT_NOISE_PROBABILITY);
- }
-
- @Override
- public float getMeasurementNavigationNoiseProbability() {
- // The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
- return DeviceConfig.getFloat(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants.KEY_MEASUREMENT_NAVIGATION_NOISE_PROBABILITY,
- /* defaultValue */ MEASUREMENT_NAVIGATION_NOISE_PROBABILITY);
- }
-
- @Override
public boolean getMeasurementEnablePreinstallCheck() {
// The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
return DeviceConfig.getBoolean(
@@ -5949,16 +5823,6 @@ public final class PhFlags extends CommonPhFlags implements Flags {
}
@Override
- public boolean getMeasurementEnableVtcConfigurableMaxEventReports() {
- return DeviceConfig.getBoolean(
- FlagsConstants.NAMESPACE_ADSERVICES,
- /* flagName */ FlagsConstants
- .KEY_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS,
- /* defaultValue */
- DEFAULT_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS);
- }
-
- @Override
public int getMeasurementVtcConfigurableMaxEventReportsCount() {
return DeviceConfig.getInt(
FlagsConstants.NAMESPACE_ADSERVICES,
@@ -6526,4 +6390,20 @@ public final class PhFlags extends CommonPhFlags implements Flags {
return loggingRatio;
}
+
+ @Override
+ public int getAppSearchWriteTimeout() {
+ return DeviceConfig.getInt(
+ FlagsConstants.NAMESPACE_ADSERVICES,
+ /* name= */ FlagsConstants.KEY_APPSEARCH_WRITE_TIMEOUT_MS,
+ /* defaultValue= */ DEFAULT_APPSEARCH_WRITE_TIMEOUT_MS);
+ }
+
+ @Override
+ public int getAppSearchReadTimeout() {
+ return DeviceConfig.getInt(
+ FlagsConstants.NAMESPACE_ADSERVICES,
+ /* name= */ FlagsConstants.KEY_APPSEARCH_READ_TIMEOUT_MS,
+ /* defaultValue= */ DEFAULT_APPSEARCH_READ_TIMEOUT_MS);
+ }
}
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
index c337bf17b..22eea4b05 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionRunner.java
@@ -49,7 +49,10 @@ import com.android.adservices.data.adselection.datahandlers.AdSelectionResultBid
import com.android.adservices.data.adselection.datahandlers.WinningCustomAudience;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
+import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.service.Flags;
+import com.android.adservices.service.adselection.signature.ProtectedAudienceSignatureManager;
import com.android.adservices.service.common.AdSelectionServiceFilter;
import com.android.adservices.service.common.FrequencyCapAdDataValidator;
import com.android.adservices.service.common.Throttler;
@@ -76,6 +79,7 @@ import com.google.common.util.concurrent.UncheckedTimeoutException;
import java.time.Clock;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -123,8 +127,11 @@ public abstract class AdSelectionRunner {
static final String ON_DEVICE_AUCTION_KILL_SWITCH_ENABLED =
"On device auction kill switch enabled";
+ @NonNull protected final Context mContext;
@NonNull protected final CustomAudienceDao mCustomAudienceDao;
@NonNull protected final AdSelectionEntryDao mAdSelectionEntryDao;
+ @NonNull protected final EncryptionKeyDao mEncryptionKeyDao;
+ @NonNull protected final EnrollmentDao mEnrollmentDao;
@NonNull protected final ListeningExecutorService mLightweightExecutorService;
@NonNull protected final ListeningExecutorService mBackgroundExecutorService;
@NonNull protected final ScheduledThreadPoolExecutor mScheduledExecutor;
@@ -157,6 +164,8 @@ public abstract class AdSelectionRunner {
@NonNull final Context context,
@NonNull final CustomAudienceDao customAudienceDao,
@NonNull final AdSelectionEntryDao adSelectionEntryDao,
+ @NonNull final EncryptionKeyDao encryptionKeyDao,
+ @NonNull final EnrollmentDao enrollmentDao,
@NonNull final ExecutorService lightweightExecutorService,
@NonNull final ExecutorService backgroundExecutorService,
@NonNull final ScheduledThreadPoolExecutor scheduledExecutor,
@@ -173,6 +182,8 @@ public abstract class AdSelectionRunner {
Objects.requireNonNull(context);
Objects.requireNonNull(customAudienceDao);
Objects.requireNonNull(adSelectionEntryDao);
+ Objects.requireNonNull(encryptionKeyDao);
+ Objects.requireNonNull(enrollmentDao);
Objects.requireNonNull(lightweightExecutorService);
Objects.requireNonNull(backgroundExecutorService);
Objects.requireNonNull(adServicesLogger);
@@ -184,8 +195,11 @@ public abstract class AdSelectionRunner {
Objects.requireNonNull(debugReporting);
Objects.requireNonNull(adSelectionExecutionLogger);
+ mContext = context;
mCustomAudienceDao = customAudienceDao;
mAdSelectionEntryDao = adSelectionEntryDao;
+ mEncryptionKeyDao = encryptionKeyDao;
+ mEnrollmentDao = enrollmentDao;
mLightweightExecutorService = MoreExecutors.listeningDecorator(lightweightExecutorService);
mBackgroundExecutorService = MoreExecutors.listeningDecorator(backgroundExecutorService);
mScheduledExecutor = scheduledExecutor;
@@ -209,6 +223,8 @@ public abstract class AdSelectionRunner {
@NonNull final Context context,
@NonNull final CustomAudienceDao customAudienceDao,
@NonNull final AdSelectionEntryDao adSelectionEntryDao,
+ @NonNull final EncryptionKeyDao encryptionKeyDao,
+ @NonNull final EnrollmentDao enrollmentDao,
@NonNull final ExecutorService lightweightExecutorService,
@NonNull final ExecutorService backgroundExecutorService,
@NonNull final ScheduledThreadPoolExecutor scheduledExecutor,
@@ -227,6 +243,8 @@ public abstract class AdSelectionRunner {
Objects.requireNonNull(context);
Objects.requireNonNull(customAudienceDao);
Objects.requireNonNull(adSelectionEntryDao);
+ Objects.requireNonNull(encryptionKeyDao);
+ Objects.requireNonNull(enrollmentDao);
Objects.requireNonNull(lightweightExecutorService);
Objects.requireNonNull(backgroundExecutorService);
Objects.requireNonNull(scheduledExecutor);
@@ -240,8 +258,11 @@ public abstract class AdSelectionRunner {
Objects.requireNonNull(adCounterHistogramUpdater);
Objects.requireNonNull(debugReporting);
+ mContext = context;
mCustomAudienceDao = customAudienceDao;
mAdSelectionEntryDao = adSelectionEntryDao;
+ mEncryptionKeyDao = encryptionKeyDao;
+ mEnrollmentDao = enrollmentDao;
mLightweightExecutorService = MoreExecutors.listeningDecorator(lightweightExecutorService);
mBackgroundExecutorService = MoreExecutors.listeningDecorator(backgroundExecutorService);
mScheduledExecutor = scheduledExecutor;
@@ -277,7 +298,6 @@ public abstract class AdSelectionRunner {
final int traceCookie = Tracing.beginAsyncSection(Tracing.RUN_AD_SELECTION);
Objects.requireNonNull(inputParams);
Objects.requireNonNull(callback);
- AdSelectionConfig adSelectionConfig = inputParams.getAdSelectionConfig();
try {
ListenableFuture<Void> filterAndValidateRequestFuture =
@@ -501,7 +521,7 @@ public abstract class AdSelectionRunner {
@NonNull final String callerPackageName) {
sLogger.v("Beginning Ad Selection Orchestration");
- AdSelectionConfig adSelectionConfigInput = adSelectionConfig;
+ AdSelectionConfig adSelectionConfigInput;
if (!mFlags.getFledgeAdSelectionContextualAdsEnabled()) {
// Empty all contextual ads if the feature is disabled
sLogger.v("Contextual flow is disabled");
@@ -594,9 +614,7 @@ public abstract class AdSelectionRunner {
private int countBuyersRequested(@NonNull AdSelectionConfig adSelectionConfig) {
Objects.requireNonNull(adSelectionConfig);
- return adSelectionConfig.getCustomAudienceBuyers().stream()
- .collect(Collectors.toSet())
- .size();
+ return new HashSet<>(adSelectionConfig.getCustomAudienceBuyers()).size();
}
private int countBuyersFromCustomAudiences(
@@ -728,10 +746,27 @@ public abstract class AdSelectionRunner {
AdSelectionConfig adSelectionConfig) {
Map<AdTechIdentifier, SignedContextualAds> filteredContextualAdsMap = new HashMap<>();
sLogger.v("Filtering contextual ads in Ad Selection Config");
+ boolean isEnrollmentCheckEnabled = !mFlags.getDisableFledgeEnrollmentCheck();
+ ProtectedAudienceSignatureManager signatureManager =
+ new ProtectedAudienceSignatureManager(
+ mEnrollmentDao, mEncryptionKeyDao, isEnrollmentCheckEnabled);
for (Map.Entry<AdTechIdentifier, SignedContextualAds> entry :
adSelectionConfig.getBuyerSignedContextualAds().entrySet()) {
+ if (!signatureManager.isVerified(entry.getKey(), entry.getValue())) {
+ sLogger.v(
+ "Contextual ads for buyer: '%s' have an invalid signature and will be"
+ + " removed from the auction",
+ entry.getKey());
+ continue;
+ }
filteredContextualAdsMap.put(
entry.getKey(), mAdFilterer.filterContextualAds(entry.getValue()));
+ sLogger.v(
+ "Buyer '%s' has a valid signature. It's contextual ads filtered from "
+ + "%s ad(s) to %s ad(s)",
+ entry.getKey(),
+ entry.getValue().getAdsWithBid().size(),
+ filteredContextualAdsMap.get(entry.getKey()).getAdsWithBid().size());
}
return adSelectionConfig
.cloneToBuilder()
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionServiceImpl.java
index 85bad0af0..9bff5dea6 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionServiceImpl.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/AdSelectionServiceImpl.java
@@ -71,12 +71,12 @@ import com.android.adservices.data.adselection.AdSelectionDebugReportingDatabase
import com.android.adservices.data.adselection.AdSelectionEntryDao;
import com.android.adservices.data.adselection.AdSelectionServerDatabase;
import com.android.adservices.data.adselection.AppInstallDao;
-import com.android.adservices.data.adselection.EncryptionContextDao;
-import com.android.adservices.data.adselection.EncryptionKeyDao;
import com.android.adservices.data.adselection.FrequencyCapDao;
import com.android.adservices.data.adselection.SharedStorageDatabase;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.CustomAudienceDatabase;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
+import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.data.signals.EncodedPayloadDao;
import com.android.adservices.data.signals.ProtectedSignalsDatabase;
import com.android.adservices.service.Flags;
@@ -137,8 +137,8 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
@NonNull private final CustomAudienceDao mCustomAudienceDao;
@NonNull private final EncodedPayloadDao mEncodedPayloadDao;
@NonNull private final FrequencyCapDao mFrequencyCapDao;
- @NonNull private final EncryptionContextDao mEncryptionContextDao;
@NonNull private final EncryptionKeyDao mEncryptionKeyDao;
+ @NonNull private final EnrollmentDao mEnrollmentDao;
@NonNull private final AdServicesHttpsClient mAdServicesHttpsClient;
@NonNull private final ExecutorService mLightweightExecutor;
@NonNull private final ExecutorService mBackgroundExecutor;
@@ -168,8 +168,8 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
@NonNull CustomAudienceDao customAudienceDao,
@NonNull EncodedPayloadDao encodedPayloadDao,
@NonNull FrequencyCapDao frequencyCapDao,
- @NonNull EncryptionContextDao encryptionContextDao,
@NonNull EncryptionKeyDao encryptionKeyDao,
+ @NonNull EnrollmentDao enrollmentDao,
@NonNull AdServicesHttpsClient adServicesHttpsClient,
@NonNull DevContextFilter devContextFilter,
@NonNull ExecutorService lightweightExecutorService,
@@ -193,8 +193,8 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
Objects.requireNonNull(customAudienceDao);
Objects.requireNonNull(encodedPayloadDao);
Objects.requireNonNull(frequencyCapDao);
- Objects.requireNonNull(encryptionContextDao);
Objects.requireNonNull(encryptionKeyDao);
+ Objects.requireNonNull(enrollmentDao);
Objects.requireNonNull(adServicesHttpsClient);
Objects.requireNonNull(devContextFilter);
Objects.requireNonNull(lightweightExecutorService);
@@ -213,8 +213,8 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
mCustomAudienceDao = customAudienceDao;
mEncodedPayloadDao = encodedPayloadDao;
mFrequencyCapDao = frequencyCapDao;
- mEncryptionContextDao = encryptionContextDao;
mEncryptionKeyDao = encryptionKeyDao;
+ mEnrollmentDao = enrollmentDao;
mAdServicesHttpsClient = adServicesHttpsClient;
mDevContextFilter = devContextFilter;
mLightweightExecutor = lightweightExecutorService;
@@ -249,8 +249,8 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
CustomAudienceDatabase.getInstance(context).customAudienceDao(),
ProtectedSignalsDatabase.getInstance(context).getEncodedPayloadDao(),
SharedStorageDatabase.getInstance(context).frequencyCapDao(),
- AdSelectionServerDatabase.getInstance(context).encryptionContextDao(),
- AdSelectionServerDatabase.getInstance(context).encryptionKeyDao(),
+ EncryptionKeyDao.getInstance(context),
+ EnrollmentDao.getInstance(context),
new AdServicesHttpsClient(
AdServicesExecutors.getBlockingExecutor(),
CacheProviderFactory.create(context, FlagsFactory.getFlags())),
@@ -332,7 +332,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, inputParams.getCallerPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -370,7 +370,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, inputParams.getCallerPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -473,7 +473,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, inputParams.getCallerPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -674,6 +674,8 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
mContext,
mCustomAudienceDao,
mAdSelectionEntryDao,
+ mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mLightweightExecutor,
mBackgroundExecutor,
@@ -709,6 +711,8 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
mContext,
mCustomAudienceDao,
mAdSelectionEntryDao,
+ mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mLightweightExecutor,
mBackgroundExecutor,
@@ -758,7 +762,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, inputParams.getCallerPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -801,7 +805,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, requestParams.getCallerPackageName(), apiName);
DevContext devContext = mDevContextFilter.createDevContext();
@@ -867,7 +871,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, inputParams.getCallerPackageName(), apiName);
int callerUid = getCallingUid(apiName);
@@ -924,7 +928,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, request.getCallerPackageName(), apiName);
AppInstallAdvertisersSetter setter =
@@ -956,7 +960,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, inputParams.getCallerPackageName(), apiName);
final int callingUid = getCallingUid(apiName);
@@ -1029,7 +1033,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -1096,7 +1100,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -1146,7 +1150,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -1201,7 +1205,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -1252,7 +1256,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -1301,7 +1305,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
int callingUid = getCallingUid(apiName);
@@ -1351,7 +1355,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
// TODO(b/265204820): Implement service
@@ -1389,7 +1393,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
// TODO(b/265204820): Implement service
@@ -1424,7 +1428,7 @@ public class AdSelectionServiceImpl extends AdSelectionService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
// TODO(b/265204820): Implement service
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/OnDeviceAdSelectionRunner.java b/adservices/service-core/java/com/android/adservices/service/adselection/OnDeviceAdSelectionRunner.java
index 4c5b280dd..e2a93966f 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/OnDeviceAdSelectionRunner.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/OnDeviceAdSelectionRunner.java
@@ -35,6 +35,8 @@ import com.android.adservices.data.adselection.AdSelectionEntryDao;
import com.android.adservices.data.adselection.DBAdSelection;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
+import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.service.Flags;
import com.android.adservices.service.common.AdSelectionServiceFilter;
import com.android.adservices.service.common.BinderFlagReader;
@@ -79,6 +81,8 @@ public class OnDeviceAdSelectionRunner extends AdSelectionRunner {
@NonNull final Context context,
@NonNull final CustomAudienceDao customAudienceDao,
@NonNull final AdSelectionEntryDao adSelectionEntryDao,
+ @NonNull final EncryptionKeyDao encryptionKeyDao,
+ @NonNull final EnrollmentDao enrollmentDao,
@NonNull final AdServicesHttpsClient adServicesHttpsClient,
@NonNull final ExecutorService lightweightExecutorService,
@NonNull final ExecutorService backgroundExecutorService,
@@ -99,6 +103,8 @@ public class OnDeviceAdSelectionRunner extends AdSelectionRunner {
context,
customAudienceDao,
adSelectionEntryDao,
+ encryptionKeyDao,
+ enrollmentDao,
lightweightExecutorService,
backgroundExecutorService,
scheduledExecutor,
@@ -172,6 +178,8 @@ public class OnDeviceAdSelectionRunner extends AdSelectionRunner {
@NonNull final Context context,
@NonNull final CustomAudienceDao customAudienceDao,
@NonNull final AdSelectionEntryDao adSelectionEntryDao,
+ @NonNull final EncryptionKeyDao encryptionKeyDao,
+ @NonNull final EnrollmentDao enrollmentDao,
@NonNull final AdServicesHttpsClient adServicesHttpsClient,
@NonNull final ExecutorService lightweightExecutorService,
@NonNull final ExecutorService backgroundExecutorService,
@@ -195,6 +203,8 @@ public class OnDeviceAdSelectionRunner extends AdSelectionRunner {
context,
customAudienceDao,
adSelectionEntryDao,
+ encryptionKeyDao,
+ enrollmentDao,
lightweightExecutorService,
backgroundExecutorService,
scheduledExecutor,
@@ -360,7 +370,10 @@ public class OnDeviceAdSelectionRunner extends AdSelectionRunner {
.filter(Objects::nonNull)
.collect(Collectors.toList()));
}
-
+ sLogger.v(
+ "Invoking score generator with %s bids and %s contextual ads.",
+ validBiddingOutcomes.size(),
+ adSelectionConfig.getBuyerSignedContextualAds().size());
return mAdsScoreGenerator
.runAdScoring(validBiddingOutcomes, adSelectionConfig)
.transform(
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/TrustedServerAdSelectionRunner.java b/adservices/service-core/java/com/android/adservices/service/adselection/TrustedServerAdSelectionRunner.java
index 190ebef74..b372378b9 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/TrustedServerAdSelectionRunner.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/TrustedServerAdSelectionRunner.java
@@ -34,6 +34,8 @@ import com.android.adservices.data.adselection.CustomAudienceSignals;
import com.android.adservices.data.adselection.DBAdSelection;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
+import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.service.Flags;
import com.android.adservices.service.common.AdRenderIdValidator;
import com.android.adservices.service.common.AdSelectionServiceFilter;
@@ -97,6 +99,8 @@ public class TrustedServerAdSelectionRunner extends AdSelectionRunner {
@NonNull final Context context,
@NonNull final CustomAudienceDao customAudienceDao,
@NonNull final AdSelectionEntryDao adSelectionEntryDao,
+ @NonNull final EncryptionKeyDao encryptionKeyDao,
+ @NonNull final EnrollmentDao enrollmentDao,
@NonNull final AdServicesHttpsClient adServicesHttpsClient,
@NonNull final ExecutorService lightweightExecutorService,
@NonNull final ExecutorService backgroundExecutorService,
@@ -116,6 +120,8 @@ public class TrustedServerAdSelectionRunner extends AdSelectionRunner {
context,
customAudienceDao,
adSelectionEntryDao,
+ encryptionKeyDao,
+ enrollmentDao,
lightweightExecutorService,
backgroundExecutorService,
scheduledExecutor,
@@ -146,6 +152,8 @@ public class TrustedServerAdSelectionRunner extends AdSelectionRunner {
@NonNull final Context context,
@NonNull final CustomAudienceDao customAudienceDao,
@NonNull final AdSelectionEntryDao adSelectionEntryDao,
+ @NonNull final EncryptionKeyDao encryptionKeyDao,
+ @NonNull final EnrollmentDao enrollmentDao,
@NonNull final ExecutorService lightweightExecutorService,
@NonNull final ExecutorService backgroundExecutorService,
@NonNull final ScheduledThreadPoolExecutor scheduledExecutor,
@@ -165,6 +173,8 @@ public class TrustedServerAdSelectionRunner extends AdSelectionRunner {
context,
customAudienceDao,
adSelectionEntryDao,
+ encryptionKeyDao,
+ enrollmentDao,
lightweightExecutorService,
backgroundExecutorService,
scheduledExecutor,
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManager.java b/adservices/service-core/java/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManager.java
index 63a3d405a..ec5511f61 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManager.java
@@ -16,9 +16,9 @@
package com.android.adservices.service.adselection.signature;
+import android.adservices.adselection.SignedContextualAds;
import android.adservices.common.AdTechIdentifier;
import android.annotation.NonNull;
-import android.content.Context;
import com.android.adservices.LoggerFactory;
import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
@@ -28,6 +28,7 @@ import com.android.adservices.service.enrollment.EnrollmentData;
import com.google.common.annotations.VisibleForTesting;
+import java.util.Base64;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -41,32 +42,96 @@ import java.util.stream.Collectors;
*/
public class ProtectedAudienceSignatureManager {
private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger();
- private final Context mContext;
- private final EnrollmentDao mEnrollmentDao;
- private final EncryptionKeyDao mEncryptionKeyDao;
+ /**
+ * This P-256 ECDSA key is used to verify signatures if {@link
+ * com.android.adservices.service.FlagsConstants #KEY_DISABLE_FLEDGE_ENROLLMENT_CHECK} is set to
+ * true.
+ *
+ * <p>This enables CTS and integration testing.
+ *
+ * <p>To test with this key, {@link SignedContextualAds} should be signed with {@link
+ * ProtectedAudienceSignatureManager#PRIVATE_TEST_KEY_STRING}.
+ */
+ public static final String PUBLIC_TEST_KEY_STRING =
+ "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+Eyo0TOllW8as2pTTzxawQ57pXJiH16VERgHqcV1/YpADt3iq6"
+ + "9vbhwW8Ksi3M0GrxacOuge/AwiM7Uh6+V3PA==";
- public ProtectedAudienceSignatureManager(@NonNull Context context) {
- Objects.requireNonNull(context);
+ /**
+ * Private key pair of the {@link ProtectedAudienceSignatureManager#PUBLIC_TEST_KEY_STRING}
+ *
+ * <p>See {@link ProtectedAudienceSignatureManager#PUBLIC_TEST_KEY_STRING}
+ */
+ public static final String PRIVATE_TEST_KEY_STRING =
+ "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgECetqRr9eE9DKKjILR+hP66Y1niEw/bqPD/MNx"
+ + "PTMvmhRANCAAT4TKjRM6WVbxqzalNPPFrBDnulcmIfXpURGAepxXX9ikAO3eKrr29uHBbwqyLczQ"
+ + "avFpw66B78DCIztSHr5Xc8";
- mContext = context;
+ @NonNull private final EnrollmentDao mEnrollmentDao;
+ @NonNull private final EncryptionKeyDao mEncryptionKeyDao;
+ private final boolean mIsEnrollmentCheckEnabled;
- mEnrollmentDao = EnrollmentDao.getInstance(mContext);
- mEncryptionKeyDao = EncryptionKeyDao.getInstance(mContext);
+ private final SignatureVerifier mSignatureVerifier;
+
+ public ProtectedAudienceSignatureManager(
+ @NonNull EnrollmentDao enrollmentDao,
+ @NonNull EncryptionKeyDao encryptionKeyDao,
+ boolean isEnrollmentCheckEnabled) {
+ Objects.requireNonNull(enrollmentDao);
+ Objects.requireNonNull(encryptionKeyDao);
+
+ mEnrollmentDao = enrollmentDao;
+ mEncryptionKeyDao = encryptionKeyDao;
+ mIsEnrollmentCheckEnabled = isEnrollmentCheckEnabled;
+
+ mSignatureVerifier = new ECDSASignatureVerifier();
}
@VisibleForTesting
ProtectedAudienceSignatureManager(
- @NonNull Context context,
@NonNull EnrollmentDao enrollmentDao,
- @NonNull EncryptionKeyDao encryptionKeyDao) {
- mContext = context;
+ @NonNull EncryptionKeyDao encryptionKeyDao,
+ @NonNull SignatureVerifier signatureVerifier) {
mEnrollmentDao = enrollmentDao;
mEncryptionKeyDao = encryptionKeyDao;
+ mSignatureVerifier = signatureVerifier;
+
+ mIsEnrollmentCheckEnabled = true;
+ }
+
+ /**
+ * Returns whether is the given {@link SignedContextualAds} object is valid or not
+ *
+ * @param buyer Ad tech's identifier to resolve their public key
+ * @param signedContextualAds contextual ads object to verify
+ * @return true if the object is valid else false
+ */
+ public boolean isVerified(
+ @NonNull AdTechIdentifier buyer, @NonNull SignedContextualAds signedContextualAds) {
+ Objects.requireNonNull(buyer);
+ Objects.requireNonNull(signedContextualAds);
+
+ List<byte[]> publicKeys = fetchPublicKeyForAdTech(buyer);
+ boolean isVerified = false;
+ SignedContextualAdsHashUtil contextualAdsHashUtil;
+ for (byte[] publicKey : publicKeys) {
+ contextualAdsHashUtil = new SignedContextualAdsHashUtil();
+ byte[] serialized = contextualAdsHashUtil.serialize(signedContextualAds);
+ isVerified =
+ mSignatureVerifier.verify(
+ publicKey, serialized, signedContextualAds.getSignature());
+ }
+ return isVerified;
}
@VisibleForTesting
- List<String> fetchPublicKeyForAdTech(AdTechIdentifier adTech) {
+ List<byte[]> fetchPublicKeyForAdTech(AdTechIdentifier adTech) {
+ Base64.Decoder decoder = Base64.getDecoder();
+ if (!mIsEnrollmentCheckEnabled) {
+ sLogger.v("Enrollment check is disabled, returning the default key");
+ return Collections.singletonList(decoder.decode(PUBLIC_TEST_KEY_STRING));
+ }
+
sLogger.v("Fetching EnrollmentData for %s", adTech);
EnrollmentData enrollmentData =
mEnrollmentDao.getEnrollmentDataForFledgeByAdTechIdentifier(adTech);
@@ -81,10 +146,10 @@ public class ProtectedAudienceSignatureManager {
mEncryptionKeyDao.getEncryptionKeyFromEnrollmentIdAndKeyType(
enrollmentData.getEnrollmentId(), EncryptionKey.KeyType.SIGNING);
- sLogger.v("Received %s signing keys", encryptionKeys.size());
+ sLogger.v("Received %s signing key(s)", encryptionKeys.size());
return encryptionKeys.stream()
.sorted(Comparator.comparingLong(EncryptionKey::getExpiration))
- .map(EncryptionKey::getBody)
+ .map(key -> decoder.decode(key.getBody()))
.collect(Collectors.toList());
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/adselection/signature/ThreadUnsafeByteArrayOutputStream.java b/adservices/service-core/java/com/android/adservices/service/adselection/signature/ThreadUnsafeByteArrayOutputStream.java
index 4857768a6..a9918549b 100644
--- a/adservices/service-core/java/com/android/adservices/service/adselection/signature/ThreadUnsafeByteArrayOutputStream.java
+++ b/adservices/service-core/java/com/android/adservices/service/adselection/signature/ThreadUnsafeByteArrayOutputStream.java
@@ -23,13 +23,13 @@ import java.util.Arrays;
/** ByteArrayStream implementation that reduces amount of copy operation */
public class ThreadUnsafeByteArrayOutputStream {
private static final int ONE_KILOBYTE = 1024;
- private static final int INITIAL_CAPACITY = 100 * ONE_KILOBYTE;
+ private static final int DEFAULT_INITIAL_CAPACITY = 100 * ONE_KILOBYTE;
private static final int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
private byte[] mBuffer;
private int mCount;
public ThreadUnsafeByteArrayOutputStream() {
- this.mBuffer = new byte[INITIAL_CAPACITY];
+ this.mBuffer = new byte[DEFAULT_INITIAL_CAPACITY];
this.mCount = 0;
}
diff --git a/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentStorageManager.java b/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentStorageManager.java
index cbd867c0f..04c6f6030 100644
--- a/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentStorageManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentStorageManager.java
@@ -412,8 +412,7 @@ public class AppSearchConsentStorageManager implements IConsentStorage {
/** Saves the default consent by apiType. */
@Override
- public void recordDefaultConsent(AdServicesApiType apiType, boolean defaultConsent)
- throws IOException {
+ public void recordDefaultConsent(AdServicesApiType apiType, boolean defaultConsent) {
mAppSearchConsentWorker.setConsent(apiType.toDefaultConsentDatastoreKey(), defaultConsent);
}
@@ -436,8 +435,7 @@ public class AppSearchConsentStorageManager implements IConsentStorage {
}
/** Saves information to the storage that user interacted with consent manually. */
- public void recordUserManualInteractionWithConsent(
- @ConsentManager.UserManualInteraction int interaction) {
+ public void recordUserManualInteractionWithConsent(int interaction) {
mAppSearchConsentWorker.recordUserManualInteractionWithConsent(interaction);
}
diff --git a/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentWorker.java b/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentWorker.java
index 42c5c1ed8..bda9d1744 100644
--- a/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentWorker.java
+++ b/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchConsentWorker.java
@@ -65,15 +65,11 @@ import java.util.stream.Collectors;
* source of truth for S-. When a device upgrades from S- to T+, the consent is initialized from
* AppSearch.
*/
-// TODO(b/269798827): Enable for R.
@RequiresApi(Build.VERSION_CODES.S)
class AppSearchConsentWorker {
// At the worker level, we ensure that writes do not conflict with any other writes/reads.
private static final ReadWriteLock READ_WRITE_LOCK = new ReentrantReadWriteLock();
- // Timeout for AppSearch write query in milliseconds.
- private static final int TIMEOUT_MS = 2000;
-
private static final String CONSENT_DATABASE_NAME = "adservices_consent";
private static final String APP_CONSENT_DATABASE_NAME = "adservices_app_consent";
private static final String NOTIFICATION_DATABASE_NAME = "adservices_notification";
@@ -82,68 +78,69 @@ class AppSearchConsentWorker {
private static final String UX_STATES_DATABASE_NAME = "adservices-ux-states";
// Required for allowing AdServices apk access to read consent written by ExtServices module.
- private String mAdservicesPackageName;
- private Context mContext;
+ private final String mAdservicesPackageName;
- private ListenableFuture<AppSearchSession> mConsentSearchSession;
- private ListenableFuture<AppSearchSession> mAppConsentSearchSession;
- private ListenableFuture<AppSearchSession> mNotificationSearchSession;
- private ListenableFuture<AppSearchSession> mInteractionsSearchSession;
- private ListenableFuture<AppSearchSession> mTopicsSearchSession;
- private ListenableFuture<AppSearchSession> mUxStatesSearchSession;
+ // Timeout for AppSearch write query in milliseconds.
+ private final int mTimeoutMs;
+
+ private final ListenableFuture<AppSearchSession> mConsentSearchSession;
+ private final ListenableFuture<AppSearchSession> mAppConsentSearchSession;
+ private final ListenableFuture<AppSearchSession> mNotificationSearchSession;
+ private final ListenableFuture<AppSearchSession> mInteractionsSearchSession;
+ private final ListenableFuture<AppSearchSession> mTopicsSearchSession;
+ private final ListenableFuture<AppSearchSession> mUxStatesSearchSession;
// When reading across APKs, a GlobalSearchSession is needed, hence we use it when reading.
- private ListenableFuture<GlobalSearchSession> mGlobalSearchSession;
- private Executor mExecutor = AdServicesExecutors.getBackgroundExecutor();
+ private final ListenableFuture<GlobalSearchSession> mGlobalSearchSession;
+ private final Executor mExecutor = AdServicesExecutors.getBackgroundExecutor();
- private List<PackageIdentifier> mPackageIdentifiers = new ArrayList<>();
+ private final List<PackageIdentifier> mPackageIdentifiers = new ArrayList<>();
// There is a single user ID for a given process, so this class would not be instantiated
// across two user IDs.
- private String mUid = getUserIdentifierFromBinderCallingUid();
+ private final String mUid = getUserIdentifierFromBinderCallingUid();
private static final String SPLITTER = ",";
private AppSearchConsentWorker(@NonNull Context context) {
Objects.requireNonNull(context);
- mContext = context;
// We write with multiple schemas, so we need to initialize sessions per db.
mConsentSearchSession =
PlatformStorage.createSearchSessionAsync(
- new PlatformStorage.SearchContext.Builder(mContext, CONSENT_DATABASE_NAME)
+ new PlatformStorage.SearchContext.Builder(context, CONSENT_DATABASE_NAME)
.build());
mAppConsentSearchSession =
PlatformStorage.createSearchSessionAsync(
new PlatformStorage.SearchContext.Builder(
- mContext, APP_CONSENT_DATABASE_NAME)
+ context, APP_CONSENT_DATABASE_NAME)
.build());
mNotificationSearchSession =
PlatformStorage.createSearchSessionAsync(
new PlatformStorage.SearchContext.Builder(
- mContext, NOTIFICATION_DATABASE_NAME)
+ context, NOTIFICATION_DATABASE_NAME)
.build());
mInteractionsSearchSession =
PlatformStorage.createSearchSessionAsync(
new PlatformStorage.SearchContext.Builder(
- mContext, INTERACTIONS_DATABASE_NAME)
+ context, INTERACTIONS_DATABASE_NAME)
.build());
mTopicsSearchSession =
PlatformStorage.createSearchSessionAsync(
- new PlatformStorage.SearchContext.Builder(mContext, TOPICS_DATABASE_NAME)
+ new PlatformStorage.SearchContext.Builder(context, TOPICS_DATABASE_NAME)
.build());
mUxStatesSearchSession =
PlatformStorage.createSearchSessionAsync(
- new PlatformStorage.SearchContext.Builder(mContext, UX_STATES_DATABASE_NAME)
+ new PlatformStorage.SearchContext.Builder(context, UX_STATES_DATABASE_NAME)
.build());
// We use global session for reads since we may perform read on T+ AdServices package to
// restore consent data post OTA.
mGlobalSearchSession =
PlatformStorage.createGlobalSearchSessionAsync(
- new PlatformStorage.GlobalSearchContext.Builder(mContext).build());
+ new PlatformStorage.GlobalSearchContext.Builder(context).build());
// The package identifier of the AdServices package on T+ should always have access to read
// data written by AdExtServices package on S-.
- mAdservicesPackageName = getAdServicesPackageName(mContext);
+ mAdservicesPackageName = getAdServicesPackageName(context);
String shaCertsFlagValue = FlagsFactory.getFlags().getAdservicesApkShaCertificate();
for (String shaCert : shaCertsFlagValue.split(SPLITTER)) {
@@ -151,6 +148,8 @@ class AppSearchConsentWorker {
new PackageIdentifier(
mAdservicesPackageName, new Signature(shaCert).toByteArray()));
}
+
+ mTimeoutMs = FlagsFactory.getFlags().getAppSearchWriteTimeout();
}
/** Get an instance of AppSearchConsentWorker. */
@@ -175,8 +174,8 @@ class AppSearchConsentWorker {
/**
* Sets the consent for this user ID for this API type in AppSearch. If we do not get
- * confirmation that the write was successful, then we throw an exception so that user does not
- * incorrectly think that the consent is updated.
+ * confirmation that the write operation was successful, then we throw an exception so that user
+ * does not incorrectly think that the consent is updated.
*/
void setConsent(@NonNull String apiType, @NonNull Boolean consented) {
Objects.requireNonNull(apiType);
@@ -193,11 +192,11 @@ class AppSearchConsentWorker {
apiType,
consented.toString());
dao.writeData(mConsentSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote consent data to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write consent to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write consent to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -235,10 +234,10 @@ class AppSearchConsentWorker {
mExecutor,
AppSearchAppConsentDao.getRowId(mUid, consentType),
AppSearchAppConsentDao.NAMESPACE)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to delete consent to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to delete consent to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -280,11 +279,11 @@ class AppSearchConsentWorker {
dao.setApps(apps);
}
dao.writeData(mAppConsentSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote app consent data to AppSearch (add): " + dao);
return true;
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write consent to AppSearch ", e);
+ LogUtil.e(e, "Failed to write consent to AppSearch");
return false;
} finally {
READ_WRITE_LOCK.writeLock().unlock();
@@ -293,8 +292,8 @@ class AppSearchConsentWorker {
/**
* Removes an app from the list of apps with this consentType for this user. If we do not get
- * confirmation that the write was successful, then we throw an exception so that user does not
- * incorrectly think that the consent is updated.
+ * confirmation that the write operation was successful, then we throw an exception so that user
+ * does not incorrectly think that the consent is updated.
*/
void removeAppWithConsent(@NonNull String consentType, @NonNull String app) {
Objects.requireNonNull(consentType);
@@ -320,11 +319,11 @@ class AppSearchConsentWorker {
.filter(filterApp -> !filterApp.equals(app))
.collect(Collectors.toList()));
dao.writeData(mAppConsentSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote app consent data to AppSearch (remove): " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write consent to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write consent to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.readLock().unlock();
}
@@ -367,11 +366,11 @@ class AppSearchConsentWorker {
/* wasNotificationDisplayed= */ wasNotificationDisplayed,
/* wasGaUxNotificationDisplayed= */ wasGaUxNotificationDisplayed());
dao.writeData(mNotificationSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote notification data to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write notification data to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write notification data to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -389,11 +388,11 @@ class AppSearchConsentWorker {
/* wasNotificationDisplayed= */ wasNotificationDisplayed(),
/* wasGaUxNotificationDisplayed= */ wasNotificationDisplayed);
dao.writeData(mNotificationSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote notification data to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write notification data to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write notification data to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -426,11 +425,11 @@ class AppSearchConsentWorker {
apiType,
currentFeatureType.ordinal());
dao.writeData(mInteractionsSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote feature type data to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write interactions data to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write interactions data to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -466,11 +465,11 @@ class AppSearchConsentWorker {
apiType,
interaction);
dao.writeData(mInteractionsSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote interactions data to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write interactions data to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write interactions data to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -512,11 +511,11 @@ class AppSearchConsentWorker {
dao.addBlockedTopic(topic);
}
dao.writeData(mTopicsSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote topics consent data to AppSearch (block): " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write consent to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write consent to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -539,11 +538,11 @@ class AppSearchConsentWorker {
}
dao.removeBlockedTopic(topic);
dao.writeData(mTopicsSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote topics consent data to AppSearch (unblock): " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write consent to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write consent to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -554,7 +553,7 @@ class AppSearchConsentWorker {
READ_WRITE_LOCK.writeLock().lock();
try {
// We don't do {read, modify, write} here since the DAO has no other information besides
- // blocked topics so we can rewrite it.
+ // blocked topics, so we can rewrite it.
AppSearchTopicsConsentDao dao =
new AppSearchTopicsConsentDao(
mUid,
@@ -564,11 +563,11 @@ class AppSearchConsentWorker {
List.of(),
List.of());
dao.writeData(mTopicsSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote topics consent data to AppSearch (clear): " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write consent to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write consent to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -606,7 +605,7 @@ class AppSearchConsentWorker {
AdServicesCommon.ADEXTSERVICES_PACKAGE_NAME_SUFFIX,
AdServicesCommon.ADSERVICES_APK_PACKAGE_NAME_SUFFIX);
}
- // If we don't know the AdServices package name, we can't do a write.
+ // If we don't know the AdServices package name, we can't write.
throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
}
@@ -637,11 +636,11 @@ class AppSearchConsentWorker {
}
dao.setAdIdEnabled(isAdIdEnabled);
dao.writeData(mUxStatesSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote the isAdIdEnabled bit to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write the isAdIdEnabled to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write the isAdIdEnabled to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -674,11 +673,11 @@ class AppSearchConsentWorker {
}
dao.setU18Account(isU18Account);
dao.writeData(mUxStatesSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote the isU18Account bit to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write the isU18Account to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write the isU18Account to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -711,11 +710,11 @@ class AppSearchConsentWorker {
}
dao.setEntryPointEnabled(isEntryPointEnabled);
dao.writeData(mUxStatesSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote the isEntryPointEnabled bit to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write the isEntryPointEnabled to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write the isEntryPointEnabled to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -748,11 +747,11 @@ class AppSearchConsentWorker {
}
dao.setAdultAccount(isAdultAccount);
dao.writeData(mUxStatesSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote the isAdultAccount bit to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write the isAdultAccount to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write the isAdultAccount to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -785,11 +784,11 @@ class AppSearchConsentWorker {
}
dao.setU18NotificationDisplayed(wasU18NotificationDisplayed);
dao.writeData(mUxStatesSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote the wasU18NotificationDisplayed bit to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write the wasU18NotificationDisplayed to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write the wasU18NotificationDisplayed to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -822,11 +821,11 @@ class AppSearchConsentWorker {
}
dao.setUx(ux.toString());
dao.writeData(mUxStatesSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote PrivacySandboxUx to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write PrivacySandboxUx to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write PrivacySandboxUx to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
@@ -865,11 +864,11 @@ class AppSearchConsentWorker {
}
dao.setEnrollmentChannel(enrollmentChannel.toString());
dao.writeData(mUxStatesSearchSession, mPackageIdentifiers, mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote PrivacySandboxUx to AppSearch: " + dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
- LogUtil.e("Failed to write PrivacySandboxUx to AppSearch ", e);
- throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ LogUtil.e(e, "Failed to write PrivacySandboxUx to AppSearch");
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE, e);
} finally {
READ_WRITE_LOCK.writeLock().unlock();
}
diff --git a/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchDao.java b/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchDao.java
index 4fdf36f67..cd52dbd72 100644
--- a/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchDao.java
+++ b/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchDao.java
@@ -16,6 +16,8 @@
package com.android.adservices.service.appsearch;
+import static com.android.adservices.service.consent.ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE;
+
import android.annotation.NonNull;
import android.os.Build;
@@ -31,6 +33,7 @@ import androidx.appsearch.app.RemoveByDocumentIdRequest;
import androidx.appsearch.app.SearchResults;
import androidx.appsearch.app.SearchSpec;
import androidx.appsearch.app.SetSchemaRequest;
+import androidx.appsearch.app.SetSchemaResponse.MigrationFailure;
import androidx.appsearch.exceptions.AppSearchException;
import com.android.adservices.AdServicesCommon;
@@ -38,7 +41,6 @@ import com.android.adservices.LogUtil;
import com.android.adservices.service.Flags;
import com.android.adservices.service.FlagsFactory;
import com.android.adservices.service.common.AllowLists;
-import com.android.adservices.service.consent.ConsentConstants;
import com.android.internal.annotations.VisibleForTesting;
import com.google.common.util.concurrent.FluentFuture;
@@ -58,12 +60,8 @@ import java.util.function.BiFunction;
* Base class for all data access objects for AppSearch. This class handles the common logic for
* reading from and writing to AppSearch.
*/
-// TODO(b/269798827): Enable for R.
@RequiresApi(Build.VERSION_CODES.S)
class AppSearchDao {
- // Timeout for AppSearch search query in milliseconds.
- private static final int TIMEOUT_MS = 500;
-
/**
* Iterate over the search results returned for the search query by AppSearch.
*
@@ -88,7 +86,7 @@ class AppSearchDao {
// Converts GenericDocument object to the type of object passed in cls.
documentResult = genericDocument.toDocumentClass(cls);
} catch (AppSearchException e) {
- LogUtil.e("Failed to convert GenericDocument to " + cls.getName(), e);
+ LogUtil.e(e, "Failed to convert GenericDocument to %s", cls.getName());
}
}
@@ -203,9 +201,11 @@ class AppSearchDao {
results -> iterateSearchResults(cls, results, executor),
executor)
.transform(result -> ((T) result), executor);
- return future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+
+ int timeout = FlagsFactory.getFlags().getAppSearchReadTimeout();
+ return future.get(timeout, TimeUnit.MILLISECONDS);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
- LogUtil.e("getConsent() Appsearch lookup failed with: ", e);
+ LogUtil.e(e, "getConsent() AppSearch lookup failed");
}
return null;
}
@@ -216,7 +216,7 @@ class AppSearchDao {
* we specify the packageIdentifier as that of the T+ AdServices APK, which after OTA, needs
* access to the data written before OTA. What is written is the subclass type of DAO.
*
- * @return the result of the write.
+ * @return the result of the write operation.
*/
FluentFuture<AppSearchBatchResult<String, Void>> writeData(
@NonNull ListenableFuture<AppSearchSession> appSearchSession,
@@ -245,14 +245,17 @@ class AppSearchDao {
// If we get failures in schemaResponse then we cannot try
// to write.
if (!setSchemaResponse.getMigrationFailures().isEmpty()) {
+ MigrationFailure failure =
+ setSchemaResponse.getMigrationFailures().get(0);
LogUtil.e(
"SetSchemaResponse migration failure: "
- + setSchemaResponse
- .getMigrationFailures()
- .get(0));
- throw new RuntimeException(
- ConsentConstants
- .ERROR_MESSAGE_APPSEARCH_FAILURE);
+ + failure);
+ String message =
+ String.format(
+ "%s Migration failure: %s",
+ ERROR_MESSAGE_APPSEARCH_FAILURE,
+ failure.getAppSearchResult());
+ throw new RuntimeException(message);
}
// The database knows about this schemaType and write can
// occur.
@@ -264,17 +267,17 @@ class AppSearchDao {
executor);
return putFuture;
} catch (AppSearchException e) {
- LogUtil.e("Cannot instantiate AppSearch database: " + e.getMessage());
+ LogUtil.e(e, "Cannot instantiate AppSearch database");
+ return FluentFuture.from(
+ Futures.immediateFailedFuture(
+ new RuntimeException(ERROR_MESSAGE_APPSEARCH_FAILURE, e)));
}
- return FluentFuture.from(
- Futures.immediateFailedFuture(
- new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE)));
}
/**
* Delete a row from the database.
*
- * @return the result of the delete.
+ * @return the result of the delete operation.
*/
protected static <T> FluentFuture<AppSearchBatchResult<String, Void>> deleteData(
@NonNull Class<T> cls,
@@ -308,8 +311,7 @@ class AppSearchDao {
.getMigrationFailures()
.get(0));
throw new RuntimeException(
- ConsentConstants
- .ERROR_MESSAGE_APPSEARCH_FAILURE);
+ ERROR_MESSAGE_APPSEARCH_FAILURE);
}
// The database knows about this schemaType and write can
// occur.
@@ -325,6 +327,6 @@ class AppSearchDao {
}
return FluentFuture.from(
Futures.immediateFailedFuture(
- new RuntimeException(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE)));
+ new RuntimeException(ERROR_MESSAGE_APPSEARCH_FAILURE)));
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorker.java b/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorker.java
index f81566cc2..b282cfefa 100644
--- a/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorker.java
+++ b/adservices/service-core/java/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorker.java
@@ -28,6 +28,7 @@ import androidx.appsearch.platformstorage.PlatformStorage;
import com.android.adservices.LogUtil;
import com.android.adservices.concurrency.AdServicesExecutors;
+import com.android.adservices.service.FlagsFactory;
import com.android.adservices.service.common.compat.FileCompatUtils;
import com.android.adservices.service.consent.ConsentConstants;
import com.android.adservices.service.measurement.rollback.MeasurementRollbackWorker;
@@ -59,7 +60,7 @@ public final class AppSearchMeasurementRollbackWorker implements MeasurementRoll
private static final ReadWriteLock READ_WRITE_LOCK = new ReentrantReadWriteLock();
// Timeout for AppSearch write query in milliseconds.
- private static final int TIMEOUT_MS = 2000;
+ private final int mTimeoutMs;
private final String mUserId;
private final String mAdServicesPackageName;
@@ -75,6 +76,8 @@ public final class AppSearchMeasurementRollbackWorker implements MeasurementRoll
mSearchSession =
PlatformStorage.createSearchSessionAsync(
new PlatformStorage.SearchContext.Builder(context, DATABASE_NAME).build());
+
+ mTimeoutMs = FlagsFactory.getFlags().getAppSearchWriteTimeout();
}
/** Return an instance of {@link AppSearchMeasurementRollbackWorker} */
@@ -98,7 +101,7 @@ public final class AppSearchMeasurementRollbackWorker implements MeasurementRoll
// don't need to share it with the T package. Thus, we can send an empty list for the
// packageIdentifiers parameter.
dao.writeData(mSearchSession, List.of(), mExecutor)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Wrote measurement rollback data to AppSearch: %s", dao);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
LogUtil.e(e, "Failed to write measurement rollback to AppSearch");
@@ -130,7 +133,7 @@ public final class AppSearchMeasurementRollbackWorker implements MeasurementRoll
mExecutor,
storageIdentifier,
AppSearchMeasurementRollbackDao.NAMESPACE)
- .get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ .get(mTimeoutMs, TimeUnit.MILLISECONDS);
LogUtil.d("Deleted MeasurementRollback data from AppSearch for: %s", storageIdentifier);
} catch (InterruptedException | TimeoutException | ExecutionException e) {
LogUtil.e(e, "Failed to delete MeasurementRollback data in AppSearch");
diff --git a/adservices/service-core/java/com/android/adservices/service/common/AdServicesCommonServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/common/AdServicesCommonServiceImpl.java
index bf002effd..ecb1e1115 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/AdServicesCommonServiceImpl.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/AdServicesCommonServiceImpl.java
@@ -58,6 +58,7 @@ import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
+import android.os.Trace;
import androidx.annotation.RequiresApi;
@@ -285,7 +286,9 @@ public class AdServicesCommonServiceImpl extends IAdServicesCommonService.Stub {
@NonNull IEnableAdServicesCallback callback) {
LogUtil.d(ENABLE_AD_SERVICES_API_CALLED_MESSAGE);
+ Trace.beginSection("AdServicesCommonService#EnableAdServices_PermissionCheck");
boolean authorizedCaller = PermissionHelper.hasModifyAdServicesStatePermission(mContext);
+ Trace.endSection();
sBackgroundExecutor.execute(
() -> {
@@ -308,7 +311,10 @@ public class AdServicesCommonServiceImpl extends IAdServicesCommonService.Stub {
return;
}
+ Trace.beginSection("AdServicesCommonService#EnableAdServices_UxEngineFlow");
mUxEngine.start(adServicesStates);
+ Trace.endSection();
+
LogUtil.d("enableAdServices(): UxEngine started.");
callback.onResult(
diff --git a/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfig.java b/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfig.java
index 5db3b171e..672e443db 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfig.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfig.java
@@ -16,6 +16,11 @@
package com.android.adservices.service.common;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_APP_ALLOWS_ALL;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_BY_APP;
import static com.android.adservices.service.common.AppManifestConfigParser.TAG_ADID;
import static com.android.adservices.service.common.AppManifestConfigParser.TAG_APPSETID;
import static com.android.adservices.service.common.AppManifestConfigParser.TAG_ATTRIBUTION;
@@ -26,6 +31,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import com.android.adservices.LogUtil;
+import com.android.adservices.service.common.AppManifestConfigCall.Result;
import java.util.function.Supplier;
@@ -96,9 +102,9 @@ public final class AppManifestConfig {
* Returns if the ad partner is permitted to access Attribution API for config represented by
* this object.
*
- * <p>If the tag is not found in the app manifest config, returns {@code false}.
+ * <p>See constants in {@link AppManifestConfigCall} for the returned value.
*/
- public boolean isAllowedAttributionAccess(@NonNull String enrollmentId) {
+ public @Result int isAllowedAttributionAccess(@NonNull String enrollmentId) {
return isAllowedAccess(TAG_ATTRIBUTION, mAttributionConfig, enrollmentId);
}
@@ -119,9 +125,9 @@ public final class AppManifestConfig {
* Returns {@code true} if an ad tech with the given enrollment ID is permitted to access Custom
* Audience API for config represented by this object.
*
- * <p>If the tag is not found in the app manifest config, returns {@code false}.
+ * <p>See constants in {@link AppManifestConfigCall} for the returned value.
*/
- public boolean isAllowedCustomAudiencesAccess(@NonNull String enrollmentId) {
+ public @Result int isAllowedCustomAudiencesAccess(@NonNull String enrollmentId) {
return isAllowedAccess(TAG_CUSTOM_AUDIENCES, mCustomAudiencesConfig, enrollmentId);
}
@@ -140,9 +146,9 @@ public final class AppManifestConfig {
* Returns if the ad partner is permitted to access Topics API for config represented by this
* object.
*
- * <p>If the tag is not found in the app manifest config, returns {@code false}.
+ * <p>See constants in {@link AppManifestConfigCall} for the returned value.
*/
- public boolean isAllowedTopicsAccess(@NonNull String enrollmentId) {
+ public @Result int isAllowedTopicsAccess(@NonNull String enrollmentId) {
return isAllowedAccess(TAG_TOPICS, mTopicsConfig, enrollmentId);
}
@@ -159,9 +165,9 @@ public final class AppManifestConfig {
/**
* Returns if sdk is permitted to access AdId API for config represented by this object.
*
- * <p>If the tag is not found in the app manifest config, returns {@code false}.
+ * <p>See constants in {@link AppManifestConfigCall} for the returned value.
*/
- public boolean isAllowedAdIdAccess(@NonNull String sdk) {
+ public @Result int isAllowedAdIdAccess(@NonNull String sdk) {
return isAllowedAccess(TAG_ADID, mAdIdConfig, sdk);
}
@@ -181,9 +187,9 @@ public final class AppManifestConfig {
/**
* Returns if sdk is permitted to access AppSetId API for config represented by this object.
*
- * <p>If the tag is not found in the app manifest config, returns {@code false}.
+ * <p>See constants in {@link AppManifestConfigCall} for the returned value.
*/
- public boolean isAllowedAppSetIdAccess(@NonNull String sdk) {
+ public @Result int isAllowedAppSetIdAccess(@NonNull String sdk) {
return isAllowedAccess(TAG_APPSETID, mAppSetIdConfig, sdk);
}
@@ -200,15 +206,21 @@ public final class AppManifestConfig {
return null;
}
- private boolean isAllowedAccess(
+ private @Result int isAllowedAccess(
String tag, @Nullable AppManifestApiConfig config, String partnerId) {
if (config == null) {
LogUtil.v(
"app manifest config tag '%s' not found, returning %b", tag, mEnabledByDefault);
- return mEnabledByDefault;
+ return mEnabledByDefault
+ ? RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION
+ : RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION;
}
-
- return config.getAllowAllToAccess()
- || config.getAllowAdPartnersToAccess().contains(partnerId);
+ if (config.getAllowAllToAccess()) {
+ return RESULT_ALLOWED_APP_ALLOWS_ALL;
+ }
+ if (config.getAllowAdPartnersToAccess().contains(partnerId)) {
+ return RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID;
+ }
+ return RESULT_DISALLOWED_BY_APP;
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigCall.java b/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigCall.java
index 449a159c3..79c93bc55 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigCall.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigCall.java
@@ -15,33 +15,162 @@
*/
package com.android.adservices.service.common;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
import java.util.Objects;
// TODO(b/310270746): make it package-protected when TopicsServiceImplTest is refactored
/** Represents a call to a public {@link AppManifestConfigHelper} method. */
public final class AppManifestConfigCall {
+
+ // TODO(b/306417555): use values from statsd atom for constants below
+ static final int API_UNSPECIFIED = 0;
+ static final int API_TOPICS = 1;
+ static final int API_CUSTOM_AUDIENCES = 2;
+ static final int API_ATTRIBUTION = 3;
+
+ @IntDef({API_TOPICS, API_CUSTOM_AUDIENCES, API_ATTRIBUTION})
+ @Retention(SOURCE)
+ public @interface ApiType {}
+
+ // TODO(b/306417555): use values from statsd atom for constants below
+ static final int RESULT_UNSPECIFIED = 0;
+ static final int RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG = 1;
+ static final int RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION = 2;
+ static final int RESULT_ALLOWED_APP_ALLOWS_ALL = 3;
+ static final int RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID = 4;
+ static final int RESULT_DISALLOWED_APP_DOES_NOT_EXIST = 5;
+ static final int RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR = 6;
+ static final int RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG = 7;
+ static final int RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION = 8;
+ static final int RESULT_DISALLOWED_BY_APP = 9;
+ static final int RESULT_DISALLOWED_GENERIC_ERROR = 10;
+
+ @IntDef({
+ RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG,
+ RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION,
+ RESULT_ALLOWED_APP_ALLOWS_ALL,
+ RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID,
+ RESULT_DISALLOWED_APP_DOES_NOT_EXIST,
+ RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR,
+ RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG,
+ RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION,
+ RESULT_DISALLOWED_BY_APP,
+ RESULT_DISALLOWED_GENERIC_ERROR
+ })
+ @Retention(SOURCE)
+ public @interface Result {}
+
+ @VisibleForTesting static final String INVALID_API_TEMPLATE = "Invalid API: %d";
+
public final String packageName;
- public boolean appExists;
- public boolean appHasConfig;
- public boolean enabledByDefault;
- public boolean result;
+ public final @ApiType int api;
+ public @Result int result;
- public AppManifestConfigCall(String packageName) {
+ public AppManifestConfigCall(String packageName, @ApiType int api) {
+ switch (api) {
+ case API_TOPICS:
+ case API_CUSTOM_AUDIENCES:
+ case API_ATTRIBUTION:
+ this.api = api;
+ break;
+ default:
+ throw new IllegalArgumentException(String.format(INVALID_API_TEMPLATE, api));
+ }
this.packageName = Objects.requireNonNull(packageName, "packageName cannot be null");
}
@Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ AppManifestConfigCall other = (AppManifestConfigCall) obj;
+ return api == other.api
+ && Objects.equals(packageName, other.packageName)
+ && result == other.result;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(api, packageName, result);
+ }
+
+ @Override
public String toString() {
return "AppManifestConfigCall[pkg="
+ packageName
- + ", appExists="
- + appExists
- + ", appHasConfig="
- + appHasConfig
- + ", enabledByDefault="
- + enabledByDefault
+ + ", api="
+ + apiToString(api)
+ ", result="
- + result
+ + resultToString(result)
+ "]";
}
+
+ static String resultToString(@Result int result) {
+ switch (result) {
+ case RESULT_UNSPECIFIED:
+ return "UNSPECIFIED";
+ case RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG:
+ return "ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG";
+ case RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION:
+ return "ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION";
+ case RESULT_ALLOWED_APP_ALLOWS_ALL:
+ return "ALLOWED_APP_ALLOWS_ALL";
+ case RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID:
+ return "ALLOWED_APP_ALLOWS_SPECIFIC_ID";
+ case RESULT_DISALLOWED_APP_DOES_NOT_EXIST:
+ return "DISALLOWED_APP_DOES_NOT_EXIST";
+ case RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR:
+ return "DISALLOWED_APP_CONFIG_PARSING_ERROR";
+ case RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG:
+ return "DISALLOWED_APP_DOES_NOT_HAVE_CONFIG";
+ case RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION:
+ return "DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION";
+ case RESULT_DISALLOWED_BY_APP:
+ return "DISALLOWED_BY_APP";
+ case RESULT_DISALLOWED_GENERIC_ERROR:
+ return "DISALLOWED_GENERIC_ERROR";
+ default:
+ return "INVALID-" + result;
+ }
+ }
+
+ static String apiToString(@ApiType int result) {
+ switch (result) {
+ case API_UNSPECIFIED:
+ return "UNSPECIFIED";
+ case API_TOPICS:
+ return "TOPICS";
+ case API_CUSTOM_AUDIENCES:
+ return "CUSTOM_AUDIENCES";
+ case API_ATTRIBUTION:
+ return "ATTRIBUTION";
+ default:
+ return "INVALID-" + result;
+ }
+ }
+
+ static boolean isAllowed(@Result int result) {
+ switch (result) {
+ case RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG:
+ case RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION:
+ case RESULT_ALLOWED_APP_ALLOWS_ALL:
+ case RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID:
+ return true;
+ default:
+ return false;
+ }
+ }
}
diff --git a/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigHelper.java b/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigHelper.java
index 0fe09ff8d..b549717ee 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigHelper.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigHelper.java
@@ -16,6 +16,18 @@
package com.android.adservices.service.common;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_ATTRIBUTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_CUSTOM_AUDIENCES;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_TOPICS;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_DOES_NOT_EXIST;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_BY_APP;
+import static com.android.adservices.service.common.AppManifestConfigCall.isAllowed;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__APP_MANIFEST_CONFIG_PARSING_ERROR;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__APP_MANIFEST_CONFIG_PARSING_ERROR;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON;
@@ -62,6 +74,7 @@ public class AppManifestConfigHelper {
@NonNull String enrollmentId) {
return isAllowedApiAccess(
"isAllowedAttributionAccess()",
+ API_ATTRIBUTION,
appPackageName,
enrollmentId,
config -> config.isAllowedAttributionAccess(enrollmentId));
@@ -80,6 +93,7 @@ public class AppManifestConfigHelper {
@NonNull String enrollmentId) {
return isAllowedApiAccess(
"isAllowedCustomAudiencesAccess()",
+ API_CUSTOM_AUDIENCES,
appPackageName,
enrollmentId,
config -> config.isAllowedCustomAudiencesAccess(enrollmentId));
@@ -101,14 +115,17 @@ public class AppManifestConfigHelper {
@NonNull String enrollmentId) {
return isAllowedApiAccess(
"isAllowedTopicsAccess()",
+ API_TOPICS,
appPackageName,
enrollmentId,
config -> {
// If the request comes directly from the app, check that the app has declared
// that it includes this Sdk library.
if (!useSandboxCheck) {
- return config.getIncludesSdkLibraryConfig().contains(enrollmentId)
- && config.isAllowedTopicsAccess(enrollmentId);
+ return (config.getIncludesSdkLibraryConfig().contains(enrollmentId)
+ && isAllowed(config.isAllowedTopicsAccess(enrollmentId)))
+ ? RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID
+ : RESULT_DISALLOWED_BY_APP;
}
// If the request comes from the SdkRuntime, then the app had to have declared
@@ -118,29 +135,22 @@ public class AppManifestConfigHelper {
}
@Nullable
- private static XmlResourceParser getXmlParser(AppManifestConfigCall call)
+ private static XmlResourceParser getXmlParser(String appPackageName)
throws NameNotFoundException, XmlParseException, XmlPullParserException, IOException {
Context context = ApplicationContextSingleton.get();
- String appPackageName = call.packageName;
- LogUtil.v("getXmlParser(%s): context=%s", call.packageName, context);
+ LogUtil.v("getXmlParser(%s): context=%s", appPackageName, context);
+
// NOTE: resources is only used pre-S, but it must be called regardless to make sure the app
// exists
Resources resources =
context.getPackageManager().getResourcesForApplication(appPackageName);
- call.appExists = true;
-
Integer resId =
SdkLevel.isAtLeastS()
? getAdServicesConfigResourceIdOnExistingPackageOnSPlus(
context, appPackageName)
: getAdServicesConfigResourceIdOnRMinus(context, resources, appPackageName);
- XmlResourceParser xmlResourceParser = null;
- if (resId != null) {
- xmlResourceParser = resources.getXml(resId);
- call.appHasConfig = true;
- }
- return xmlResourceParser;
+ return resId != null ? resources.getXml(resId) : null;
}
@Nullable
@@ -171,28 +181,37 @@ public class AppManifestConfigHelper {
private static boolean isAllowedApiAccess(
String method,
+ int api,
String appPackageName,
String enrollmentId,
ApiAccessChecker checker) {
Objects.requireNonNull(appPackageName);
Objects.requireNonNull(enrollmentId);
- AppManifestConfigCall call = new AppManifestConfigCall(appPackageName);
- call.enabledByDefault = FlagsFactory.getFlags().getAppConfigReturnsEnabledByDefault();
+
+ AppManifestConfigCall call = new AppManifestConfigCall(appPackageName, api);
+ boolean enabledByDefault = FlagsFactory.getFlags().getAppConfigReturnsEnabledByDefault();
+
try {
- XmlResourceParser in = getXmlParser(call);
+ XmlResourceParser in = getXmlParser(appPackageName);
if (in == null) {
+ call.result =
+ enabledByDefault
+ ? RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG
+ : RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG;
LogUtil.v(
"%s: returning %b for app (%s) that doesn't have the AdServices XML config",
- method, call.enabledByDefault, appPackageName);
- return call.enabledByDefault;
+ method, enabledByDefault, appPackageName);
+ return enabledByDefault;
}
AppManifestConfig appManifestConfig =
- AppManifestConfigParser.getConfig(in, call.enabledByDefault);
+ AppManifestConfigParser.getConfig(in, enabledByDefault);
call.result = checker.isAllowedAccess(appManifestConfig);
} catch (NameNotFoundException e) {
+ call.result = RESULT_DISALLOWED_APP_DOES_NOT_EXIST;
LogUtil.v(
"Name not found while looking for manifest for app %s: %s", appPackageName, e);
} catch (Exception e) {
+ call.result = RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR;
LogUtil.e(e, "App manifest parse failed.");
ErrorLogUtil.e(
e,
@@ -201,10 +220,10 @@ public class AppManifestConfigHelper {
} finally {
AppManifestConfigMetricsLogger.logUsage(call);
}
- return call.result;
+ return isAllowed(call.result);
}
private interface ApiAccessChecker {
- boolean isAllowedAccess(AppManifestConfig config);
+ int isAllowedAccess(AppManifestConfig config);
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigMetricsLogger.java b/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigMetricsLogger.java
index d573e05ef..17524ee94 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigMetricsLogger.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/AppManifestConfigMetricsLogger.java
@@ -15,9 +15,13 @@
*/
package com.android.adservices.service.common;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_UNSPECIFIED;
+import static com.android.adservices.service.common.AppManifestConfigCall.apiToString;
+import static com.android.adservices.service.common.AppManifestConfigCall.resultToString;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__APP_MANIFEST_CONFIG_LOGGING_ERROR;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_EXCEPTION;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_UPDATE_FAILURE;
-import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON;
import android.content.Context;
import android.content.SharedPreferences;
@@ -27,12 +31,15 @@ import com.android.adservices.LogUtil;
import com.android.adservices.concurrency.AdServicesExecutors;
import com.android.adservices.errorlogging.ErrorLogUtil;
import com.android.adservices.service.FlagsFactory;
+import com.android.adservices.service.common.AppManifestConfigCall.ApiType;
+import com.android.adservices.service.common.AppManifestConfigCall.Result;
import com.android.adservices.service.common.compat.FileCompatUtils;
import com.android.adservices.shared.common.ApplicationContextSingleton;
import com.android.internal.annotations.VisibleForTesting;
import java.io.File;
import java.io.PrintWriter;
+import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
@@ -45,40 +52,39 @@ public final class AppManifestConfigMetricsLogger {
static final String PREFS_NAME =
FileCompatUtils.getAdservicesFilename("AppManifestConfigMetricsLogger");
- private static final int NOT_SET = -1;
- private static final int FLAG_APP_EXISTS = 0x1;
- private static final int FLAG_APP_HAS_CONFIG = 0x2;
- private static final int FLAG_ENABLED_BY_DEFAULT = 0x4;
+ @VisibleForTesting static final String PREFS_KEY_TEMPLATE = "%s-%d";
// TODO(b/310270746): make it package-protected when TopicsServiceImplTest is refactored
/** Represents a call to a public {@link AppManifestConfigHelper} method. */
/** Logs the app usage. */
public static void logUsage(AppManifestConfigCall call) {
Objects.requireNonNull(call, "call cannot be null");
+
+ // Cannot be RESULT_UNSPECIFIED because that's used to check if the shared preferences value
+ // doesn't exist yet
+ if (call.result == RESULT_UNSPECIFIED) {
+ LogUtil.e("invalid call result: %s", call);
+ ErrorLogUtil.e(
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__APP_MANIFEST_CONFIG_LOGGING_ERROR,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON);
+ return;
+ }
AdServicesExecutors.getBackgroundExecutor().execute(() -> handleLogUsage(call));
}
private static void handleLogUsage(AppManifestConfigCall call) {
Context context = ApplicationContextSingleton.get();
try {
- int newValue =
- (call.appExists ? FLAG_APP_EXISTS : 0)
- | (call.appHasConfig ? FLAG_APP_HAS_CONFIG : 0)
- | (call.enabledByDefault ? FLAG_ENABLED_BY_DEFAULT : 0);
+ @Result int newValue = call.result;
LogUtil.d(
- "AppManifestConfigMetricsLogger.logUsage(): app=[name=%s, exists=%b,"
- + " hasConfig=%b], enabledByDefault=%b, newValue=%d",
- call.packageName,
- call.appExists,
- call.appHasConfig,
- call.enabledByDefault,
- newValue);
+ "AppManifestConfigMetricsLogger.logUsage(): call=%s, newValue=%d",
+ call, newValue);
SharedPreferences prefs = getPrefs(context);
- String key = call.packageName;
+ String key = String.format(Locale.US, PREFS_KEY_TEMPLATE, call.packageName, call.api);
- int currentValue = prefs.getInt(key, NOT_SET);
- if (currentValue == NOT_SET) {
+ @Result int currentValue = prefs.getInt(key, RESULT_UNSPECIFIED);
+ if (currentValue == RESULT_UNSPECIFIED) {
LogUtil.v("Logging for the first time (value=%d)", newValue);
} else if (currentValue != newValue) {
LogUtil.v("Logging as value change (was %d)", currentValue);
@@ -95,28 +101,14 @@ public final class AppManifestConfigMetricsLogger {
LogUtil.v("Changes committed");
} else {
LogUtil.e(
- "logUsage(ctx, file=%s, app=%s, appExist=%b, appHasConfig=%b,"
- + " enabledByDefault=%b, newValue=%d): failed to commit",
- PREFS_NAME,
- call.packageName,
- call.appExists,
- call.appHasConfig,
- call.enabledByDefault,
- newValue);
+ "logUsage(ctx, file=%s, call=%s, newValue=%d): failed to commit",
+ PREFS_NAME, call, newValue);
ErrorLogUtil.e(
AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_UPDATE_FAILURE,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON);
}
} catch (Exception e) {
- LogUtil.e(
- e,
- "logUsage(ctx, file=%s, app=%s, appExist=%b, appHasConfig=%b,"
- + " enabledByDefault=%b) failed",
- PREFS_NAME,
- call.packageName,
- call.appExists,
- call.appHasConfig,
- call.enabledByDefault);
+ LogUtil.e(e, "logUsage(ctx, file=%s, call=%s) failed", PREFS_NAME, call);
ErrorLogUtil.e(
e,
AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_EXCEPTION,
@@ -126,13 +118,13 @@ public final class AppManifestConfigMetricsLogger {
/** Dumps the internal state. */
public static void dump(Context context, PrintWriter pw) {
+ String prefix = " ";
pw.println("AppManifestConfigMetricsLogger");
- String prefix = " ";
- @SuppressWarnings("NewAdServicesFile") // PREFS_NAME already called FileCompatUtils
// NOTE: shared_prefs is hard-coded on ContextImpl, but unfortunately Context doesn't offer
// any API we could use here to get that path (getSharedPreferencesPath() is @removed and
// the available APIs return a SharedPreferences, not a File).
+ @SuppressWarnings("NewAdServicesFile") // PREFS_NAME already called FileCompatUtils
String path =
new File(context.getDataDir() + "/shared_prefs", PREFS_NAME).getAbsolutePath();
pw.printf("%sPreferences file: %s.xml\n", prefix, path);
@@ -147,19 +139,25 @@ public final class AppManifestConfigMetricsLogger {
String prefix2 = prefix + " ";
for (Entry<String, ?> pref : appPrefs.entrySet()) {
- String app = pref.getKey();
+ String key = pref.getKey();
+ String appAndApi = key;
+ try {
+ String[] keyParts = key.split("-");
+ String app = keyParts[0];
+ @ApiType int api = Integer.parseInt(keyParts[1]);
+ appAndApi = app + "-" + apiToString(api);
+ } catch (Exception e) {
+ LogUtil.e(e, "failed to parse key %s", key);
+ }
Object value = pref.getValue();
if (value instanceof Integer) {
- int flags = (Integer) value;
- boolean appExists = (flags & FLAG_APP_EXISTS) != 0;
- boolean appHasConfig = (flags & FLAG_APP_HAS_CONFIG) != 0;
- boolean enabledByDefault = (flags & FLAG_ENABLED_BY_DEFAULT) != 0;
- pw.printf(
- "%s%s: rawValue=%d, appExists=%b, appHasConfig=%b, enabledByDefault=%b\n",
- prefix2, app, flags, appExists, appHasConfig, enabledByDefault);
+ @Result int result = (Integer) value;
+ pw.printf("%s%s: %s\n", prefix2, appAndApi, resultToString(result));
} else {
// Shouldn't happen
- pw.printf(" %s: unexpected value %s (class %s):\n", app, value, value.getClass());
+ pw.printf(
+ " %s: unexpected value %s (class %s):\n",
+ appAndApi, value, value.getClass());
}
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/common/FledgeAuthorizationFilter.java b/adservices/service-core/java/com/android/adservices/service/common/FledgeAuthorizationFilter.java
index c99b0b9a3..7809ecd40 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/FledgeAuthorizationFilter.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/FledgeAuthorizationFilter.java
@@ -123,47 +123,22 @@ public class FledgeAuthorizationFilter {
* @param apiNameLoggingId the id of the api being called
* @throws SecurityException if the package did not declare custom audience permission
*/
- public void assertAppDeclaredCustomAudiencePermission(
+ public void assertAppDeclaredPermission(
@NonNull Context context, @NonNull String appPackageName, int apiNameLoggingId)
throws SecurityException {
Objects.requireNonNull(context);
Objects.requireNonNull(appPackageName);
if (!PermissionHelper.hasCustomAudiencesPermission(context, appPackageName)) {
- logAndThrowPermissionFailure(apiNameLoggingId);
- }
- }
-
- /**
- * Check if the app had declared the protected signals permission.
- *
- * @param context api service context
- * @param apiNameLoggingId the id of the api being called
- * @throws SecurityException if the package did not declare custom audience permission
- */
- public void assertAppDeclaredProtectedSignalsPermission(
- @NonNull Context context, @NonNull String appPackageName, int apiNameLoggingId)
- throws SecurityException {
- Objects.requireNonNull(context);
- Objects.requireNonNull(appPackageName);
-
- if (!PermissionHelper.hasProtectedSignalsPermission(context, appPackageName)) {
- /*
- * Using the same message for both since getAdSelectionData can be called with either
- * permission and we don't want the error message to depend on which is checked first.
- */
- logAndThrowPermissionFailure(apiNameLoggingId);
+ sLogger.v("Permission not declared by caller in API %d", apiNameLoggingId);
+ mAdServicesLogger.logFledgeApiCallStats(
+ apiNameLoggingId, STATUS_PERMISSION_NOT_REQUESTED, 0);
+ throw new SecurityException(
+ AdServicesStatusUtils
+ .SECURITY_EXCEPTION_PERMISSION_NOT_REQUESTED_ERROR_MESSAGE);
}
}
- private void logAndThrowPermissionFailure(int apiNameLoggingId) {
- sLogger.v("Permission not declared by caller in API %d", apiNameLoggingId);
- mAdServicesLogger.logFledgeApiCallStats(
- apiNameLoggingId, STATUS_PERMISSION_NOT_REQUESTED, 0);
- throw new SecurityException(
- AdServicesStatusUtils.SECURITY_EXCEPTION_PERMISSION_NOT_REQUESTED_ERROR_MESSAGE);
- }
-
/**
* Check if a certain ad tech is enrolled and authorized to perform the operation for the
* package.
diff --git a/adservices/service-core/java/com/android/adservices/service/common/PackageChangedReceiver.java b/adservices/service-core/java/com/android/adservices/service/common/PackageChangedReceiver.java
index e2afca136..35d6ff658 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/PackageChangedReceiver.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/PackageChangedReceiver.java
@@ -295,6 +295,10 @@ public class PackageChangedReceiver extends BroadcastReceiver {
@VisibleForTesting
void consentOnPackageFullyRemoved(
@NonNull Context context, @NonNull Uri packageUri, int packageUid) {
+ if (!SdkLevel.isAtLeastS()) {
+ LogUtil.d("consentOnPackageFullyRemoved is not needed on Android R, returning...");
+ return;
+ }
Objects.requireNonNull(context);
Objects.requireNonNull(packageUri);
diff --git a/adservices/service-core/java/com/android/adservices/service/common/PermissionHelper.java b/adservices/service-core/java/com/android/adservices/service/common/PermissionHelper.java
index 67142b6d3..d02225e4e 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/PermissionHelper.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/PermissionHelper.java
@@ -101,16 +101,6 @@ public final class PermissionHelper {
}
/**
- * @return {@code true} if the caller has the permission to invoke Protected Signals APIs.
- */
- public static boolean hasProtectedSignalsPermission(
- @NonNull Context context, @NonNull String appPackageName) {
- // TODO(b/236268316): Add check for SDK permission.
- return hasPermission(
- context, appPackageName, AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS);
- }
-
- /**
* @return {@code true} if the caller has the permission to invoke AdService's state
* modification API.
*/
diff --git a/adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java b/adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java
index f809950c9..7ab2ff9fa 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java
@@ -175,7 +175,7 @@ public class AdServicesHttpsClient {
// Setting true explicitly to follow redirects
Uri uri = Uri.parse(url.toString());
if (WebAddresses.isLocalhost(uri) && devContext.getDevOptionsEnabled()) {
- LogUtil.v("Using unsafe HTTPS for url ", url.toString());
+ LogUtil.v("Using unsafe HTTPS for url %s", url.toString());
urlConnection.setSSLSocketFactory(getUnsafeSslSocketFactory());
} else if (WebAddresses.isLocalhost(uri)) {
LogUtil.v(
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/AdServicesStorageManager.java b/adservices/service-core/java/com/android/adservices/service/consent/AdServicesStorageManager.java
index c32e72702..f3aa86683 100644
--- a/adservices/service-core/java/com/android/adservices/service/consent/AdServicesStorageManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/consent/AdServicesStorageManager.java
@@ -125,13 +125,20 @@ public final class AdServicesStorageManager implements IConsentStorage {
@Override
public AdServicesApiConsent getConsent(AdServicesApiType apiType) {
int consentApiType = apiType.toConsentApiType();
- return AdServicesApiConsent.getConsent(
- mAdServicesManager.getConsent(consentApiType).isIsGiven());
+ ConsentParcel consentParcel = mAdServicesManager.getConsent(consentApiType);
+ if (consentParcel == null) {
+ return AdServicesApiConsent.REVOKED;
+ }
+ return AdServicesApiConsent.getConsent(consentParcel.isIsGiven());
}
/** Returns the current privacy sandbox feature. */
@Override
- public PrivacySandboxFeatureType getCurrentPrivacySandboxFeature() {
+ public PrivacySandboxFeatureType getCurrentPrivacySandboxFeature() throws IOException {
+ if (mAdServicesManager == null
+ || mAdServicesManager.getCurrentPrivacySandboxFeature() == null) {
+ return PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED;
+ }
return PrivacySandboxFeatureType.valueOf(
mAdServicesManager.getCurrentPrivacySandboxFeature());
}
@@ -434,7 +441,8 @@ public final class AdServicesStorageManager implements IConsentStorage {
return mAdServicesManager.wasU18NotificationDisplayed();
}
- private PrivacySandboxUxCollection convertUxString(String uxString) {
+ private PrivacySandboxUxCollection convertUxString(@NonNull String uxString) {
+ Objects.requireNonNull(uxString);
return Stream.of(PrivacySandboxUxCollection.values())
.filter(ux -> uxString.equals(ux.toString()))
.findFirst()
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/AppConsentForRStorageManager.java b/adservices/service-core/java/com/android/adservices/service/consent/AppConsentForRStorageManager.java
new file mode 100644
index 000000000..259b57cbd
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/service/consent/AppConsentForRStorageManager.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2023 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.service.consent;
+
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.adservices.data.common.BooleanFileDatastore;
+import com.android.adservices.data.consent.AppConsentDao;
+import com.android.adservices.service.extdata.AdServicesExtDataStorageServiceManager;
+import com.android.adservices.service.ui.data.UxStatesDao;
+
+import com.google.common.collect.ImmutableList;
+
+import java.io.IOException;
+
+/**
+ * AppConsentStorageManager to handle user's consent related Apis in Android R.
+ *
+ * <p>It shares similarities with AppConsentStorageManager's logic, but adds additional storage
+ * functionality specific to AdServicesExtDataStorageServiceManager.
+ *
+ * <p>Used in PPAPI_AND_ADEXT_SERVICE
+ */
+@RequiresApi(Build.VERSION_CODES.S)
+public class AppConsentForRStorageManager extends AppConsentStorageManager {
+
+ private final AdServicesExtDataStorageServiceManager mAdExtDataManager;
+ /**
+ * Constructor of AppConsentForRStorageManager
+ *
+ * @param datastore stores consent
+ * @param appConsentDao mostly used by FLEDGE
+ * @param uxStatesDao stores ux related data
+ */
+ public AppConsentForRStorageManager(
+ BooleanFileDatastore datastore,
+ AppConsentDao appConsentDao,
+ UxStatesDao uxStatesDao,
+ AdServicesExtDataStorageServiceManager adExtDataManager) {
+ super(datastore, appConsentDao, uxStatesDao);
+ this.mAdExtDataManager = adExtDataManager;
+ }
+
+ /** Clear ConsentForUninstalledApp, not support for Measurement. */
+ @Override
+ public void clearAllAppConsentData() {
+ // PPAPI_AND_ADEXT_SERVICE is only set on R which supports only
+ // Measurement.
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(/* illegalAction= */ "reset consent for apps"));
+ }
+
+ /** Clear ConsentForUninstalledApp, not support for Measurement. */
+ @Override
+ public void clearConsentForUninstalledApp(String packageName) {
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(/* illegalAction= */ "clear consent for uninstalled app"));
+ }
+
+ /** Clear ConsentForUninstalledApp, not support for Measurement. */
+ @Override
+ public void clearConsentForUninstalledApp(String packageName, int packageUid) {
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(/* illegalAction= */ "clear consent for uninstalled app"));
+ }
+
+ /** Clear KnownAppsWithConsent flag, not support for Measurement. */
+ @Override
+ public void clearKnownAppsWithConsent() {
+ // PPAPI_AND_ADEXT_SERVICE is only set on R which supports only
+ // Measurement.
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(/* illegalAction= */ "reset apps"));
+ }
+
+ /** Gets getAppsWithRevokedConsent flag, not support for Measurement. */
+ @Override
+ public ImmutableList<String> getAppsWithRevokedConsent() {
+ // PPAPI_AND_ADEXT_SERVICE is only set on R which supports only
+ // Measurement.
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(/* illegalAction= */ "fetch apps with revoked consent"));
+ }
+
+ /** Gets Consent by api flag. */
+ @Override
+ public AdServicesApiConsent getConsent(AdServicesApiType apiType) {
+ if (apiType == AdServicesApiType.MEASUREMENTS) {
+ return AdServicesApiConsent.getConsent(mAdExtDataManager.getMsmtConsent());
+ }
+ return AdServicesApiConsent.REVOKED;
+ }
+
+ /** Gets getKnownAppsWithConsent flag, not support for Measurement. */
+ @Override
+ public ImmutableList<String> getKnownAppsWithConsent() throws IOException {
+ // PPAPI_AND_ADEXT_SERVICE is only set on R which supports only
+ // Measurement.
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(/* illegalAction= */ "fetch apps with consent"));
+ }
+
+ /** Gets UserManualInteraction flag. */
+ @Override
+ public int getUserManualInteractionWithConsent() {
+ return mAdExtDataManager.getManualInteractionWithConsentStatus();
+ }
+
+ /** Gets isAdultAccount flag. */
+ @Override
+ public boolean isAdultAccount() {
+ return mAdExtDataManager.getIsAdultAccount();
+ }
+
+ /** Gets isConsentRevokedForApp flag, not support for Measurement. */
+ @Override
+ public boolean isConsentRevokedForApp(String packageName) {
+ // PPAPI_AND_ADEXT_SERVICE is only set on R which supports only
+ // Measurement.
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(
+ /* illegalAction= */ "check if consent has been revoked for" + " app"));
+ }
+
+ /** Gets isU18 account flag. */
+ @Override
+ public boolean isU18Account() {
+ return mAdExtDataManager.getIsU18Account();
+ }
+
+ /** Records GA notification displayed. */
+ @Override
+ public void recordGaUxNotificationDisplayed(boolean wasGaUxDisplayed) {
+ // PPAPI_AND_ADEXT_SERVICE is only set on R which should never show
+ // GA UX.
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(
+ /* illegalAction= */ "store if GA notification was displayed"));
+ }
+
+ /** Records notification displayed. */
+ @Override
+ public void recordNotificationDisplayed(boolean wasNotificationDisplayed) {
+ // PPAPI_AND_ADEXT_SERVICE is only set on R which should never show
+ // Beta UX.
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(/* illegalAction= */ "store if beta notif was displayed"));
+ }
+
+ /** Records user manual interaction bit. */
+ @Override
+ public void recordUserManualInteractionWithConsent(int interaction) {
+ mAdExtDataManager.setManualInteractionWithConsentStatus(interaction);
+ }
+
+ /** Sets consent by api type. */
+ @Override
+ public void setAdultAccount(boolean isAdultAccount) {
+ mAdExtDataManager.setIsAdultAccount(isAdultAccount);
+ }
+
+ /** Sets consent by api type. */
+ @Override
+ public void setConsent(AdServicesApiType apiType, boolean isGiven) throws IOException {
+ if (apiType == AdServicesApiType.ALL_API) {
+ super.setConsent(apiType, isGiven);
+ return;
+ }
+ // PPAPI_AND_ADEXT_SERVICE is only set on R which supports only
+ // Measurement. There should never be a call to set consent for other PPAPIs.
+ if (apiType != AdServicesApiType.MEASUREMENTS) {
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(
+ /* illegalAction= */ "set consent for a non-msmt API"));
+ }
+ mAdExtDataManager.setMsmtConsent(isGiven);
+ }
+
+ /**
+ * setConsentForApp.
+ *
+ * <p>PPAPI_AND_ADEXT_SERVICE is only set on R which only supports Measurement
+ */
+ @Override
+ public void setConsentForApp(String packageName, boolean isConsentRevoked) {
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(/* illegalAction= */ "revoke consent for app"));
+ }
+
+ /**
+ * SetConsentForAppIfNew.
+ *
+ * <p>PPAPI_AND_ADEXT_SERVICE is only set on R which only supports Measurement
+ */
+ @Override
+ public boolean setConsentForAppIfNew(String packageName, boolean isConsentRevoked) {
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(
+ /* illegalAction= */ "check if consent has been revoked for" + " app"));
+ }
+
+ @Override
+ public void recordDefaultConsent(AdServicesApiType apiType, boolean defaultConsent)
+ throws IOException {
+ if (apiType == AdServicesApiType.MEASUREMENTS) {
+ super.recordDefaultConsent(apiType, defaultConsent);
+ } else {
+ throw new IllegalStateException(
+ getAdExtExceptionMessage(
+ /* illegalAction= */ "record default consent for "
+ + apiType.toString()));
+ }
+ }
+
+ /** Stores isU18Account bit in AdExtData. */
+ @Override
+ public void setU18Account(boolean isU18Account) {
+ mAdExtDataManager.setIsU18Account(isU18Account);
+ }
+
+ /** Stores U18 notification bit in AdExtData. */
+ @Override
+ public void setU18NotificationDisplayed(boolean wasU18NotificationDisplayed) {
+ mAdExtDataManager.setNotificationDisplayed(wasU18NotificationDisplayed);
+ }
+
+ /** GA UX is never shown on R, so this info is not stored. */
+ @Override
+ public boolean wasGaUxNotificationDisplayed() {
+ return false;
+ }
+
+ /** Beta UX is never shown on R, so this info is not stored. */
+ @Override
+ public boolean wasNotificationDisplayed() {
+ return false;
+ }
+
+ /** Android R only U18 notification is allowed to be displayed. */
+ @Override
+ public boolean wasU18NotificationDisplayed() {
+ return mAdExtDataManager.getNotificationDisplayed();
+ }
+
+ private static String getAdExtExceptionMessage(String illegalAction) {
+ return String.format(
+ "Attempting to %s using PPAPI_AND_ADEXT_SERVICE consent source of truth!",
+ illegalAction);
+ }
+}
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/AppConsentStorageManager.java b/adservices/service-core/java/com/android/adservices/service/consent/AppConsentStorageManager.java
index a7dc3050a..af1b2ddd0 100644
--- a/adservices/service-core/java/com/android/adservices/service/consent/AppConsentStorageManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/consent/AppConsentStorageManager.java
@@ -31,6 +31,7 @@ import com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollectio
import com.google.common.collect.ImmutableList;
import java.io.IOException;
+import java.util.Objects;
import java.util.stream.Collectors;
/**
@@ -131,7 +132,8 @@ public class AppConsentStorageManager implements IConsentStorage {
*/
@Override
public AdServicesApiConsent getConsent(AdServicesApiType apiType) {
- return AdServicesApiConsent.getConsent(mDatastore.get(apiType.toPpApiDatastoreKey()));
+ return AdServicesApiConsent.getConsent(
+ Objects.requireNonNullElse(mDatastore.get(apiType.toPpApiDatastoreKey()), false));
}
/**
@@ -153,6 +155,15 @@ public class AppConsentStorageManager implements IConsentStorage {
return PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED;
}
+ /** Set the current privacy sandbox feature. */
+ @Override
+ public void setCurrentPrivacySandboxFeature(PrivacySandboxFeatureType featureType)
+ throws IOException {
+ for (PrivacySandboxFeatureType currentFeatureType : PrivacySandboxFeatureType.values()) {
+ mDatastore.put(currentFeatureType.name(), currentFeatureType == featureType);
+ }
+ }
+
/**
* Retrieves the default AdId state.
*
@@ -160,7 +171,8 @@ public class AppConsentStorageManager implements IConsentStorage {
*/
@Override
public boolean getDefaultAdIdState() {
- return mDatastore.get(ConsentConstants.DEFAULT_AD_ID_STATE);
+ return Objects.requireNonNullElse(
+ mDatastore.get(ConsentConstants.DEFAULT_AD_ID_STATE), false);
}
/**
@@ -170,7 +182,9 @@ public class AppConsentStorageManager implements IConsentStorage {
*/
@Override
public AdServicesApiConsent getDefaultConsent(AdServicesApiType apiType) {
- return AdServicesApiConsent.getConsent(mDatastore.get(apiType.toPpApiDatastoreKey()));
+ return AdServicesApiConsent.getConsent(
+ Objects.requireNonNullElse(
+ mDatastore.get(apiType.toDefaultConsentDatastoreKey()), false));
}
/** Returns current enrollment channel. */
@@ -215,16 +229,34 @@ public class AppConsentStorageManager implements IConsentStorage {
return mUxStatesDao.getUx();
}
+ /** Set the current UX to storage. */
+ @Override
+ public void setUx(PrivacySandboxUxCollection ux) {
+ mUxStatesDao.setUx(ux);
+ }
+
/** Returns whether the isAdIdEnabled bit is true. */
@Override
public boolean isAdIdEnabled() {
- return mDatastore.get(ConsentConstants.IS_AD_ID_ENABLED);
+ return Objects.requireNonNullElse(mDatastore.get(ConsentConstants.IS_AD_ID_ENABLED), false);
+ }
+
+ /** Set the AdIdEnabled bit to storage. */
+ @Override
+ public void setAdIdEnabled(boolean isAdIdEnabled) throws IOException {
+ mDatastore.put(ConsentConstants.IS_AD_ID_ENABLED, isAdIdEnabled);
}
/** Returns whether the isAdultAccount bit is true. */
@Override
public boolean isAdultAccount() {
- return mDatastore.get(ConsentConstants.IS_ADULT_ACCOUNT);
+ return Objects.requireNonNullElse(mDatastore.get(ConsentConstants.IS_ADULT_ACCOUNT), false);
+ }
+
+ /** Set the AdultAccount bit to storage. */
+ @Override
+ public void setAdultAccount(boolean isAdultAccount) throws IOException {
+ mDatastore.put(ConsentConstants.IS_ADULT_ACCOUNT, isAdultAccount);
}
/**
@@ -241,7 +273,8 @@ public class AppConsentStorageManager implements IConsentStorage {
@Override
public boolean isConsentRevokedForApp(String packageName) throws IllegalArgumentException {
try {
- return mAppConsentDao.isConsentRevokedForApp(packageName);
+ return Objects.requireNonNullElse(
+ mAppConsentDao.isConsentRevokedForApp(packageName), false);
} catch (IOException exception) {
LogUtil.e(exception, "FLEDGE consent check failed due to IOException");
}
@@ -251,13 +284,26 @@ public class AppConsentStorageManager implements IConsentStorage {
/** Returns whether the isEntryPointEnabled bit is true. */
@Override
public boolean isEntryPointEnabled() {
- return mDatastore.get(ConsentConstants.IS_ENTRY_POINT_ENABLED);
+ return Objects.requireNonNullElse(
+ mDatastore.get(ConsentConstants.IS_ENTRY_POINT_ENABLED), false);
+ }
+
+ /** Set the EntryPointEnabled bit to storage . */
+ @Override
+ public void setEntryPointEnabled(boolean isEntryPointEnabled) throws IOException {
+ mDatastore.put(ConsentConstants.IS_ENTRY_POINT_ENABLED, isEntryPointEnabled);
}
/** Returns whether the isU18Account bit is true. */
@Override
public boolean isU18Account() {
- return mDatastore.get(ConsentConstants.IS_U18_ACCOUNT);
+ return Objects.requireNonNullElse(mDatastore.get(ConsentConstants.IS_U18_ACCOUNT), false);
+ }
+
+ /** Set the U18Account bit to storage. */
+ @Override
+ public void setU18Account(boolean isU18Account) throws IOException {
+ mDatastore.put(ConsentConstants.IS_U18_ACCOUNT, isU18Account);
}
/** Saves the default AdId state bit to data stores based on source of truth. */
@@ -270,7 +316,7 @@ public class AppConsentStorageManager implements IConsentStorage {
@Override
public void recordDefaultConsent(AdServicesApiType apiType, boolean defaultConsent)
throws IOException {
- mDatastore.put(apiType.toPpApiDatastoreKey(), defaultConsent);
+ mDatastore.put(apiType.toDefaultConsentDatastoreKey(), defaultConsent);
}
/**
@@ -311,22 +357,9 @@ public class AppConsentStorageManager implements IConsentStorage {
}
}
- /** Set the AdIdEnabled bit to storage. */
- @Override
- public void setAdIdEnabled(boolean isAdIdEnabled) throws IOException {
- // test
- mDatastore.put(ConsentConstants.IS_AD_ID_ENABLED, isAdIdEnabled);
- }
-
- /** Set the AdultAccount bit to storage. */
- @Override
- public void setAdultAccount(boolean isAdultAccount) throws IOException {
- mDatastore.put(ConsentConstants.IS_ADULT_ACCOUNT, isAdultAccount);
- }
-
/**
* Sets the consent for this user ID for this API type in AppSearch. If we do not get
- * confirmation that the write was successful, then we throw an exception so that user does not
+ * confirmation that to write was successful, then we throw an exception so that user does not
* incorrectly think that the consent is updated.
*
* @throws IOException if the operation fails
@@ -361,7 +394,7 @@ public class AppConsentStorageManager implements IConsentStorage {
@Override
public boolean setConsentForAppIfNew(String packageName, boolean isConsentRevoked)
throws IllegalArgumentException {
- // test
+ // TODO(b/317595641) clean up setConsentForAppIfNew logic
try {
return mAppConsentDao.setConsentForAppIfNew(packageName, isConsentRevoked);
} catch (IOException exception) {
@@ -370,15 +403,6 @@ public class AppConsentStorageManager implements IConsentStorage {
}
}
- /** Set the current privacy sandbox feature. */
- @Override
- public void setCurrentPrivacySandboxFeature(PrivacySandboxFeatureType featureType)
- throws IOException {
- for (PrivacySandboxFeatureType currentFeatureType : PrivacySandboxFeatureType.values()) {
- mDatastore.put(currentFeatureType.name(), currentFeatureType == featureType);
- }
- }
-
/** Set the current enrollment channel to storage. */
@Override
public void setEnrollmentChannel(
@@ -386,18 +410,6 @@ public class AppConsentStorageManager implements IConsentStorage {
mUxStatesDao.setEnrollmentChannel(ux, channel);
}
- /** Set the EntryPointEnabled bit to storage . */
- @Override
- public void setEntryPointEnabled(boolean isEntryPointEnabled) throws IOException {
- mDatastore.put(ConsentConstants.IS_ENTRY_POINT_ENABLED, isEntryPointEnabled);
- }
-
- /** Set the U18Account bit to storage. */
- @Override
- public void setU18Account(boolean isU18Account) throws IOException {
- mDatastore.put(ConsentConstants.IS_U18_ACCOUNT, isU18Account);
- }
-
/** Set the U18NotificationDisplayed bit to storage. */
@Override
public void setU18NotificationDisplayed(boolean wasU18NotificationDisplayed)
@@ -406,12 +418,6 @@ public class AppConsentStorageManager implements IConsentStorage {
ConsentConstants.WAS_U18_NOTIFICATION_DISPLAYED, wasU18NotificationDisplayed);
}
- /** Set the current UX to storage. */
- @Override
- public void setUx(PrivacySandboxUxCollection ux) {
- mUxStatesDao.setUx(ux);
- }
-
/**
* Retrieves if GA UX notification has been displayed.
*
@@ -419,7 +425,8 @@ public class AppConsentStorageManager implements IConsentStorage {
*/
@Override
public boolean wasGaUxNotificationDisplayed() {
- return mDatastore.get(ConsentConstants.GA_UX_NOTIFICATION_DISPLAYED_ONCE);
+ return Objects.requireNonNullElse(
+ mDatastore.get(ConsentConstants.GA_UX_NOTIFICATION_DISPLAYED_ONCE), false);
}
/**
@@ -429,12 +436,16 @@ public class AppConsentStorageManager implements IConsentStorage {
*/
@Override
public boolean wasNotificationDisplayed() {
- return mDatastore.get(ConsentConstants.NOTIFICATION_DISPLAYED_ONCE);
+ return Objects.requireNonNullElse(
+ mDatastore.get(ConsentConstants.NOTIFICATION_DISPLAYED_ONCE), false);
}
/** Returns whether the wasU18NotificationDisplayed bit is true. */
@Override
public boolean wasU18NotificationDisplayed() {
- return mDatastore.get(ConsentConstants.WAS_U18_NOTIFICATION_DISPLAYED);
+ return Objects.requireNonNullElse(
+ mDatastore.get(ConsentConstants.WAS_U18_NOTIFICATION_DISPLAYED), false);
}
+
+
}
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/ConsentCompositeStorage.java b/adservices/service-core/java/com/android/adservices/service/consent/ConsentCompositeStorage.java
index 730b0788b..75229cb1c 100644
--- a/adservices/service-core/java/com/android/adservices/service/consent/ConsentCompositeStorage.java
+++ b/adservices/service-core/java/com/android/adservices/service/consent/ConsentCompositeStorage.java
@@ -22,13 +22,18 @@ import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICE
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PRIVACY_SANDBOX_SAVE_FAILURE;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX;
+import static com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection.U18_UX;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
import com.android.adservices.LogUtil;
import com.android.adservices.errorlogging.ErrorLogUtil;
import com.android.adservices.service.common.feature.PrivacySandboxFeatureType;
+import com.android.adservices.service.exception.ConsentStorageDeferException;
import com.android.adservices.service.ui.enrollment.collection.PrivacySandboxEnrollmentChannelCollection;
import com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection;
import com.android.internal.annotations.VisibleForTesting;
@@ -36,14 +41,22 @@ import com.android.internal.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
-import java.util.List;
/**
* CompositeStorage to handle read/write user's to multiple source of truth
*
* <p>Every source of truth should have its own dedicated storage class that implements the
* IConsentStorage interface, and pass in the instances to ConsentCompositeStorage.
+ *
+ * <p>By default, when caller set value to the storage, CompositeStorage will iterate through every
+ * instance in mConsentStorageList and call the corresponding method. For getter, CompositeStorage
+ * will only return the first one.
+ *
+ * <p>If the method not available in some implementation, the implementation class should throw
+ * {code ConsentStorageDeferException}, CompositeStorage will try to get the result for next
+ * instance.
*/
+@RequiresApi(Build.VERSION_CODES.S)
public class ConsentCompositeStorage implements IConsentStorage {
private static final int UNKNOWN = 0;
private final ImmutableList<IConsentStorage> mConsentStorageList;
@@ -54,7 +67,6 @@ public class ConsentCompositeStorage implements IConsentStorage {
* @param consentStorageList storage implementation instance list.
*/
public ConsentCompositeStorage(ImmutableList<IConsentStorage> consentStorageList) {
- assert (consentStorageList.size() > 0);
if (consentStorageList == null || consentStorageList.isEmpty()) {
throw new IllegalArgumentException("consent storage list can not be empty!");
}
@@ -67,9 +79,21 @@ public class ConsentCompositeStorage implements IConsentStorage {
* <p>This should be called when the Privacy Sandbox has been disabled.
*/
@Override
- public void clearAllAppConsentData() throws IOException {
+ public void clearAllAppConsentData() {
for (IConsentStorage storage : getConsentStorageList()) {
- storage.clearAllAppConsentData();
+ try {
+ storage.clearAllAppConsentData();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ throw new RuntimeException(e);
+ }
}
}
@@ -80,12 +104,19 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public void clearConsentForUninstalledApp(@NonNull String packageName) {
- try {
- for (IConsentStorage storage : getConsentStorageList()) {
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
storage.clearConsentForUninstalledApp(packageName);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
}
- } catch (IOException e) {
- throw new RuntimeException(e);
}
}
@@ -97,12 +128,18 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public void clearConsentForUninstalledApp(String packageName, int packageUid) {
-
for (IConsentStorage storage : getConsentStorageList()) {
try {
storage.clearConsentForUninstalledApp(packageName, packageUid);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
- LogUtil.e(getClass().getSimpleName() + " failed. " + e.getMessage());
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
}
}
}
@@ -117,8 +154,15 @@ public class ConsentCompositeStorage implements IConsentStorage {
for (IConsentStorage storage : getConsentStorageList()) {
try {
storage.clearKnownAppsWithConsent();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
- throw new RuntimeException(e);
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
}
}
}
@@ -126,15 +170,24 @@ public class ConsentCompositeStorage implements IConsentStorage {
/**
* @return an {@link ImmutableList} of all known apps in the database that have had user consent
* revoked
- * @throws IOException if the operation fails
*/
@Override
public ImmutableList<String> getAppsWithRevokedConsent() {
- try {
- return getPrimaryStorage().getAppsWithRevokedConsent();
- } catch (IOException e) {
- throw new RuntimeException(e);
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.getAppsWithRevokedConsent();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ }
}
+ return ImmutableList.of();
}
/**
@@ -147,15 +200,22 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public AdServicesApiConsent getConsent(AdServicesApiType apiType) {
- try {
- return getPrimaryStorage().getConsent(apiType);
- } catch (IOException e) {
- ErrorLogUtil.e(
- e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT,
- AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
- return AdServicesApiConsent.REVOKED;
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.getConsent(apiType);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException | RuntimeException e) {
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ return AdServicesApiConsent.REVOKED;
+ }
}
+ return AdServicesApiConsent.REVOKED;
}
/**
@@ -178,15 +238,42 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public PrivacySandboxFeatureType getCurrentPrivacySandboxFeature() {
- try {
- return getPrimaryStorage().getCurrentPrivacySandboxFeature();
- } catch (IOException e) {
- ErrorLogUtil.e(
- e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PRIVACY_SANDBOX_SAVE_FAILURE,
- AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
- LogUtil.e(getClass().getSimpleName() + " failed. " + e.getMessage());
- return PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED;
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.getCurrentPrivacySandboxFeature();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException | RuntimeException e) {
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PRIVACY_SANDBOX_SAVE_FAILURE,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ return PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED;
+ }
+ }
+ return PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED;
+ }
+
+ /** Sets the current privacy sandbox feature. */
+ @Override
+ public void setCurrentPrivacySandboxFeature(PrivacySandboxFeatureType featureType) {
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ storage.setCurrentPrivacySandboxFeature(featureType);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PRIVACY_SANDBOX_SAVE_FAILURE,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ throw new RuntimeException(
+ getClass().getSimpleName() + " failed. " + e.getMessage());
+ }
}
}
@@ -197,7 +284,19 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public boolean getDefaultAdIdState() {
- return getPrimaryStorage().getDefaultAdIdState();
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.getDefaultAdIdState();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreWhileRecordingDefaultConsent(e);
+ return false;
+ }
+ }
+ return false;
}
/**
@@ -207,22 +306,37 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public AdServicesApiConsent getDefaultConsent(AdServicesApiType apiType) {
- try {
- return getPrimaryStorage().getDefaultConsent(apiType);
- } catch (IOException e) {
- ErrorLogUtil.e(
- e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__DATASTORE_EXCEPTION_WHILE_RECORDING_DEFAULT_CONSENT,
- AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
- return AdServicesApiConsent.REVOKED;
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.getDefaultConsent(apiType);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreWhileRecordingDefaultConsent(e);
+ return AdServicesApiConsent.REVOKED;
+ }
}
+ return AdServicesApiConsent.REVOKED;
}
/** Returns current enrollment channel. */
@Override
public PrivacySandboxEnrollmentChannelCollection getEnrollmentChannel(
PrivacySandboxUxCollection ux) {
- return getPrimaryStorage().getEnrollmentChannel(ux);
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.getEnrollmentChannel(ux);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreWhileRecordingDefaultConsent(e);
+ }
+ }
+ return null;
}
/**
@@ -233,26 +347,20 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public ImmutableList<String> getKnownAppsWithConsent() {
- try {
- return getPrimaryStorage().getKnownAppsWithConsent();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Gets first storage instance, for read operations, should always return from the first source
- * of truth.
- *
- * @return first instance of IConsentStorage.
- */
- @VisibleForTesting
- public IConsentStorage getPrimaryStorage() {
- List<IConsentStorage> storageList = getConsentStorageList();
- if (storageList.isEmpty()) {
- throw new IllegalStateException("Consent Storage List is empty.");
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.getKnownAppsWithConsent();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreWhileRecordingDefaultConsent(e);
+ } catch (IllegalStateException e) {
+ LogUtil.i("IllegalStateException" + e);
+ }
}
- return storageList.get(0);
+ return ImmutableList.of();
}
/**
@@ -262,33 +370,121 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public int getUserManualInteractionWithConsent() {
- try {
- return getPrimaryStorage().getUserManualInteractionWithConsent();
- } catch (IOException e) {
- ErrorLogUtil.e(
- e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__DATASTORE_EXCEPTION_WHILE_RECORDING_MANUAL_CONSENT_INTERACTION,
- AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
- return UNKNOWN;
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.getUserManualInteractionWithConsent();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreManualInteractionException(e);
+ return UNKNOWN;
+ }
}
+ return 0;
}
/** Returns current UX. */
@Override
public PrivacySandboxUxCollection getUx() {
- return getPrimaryStorage().getUx();
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.getUx();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreManualInteractionException(e);
+ throw new RuntimeException(e);
+ }
+ }
+ return null;
+ }
+
+ /** Sets the current UX to storage. */
+ @Override
+ public void setUx(PrivacySandboxUxCollection ux) {
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ storage.setUx(ux);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
+ }
+ }
}
/** Returns whether the isAdIdEnabled bit is true. */
@Override
public boolean isAdIdEnabled() {
- return getPrimaryStorage().isAdIdEnabled();
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.isAdIdEnabled();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreManualInteractionException(e);
+ throw new RuntimeException(e);
+ }
+ }
+ return false;
+ }
+
+ /** Set the AdIdEnabled bit to storage. */
+ @Override
+ public void setAdIdEnabled(boolean isAdIdEnabled) {
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ storage.setAdIdEnabled(isAdIdEnabled);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
+ }
+ }
}
/** Returns whether the isAdultAccount bit is true. */
@Override
public boolean isAdultAccount() {
- return getPrimaryStorage().isAdultAccount();
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.isAdultAccount();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreManualInteractionException(e);
+ throw new RuntimeException(e);
+ }
+ }
+ return false;
+ }
+
+ /** Set the AdultAccount bit to storage. */
+ @Override
+ public void setAdultAccount(boolean isAdultAccount) {
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ storage.setAdultAccount(isAdultAccount);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
+ }
+ }
}
/**
@@ -300,23 +496,90 @@ public class ConsentCompositeStorage implements IConsentStorage {
*
* @throws IllegalArgumentException if the package name is invalid or not found as an installed
* application
- * @throws IOException if the operation fails
*/
@Override
public boolean isConsentRevokedForApp(String packageName) throws IllegalArgumentException {
- return getPrimaryStorage().isConsentRevokedForApp(packageName);
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.isConsentRevokedForApp(packageName);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreManualInteractionException(e);
+ throw new RuntimeException(e);
+ }
+ }
+ return false;
}
/** Returns whether the isEntryPointEnabled bit is true. */
@Override
public boolean isEntryPointEnabled() {
- return getPrimaryStorage().isEntryPointEnabled();
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.isEntryPointEnabled();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreManualInteractionException(e);
+ throw new RuntimeException(e);
+ }
+ }
+ return false;
+ }
+
+ /** Sets the EntryPointEnabled bit to storage . */
+ @Override
+ public void setEntryPointEnabled(boolean isEntryPointEnabled) {
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ storage.setEntryPointEnabled(isEntryPointEnabled);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
+ }
+ }
}
/** Returns whether the isU18Account bit is true. */
@Override
public boolean isU18Account() {
- return getPrimaryStorage().isU18Account();
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.isU18Account();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDatastoreManualInteractionException(e);
+ throw new RuntimeException(e);
+ }
+ }
+ return false;
+ }
+
+ /** Sets the U18Account bit to storage. */
+ @Override
+ public void setU18Account(boolean isU18Account) {
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ storage.setU18Account(isU18Account);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
+ }
+ }
}
/** Saves the default AdId state bit to data stores based on source of truth. */
@@ -325,7 +588,12 @@ public class ConsentCompositeStorage implements IConsentStorage {
for (IConsentStorage storage : getConsentStorageList()) {
try {
storage.recordDefaultAdIdState(defaultAdIdState);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
+ logDatastoreManualInteractionException(e);
throw new RuntimeException(e);
}
}
@@ -337,7 +605,12 @@ public class ConsentCompositeStorage implements IConsentStorage {
for (IConsentStorage storage : getConsentStorageList()) {
try {
storage.recordDefaultConsent(apiType, defaultConsent);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
+ logDatastoreManualInteractionException(e);
throw new RuntimeException(e);
}
}
@@ -352,7 +625,12 @@ public class ConsentCompositeStorage implements IConsentStorage {
for (IConsentStorage storage : getConsentStorageList()) {
try {
storage.recordGaUxNotificationDisplayed(wasGaUxDisplayed);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
+ logDatastoreManualInteractionException(e);
throw new RuntimeException(e);
}
}
@@ -366,10 +644,13 @@ public class ConsentCompositeStorage implements IConsentStorage {
public void recordNotificationDisplayed(boolean wasNotificationDisplayed) {
for (IConsentStorage storage : getConsentStorageList()) {
try {
-
storage.recordNotificationDisplayed(wasNotificationDisplayed);
-
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
+ logDatastoreManualInteractionException(e);
throw new RuntimeException(e);
}
}
@@ -381,53 +662,66 @@ public class ConsentCompositeStorage implements IConsentStorage {
for (IConsentStorage storage : getConsentStorageList()) {
try {
storage.recordUserManualInteractionWithConsent(interaction);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
- ErrorLogUtil.e(
- e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__DATASTORE_EXCEPTION_WHILE_RECORDING_MANUAL_CONSENT_INTERACTION,
- AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ logDatastoreManualInteractionException(e);
throw new RuntimeException(
getClass().getSimpleName() + " failed. " + e.getMessage());
}
}
}
- /** Set the AdIdEnabled bit to storage. */
+ /**
+ * Sets the consent for this user ID for this API type in AppSearch. If we do not get
+ * confirmation that the write was successful, then we throw an exception so that user does not
+ * incorrectly think that the consent is updated.
+ */
@Override
- public void setAdIdEnabled(boolean isAdIdEnabled) {
- for (IConsentStorage storage : getConsentStorageList()) {
- try {
- storage.setAdIdEnabled(isAdIdEnabled);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ public void setConsent(AdServicesApiType apiType, boolean isGiven) {
+ setConsentToApiType(apiType, isGiven);
+ if (apiType == AdServicesApiType.ALL_API) {
+ return;
}
+ setAggregatedConsent();
}
- /** Set the AdultAccount bit to storage. */
- @Override
- public void setAdultAccount(boolean isAdultAccount) {
+ private void setConsentToApiType(AdServicesApiType apiType, boolean isGiven) {
for (IConsentStorage storage : getConsentStorageList()) {
try {
- storage.setAdultAccount(isAdultAccount);
+ storage.setConsent(apiType, isGiven);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
- throw new RuntimeException(e);
+ logDataStoreWhileRecordingException(e);
}
}
}
- /**
- * Sets the consent for this user ID for this API type in AppSearch. If we do not get
- * confirmation that the write was successful, then we throw an exception so that user does not
- * incorrectly think that the consent is updated.
- *
- * @throws IOException if the operation fails
- */
- @Override
- public void setConsent(AdServicesApiType apiType, boolean isGiven) throws IOException {
- for (IConsentStorage storage : getConsentStorageList()) {
- storage.setConsent(apiType, isGiven);
+ // Set the aggregated consent so that after the rollback of the module
+ // and the flag which controls the consent flow everything works as expected.
+ // The problematic edge case which is covered:
+ // T1: AdServices is installed in pre-GA UX version and the consent is given
+ // T2: AdServices got upgraded to GA UX binary and GA UX feature flag is enabled
+ // T3: Consent for the Topics API got revoked
+ // T4: AdServices got rolledback and the feature flags which controls consent flow
+ // (SYSTEM_SERVER_ONLY and DUAL_WRITE) also got rolledback
+ // T5: Restored consent should be revoked
+ @VisibleForTesting
+ void setAggregatedConsent() {
+ if (getUx() == U18_UX) {
+ // The edge case does not apply to U18 UX.
+ return;
}
+ setConsentToApiType(
+ AdServicesApiType.ALL_API,
+ getConsent(AdServicesApiType.TOPICS).isGiven()
+ && getConsent(AdServicesApiType.MEASUREMENTS).isGiven()
+ && getConsent(AdServicesApiType.FLEDGE).isGiven());
}
/**
@@ -441,7 +735,12 @@ public class ConsentCompositeStorage implements IConsentStorage {
for (IConsentStorage storage : getConsentStorageList()) {
try {
storage.setConsentForApp(packageName, isConsentRevoked);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
throw new RuntimeException(e);
}
}
@@ -459,34 +758,25 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public boolean setConsentForAppIfNew(String packageName, boolean isConsentRevoked) {
- boolean ret = false;
- for (IConsentStorage storage : getConsentStorageList()) {
- try {
- // Same as original logic, only return the last one.
- ret = storage.setConsentForAppIfNew(packageName, isConsentRevoked);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- // LogUtil.e(ConsentConstants.ERROR_MESSAGE_INVALID_CONSENT_SOURCE_OF_TRUTH);
- return ret;
- }
-
- /** Sets the current privacy sandbox feature. */
- @Override
- public void setCurrentPrivacySandboxFeature(PrivacySandboxFeatureType featureType) {
- for (IConsentStorage storage : getConsentStorageList()) {
+ for (IConsentStorage storage : getConsentStorageList().reverse()) {
try {
- storage.setCurrentPrivacySandboxFeature(featureType);
+ // Same as original logic, call the PPAPI first
+ // TODO(b/317595641): clean up the logic
+ boolean ret = storage.setConsentForAppIfNew(packageName, isConsentRevoked);
+ if (ret) {
+ return true;
+ }
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
- ErrorLogUtil.e(
- e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PRIVACY_SANDBOX_SAVE_FAILURE,
- AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
- throw new RuntimeException(
- getClass().getSimpleName() + " failed. " + e.getMessage());
+ LogUtil.e(ConsentConstants.ERROR_MESSAGE_INVALID_CONSENT_SOURCE_OF_TRUTH);
+ logDataStoreWhileRecordingException(e);
+ return false;
}
}
+ return false;
}
/** Sets the current enrollment channel to storage. */
@@ -494,50 +784,35 @@ public class ConsentCompositeStorage implements IConsentStorage {
public void setEnrollmentChannel(
PrivacySandboxUxCollection ux, PrivacySandboxEnrollmentChannelCollection channel) {
for (IConsentStorage storage : getConsentStorageList()) {
- storage.setEnrollmentChannel(ux, channel);
- }
- }
-
- /** Sets the EntryPointEnabled bit to storage . */
- @Override
- public void setEntryPointEnabled(boolean isEntryPointEnabled) {
- for (IConsentStorage storage : getConsentStorageList()) {
try {
- storage.setEntryPointEnabled(isEntryPointEnabled);
+ storage.setEnrollmentChannel(ux, channel);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
- throw new RuntimeException(e);
+ logDataStoreWhileRecordingException(e);
}
}
}
- /** Sets the U18Account bit to storage. */
- @Override
- public void setU18Account(boolean isU18Account) throws IOException {
- for (IConsentStorage storage : getConsentStorageList()) {
- storage.setU18Account(isU18Account);
- }
- }
-
/** Sets the U18NotificationDisplayed bit to storage. */
@Override
public void setU18NotificationDisplayed(boolean wasU18NotificationDisplayed) {
for (IConsentStorage storage : getConsentStorageList()) {
try {
storage.setU18NotificationDisplayed(wasU18NotificationDisplayed);
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
} catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
throw new RuntimeException(e);
}
}
}
- /** Sets the current UX to storage. */
- @Override
- public void setUx(PrivacySandboxUxCollection ux) {
- for (IConsentStorage storage : getConsentStorageList()) {
- storage.setUx(ux);
- }
- }
-
/**
* Retrieves if GA UX notification has been displayed.
*
@@ -545,7 +820,19 @@ public class ConsentCompositeStorage implements IConsentStorage {
*/
@Override
public boolean wasGaUxNotificationDisplayed() {
- return getPrimaryStorage().wasGaUxNotificationDisplayed();
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.wasGaUxNotificationDisplayed();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
+ return false;
+ }
+ }
+ return false;
}
/**
@@ -556,20 +843,57 @@ public class ConsentCompositeStorage implements IConsentStorage {
@SuppressLint("NameOfTheRuleToSuppress")
@Override
public boolean wasNotificationDisplayed() {
- try {
- return getPrimaryStorage().wasNotificationDisplayed();
- } catch (IOException e) {
- ErrorLogUtil.e(
- e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__DATASTORE_EXCEPTION_WHILE_RECORDING_NOTIFICATION,
- AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
- return false;
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.wasNotificationDisplayed();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
+ return false;
+ }
}
+ return false;
}
/** Returns whether the wasU18NotificationDisplayed bit is true. */
@Override
public boolean wasU18NotificationDisplayed() {
- return getPrimaryStorage().wasU18NotificationDisplayed();
+ for (IConsentStorage storage : getConsentStorageList()) {
+ try {
+ return storage.wasU18NotificationDisplayed();
+ } catch (ConsentStorageDeferException e) {
+ LogUtil.i(
+ "Skip current storage manager %s. Defer to next one",
+ storage.getClass().getSimpleName());
+ } catch (IOException e) {
+ logDataStoreWhileRecordingException(e);
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private static void logDataStoreWhileRecordingException(IOException e) {
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__DATASTORE_EXCEPTION_WHILE_RECORDING_NOTIFICATION,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ }
+
+ private static void logDatastoreManualInteractionException(IOException e) {
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__DATASTORE_EXCEPTION_WHILE_RECORDING_MANUAL_CONSENT_INTERACTION,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ }
+
+ private static void logDatastoreWhileRecordingDefaultConsent(IOException e) {
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__DATASTORE_EXCEPTION_WHILE_RECORDING_DEFAULT_CONSENT,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/ConsentConstants.java b/adservices/service-core/java/com/android/adservices/service/consent/ConsentConstants.java
index 8407ed08e..582f2a141 100644
--- a/adservices/service-core/java/com/android/adservices/service/consent/ConsentConstants.java
+++ b/adservices/service-core/java/com/android/adservices/service/consent/ConsentConstants.java
@@ -17,7 +17,6 @@
package com.android.adservices.service.consent;
import com.android.adservices.service.common.compat.FileCompatUtils;
-import com.android.internal.annotations.VisibleForTesting;
/** ConsentManager related Constants. */
public class ConsentConstants {
@@ -37,8 +36,7 @@ public class ConsentConstants {
public static final String DEFAULT_AD_ID_STATE = "DEFAULT_AD_ID_STATE";
- @VisibleForTesting
- static final String MANUAL_INTERACTION_WITH_CONSENT_RECORDED =
+ public static final String MANUAL_INTERACTION_WITH_CONSENT_RECORDED =
"MANUAL_INTERACTION_WITH_CONSENT_RECORDED";
public static final String CONSENT_KEY = "CONSENT";
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java b/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java
index 900ffd58f..171970b3b 100644
--- a/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java
@@ -39,6 +39,7 @@ import android.app.job.JobScheduler;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
+import android.os.Trace;
import androidx.annotation.RequiresApi;
@@ -206,6 +207,7 @@ public class ConsentManager {
public static ConsentManager getInstance(@NonNull Context context) {
Objects.requireNonNull(context);
+ Trace.beginSection("ConsentManager#Initialization");
if (sConsentManager == null) {
synchronized (LOCK) {
if (sConsentManager == null) {
@@ -253,7 +255,8 @@ public class ConsentManager {
context,
datastore,
appSearchConsentManager,
- adServicesExtDataManager);
+ adServicesExtDataManager,
+ statsdAdServicesLogger);
}
}
@@ -288,6 +291,7 @@ public class ConsentManager {
}
}
}
+ Trace.endSection();
return sConsentManager;
}
@@ -2154,6 +2158,7 @@ public class ConsentManager {
for back compat. */
ThrowableSetter ppapiAndAdExtDataServiceSetter,
ErrorLogger errorLogger) {
+ Trace.beginSection("ConsentManager#WriteOperation");
mReadWriteLock.writeLock().lock();
try {
switch (mConsentSourceOfTruth) {
@@ -2185,11 +2190,12 @@ public class ConsentManager {
if (errorLogger != null) {
errorLogger.apply(e);
}
- throw new RuntimeException(getClass().getSimpleName() + " failed. " + e.getMessage());
+ throw new RuntimeException(
+ getClass().getSimpleName() + " failed. " + e.getMessage(), e);
} finally {
mReadWriteLock.writeLock().unlock();
+ Trace.endSection();
}
-
}
@FunctionalInterface
@@ -2218,6 +2224,7 @@ public class ConsentManager {
for back compat. */
ThrowableGetter<T> ppapiAndAdExtDataServiceGetter,
ErrorLogger errorLogger) {
+ Trace.beginSection("ConsentManager#ReadOperation");
mReadWriteLock.readLock().lock();
try {
switch (mConsentSourceOfTruth) {
@@ -2248,6 +2255,7 @@ public class ConsentManager {
LogUtil.e(getClass().getSimpleName() + " failed. " + e.getMessage());
} finally {
mReadWriteLock.readLock().unlock();
+ Trace.endSection();
}
return defaultReturn;
@@ -2260,8 +2268,20 @@ public class ConsentManager {
: AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__ROW;
}
- /* Returns an object of ConsentMigrationStats */
- private static ConsentMigrationStats getConsentManagerStatsForLogging(
+ /***
+ * Returns an object of ConsentMigrationStats for logging
+ *
+ * @param appConsents AppConsents consents per API (fledge, msmt, topics, default)
+ * @param migrationStatus Status of migration ( FAILURE, SUCCESS_WITH_SHARED_PREF_UPDATED,
+ * SUCCESS_WITH_SHARED_PREF_NOT_UPDATED)
+ * @param migrationType Type of migration ( PPAPI_TO_SYSTEM_SERVICE,
+ * APPSEARCH_TO_SYSTEM_SERVICE,
+ * ADEXT_SERVICE_TO_SYSTEM_SERVICE,
+ * ADEXT_SERVICE_TO_APPSEARCH)
+ * @param context Context of the application
+ * @return consentMigrationStats returns ConsentMigrationStats for logging
+ */
+ public static ConsentMigrationStats getConsentManagerStatsForLogging(
AppConsents appConsents,
ConsentMigrationStats.MigrationStatus migrationStatus,
ConsentMigrationStats.MigrationType migrationType,
@@ -2269,7 +2289,6 @@ public class ConsentManager {
ConsentMigrationStats consentMigrationStats =
ConsentMigrationStats.builder()
.setMigrationType(migrationType)
- .setMigrationStatus(migrationStatus)
// When appConsents is null we log it as a failure
.setMigrationStatus(
appConsents != null
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/ConsentManagerV2.java b/adservices/service-core/java/com/android/adservices/service/consent/ConsentManagerV2.java
new file mode 100644
index 000000000..b321c6754
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/service/consent/ConsentManagerV2.java
@@ -0,0 +1,1445 @@
+/*
+ * 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.service.consent;
+
+import static com.android.adservices.AdServicesCommon.ADEXTSERVICES_PACKAGE_NAME_SUFFIX;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__APP_SEARCH_DATA_MIGRATION_FAILURE;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_RESET_FAILURE;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_UPDATE_FAILURE;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_MEASUREMENT_WIPEOUT;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__EU;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__ROW;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.app.adservices.AdServicesManager;
+import android.app.job.JobScheduler;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.adservices.LogUtil;
+import com.android.adservices.concurrency.AdServicesExecutors;
+import com.android.adservices.data.adselection.AppInstallDao;
+import com.android.adservices.data.adselection.FrequencyCapDao;
+import com.android.adservices.data.adselection.SharedStorageDatabase;
+import com.android.adservices.data.common.BooleanFileDatastore;
+import com.android.adservices.data.consent.AppConsentDao;
+import com.android.adservices.data.customaudience.CustomAudienceDao;
+import com.android.adservices.data.customaudience.CustomAudienceDatabase;
+import com.android.adservices.data.enrollment.EnrollmentDao;
+import com.android.adservices.data.topics.Topic;
+import com.android.adservices.data.topics.TopicsTables;
+import com.android.adservices.errorlogging.ErrorLogUtil;
+import com.android.adservices.service.Flags;
+import com.android.adservices.service.FlagsFactory;
+import com.android.adservices.service.appsearch.AppSearchConsentStorageManager;
+import com.android.adservices.service.common.BackgroundJobsManager;
+import com.android.adservices.service.common.UserProfileIdManager;
+import com.android.adservices.service.common.compat.FileCompatUtils;
+import com.android.adservices.service.common.feature.PrivacySandboxFeatureType;
+import com.android.adservices.service.extdata.AdServicesExtDataStorageServiceManager;
+import com.android.adservices.service.measurement.MeasurementImpl;
+import com.android.adservices.service.measurement.WipeoutStatus;
+import com.android.adservices.service.stats.AdServicesLoggerImpl;
+import com.android.adservices.service.stats.ConsentMigrationStats;
+import com.android.adservices.service.stats.MeasurementWipeoutStats;
+import com.android.adservices.service.stats.StatsdAdServicesLogger;
+import com.android.adservices.service.stats.UiStatsLogger;
+import com.android.adservices.service.topics.TopicsWorker;
+import com.android.adservices.service.ui.data.UxStatesDao;
+import com.android.adservices.service.ui.enrollment.collection.PrivacySandboxEnrollmentChannelCollection;
+import com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.modules.utils.build.SdkLevel;
+
+import com.google.common.collect.ImmutableList;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * Manager all critical user data such as per API consent.
+ *
+ * <p>For Beta the consent is given for all {@link AdServicesApiType} or for none.
+ *
+ * <p>Currently there are three types of source of truth to store consent data,
+ *
+ * <ul>
+ * <li>SYSTEM_SERVER_ONLY: Write and read consent from system server only.
+ * <li>PPAPI_ONLY: Write and read consent from PPAPI only.
+ * <li>PPAPI_AND_SYSTEM_SERVER: Write consent to both PPAPI and system server. Read consent from
+ * system server only.
+ * <li>APPSEARCH_ONLY: Write and read consent from appSearch only for back compat.
+ * <li>PPAPI_AND_ADEXT_SERVICE: Write and read consent from PPAPI and AdExt service..
+ * </ul>
+ */
+// TODO(b/279042385): move UI logs to UI.
+@RequiresApi(Build.VERSION_CODES.S)
+public class ConsentManagerV2 {
+ private static volatile ConsentManagerV2 sConsentManager;
+
+ @IntDef(value = {NO_MANUAL_INTERACTIONS_RECORDED, UNKNOWN, MANUAL_INTERACTIONS_RECORDED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UserManualInteraction {}
+
+ public static final int NO_MANUAL_INTERACTIONS_RECORDED = -1;
+ public static final int UNKNOWN = 0;
+ public static final int MANUAL_INTERACTIONS_RECORDED = 1;
+
+ private final Flags mFlags;
+ private final TopicsWorker mTopicsWorker;
+ private final BooleanFileDatastore mDatastore;
+ private final EnrollmentDao mEnrollmentDao;
+ private final MeasurementImpl mMeasurementImpl;
+ private final CustomAudienceDao mCustomAudienceDao;
+ private final AppInstallDao mAppInstallDao;
+ private final FrequencyCapDao mFrequencyCapDao;
+ private final AdServicesStorageManager mAdServicesStorageManager;
+ private final AppSearchConsentStorageManager mAppSearchConsentStorageManager;
+ private final UserProfileIdManager mUserProfileIdManager;
+
+ private final AppConsentForRStorageManager mAppConsentForRStorageManager;
+
+ private static final Object LOCK = new Object();
+
+ private ConsentCompositeStorage mConsentCompositeStorage;
+
+ private AppConsentStorageManager mAppConsentStorageManager;
+
+ ConsentManagerV2(
+ @NonNull TopicsWorker topicsWorker,
+ @NonNull AppConsentDao appConsentDao,
+ @NonNull EnrollmentDao enrollmentDao,
+ @NonNull MeasurementImpl measurementImpl,
+ @NonNull CustomAudienceDao customAudienceDao,
+ @NonNull AppConsentStorageManager appConsentStorageManager,
+ @NonNull AppInstallDao appInstallDao,
+ @NonNull FrequencyCapDao frequencyCapDao,
+ @NonNull AdServicesStorageManager adServicesStorageManager,
+ @NonNull BooleanFileDatastore booleanFileDatastore,
+ @NonNull AppSearchConsentStorageManager appSearchConsentStorageManager,
+ @NonNull UserProfileIdManager userProfileIdManager,
+ @NonNull AppConsentForRStorageManager appConsentForRStorageManager,
+ @NonNull Flags flags,
+ @Flags.ConsentSourceOfTruth int consentSourceOfTruth,
+ boolean enableAppsearchConsentData,
+ boolean enableAdExtServiceConsentData) {
+ Objects.requireNonNull(topicsWorker);
+ Objects.requireNonNull(appConsentDao);
+ Objects.requireNonNull(measurementImpl);
+ Objects.requireNonNull(customAudienceDao);
+ Objects.requireNonNull(appInstallDao);
+ Objects.requireNonNull(frequencyCapDao);
+ Objects.requireNonNull(booleanFileDatastore);
+ Objects.requireNonNull(userProfileIdManager);
+
+ if (consentSourceOfTruth != Flags.PPAPI_ONLY
+ && consentSourceOfTruth != Flags.APPSEARCH_ONLY) {
+ Objects.requireNonNull(adServicesStorageManager);
+ }
+
+ if (enableAppsearchConsentData) {
+ Objects.requireNonNull(appSearchConsentStorageManager);
+ }
+
+ if (enableAdExtServiceConsentData) {
+ Objects.requireNonNull(appConsentForRStorageManager);
+ }
+
+ mAdServicesStorageManager = adServicesStorageManager;
+ mTopicsWorker = topicsWorker;
+ mDatastore = booleanFileDatastore;
+ mEnrollmentDao = enrollmentDao;
+ mMeasurementImpl = measurementImpl;
+ mCustomAudienceDao = customAudienceDao;
+ mAppInstallDao = appInstallDao;
+ mFrequencyCapDao = frequencyCapDao;
+
+ mAppSearchConsentStorageManager = appSearchConsentStorageManager;
+ mUserProfileIdManager = userProfileIdManager;
+
+ mFlags = flags;
+ mAppConsentStorageManager = appConsentStorageManager;
+ mAppConsentForRStorageManager = appConsentForRStorageManager;
+
+ mConsentCompositeStorage =
+ new ConsentCompositeStorage(getStorageListBySourceOfTruth(consentSourceOfTruth));
+ }
+
+ private ImmutableList<IConsentStorage> getStorageListBySourceOfTruth(
+ @Flags.ConsentSourceOfTruth int consentSourceOfTruth) {
+ switch (consentSourceOfTruth) {
+ case Flags.PPAPI_ONLY:
+ return ImmutableList.of(mAppConsentStorageManager);
+ case Flags.SYSTEM_SERVER_ONLY:
+ return ImmutableList.of(mAdServicesStorageManager);
+ case Flags.PPAPI_AND_SYSTEM_SERVER:
+ // System storage has higher priority
+ return ImmutableList.of(mAdServicesStorageManager, mAppConsentStorageManager);
+ case Flags.APPSEARCH_ONLY:
+ return ImmutableList.of(mAppSearchConsentStorageManager);
+ case Flags.PPAPI_AND_ADEXT_SERVICE:
+ return ImmutableList.of(mAppConsentForRStorageManager);
+ default:
+ LogUtil.e(ConsentConstants.ERROR_MESSAGE_INVALID_CONSENT_SOURCE_OF_TRUTH);
+ return ImmutableList.of();
+ }
+ }
+
+ /**
+ * Gets an instance of {@link ConsentManagerV2} to be used.
+ *
+ * <p>If no instance has been initialized yet, a new one will be created. Otherwise, the
+ * existing instance will be returned.
+ */
+ @NonNull
+ public static ConsentManagerV2 getInstance(@NonNull Context context) {
+ Objects.requireNonNull(context);
+
+ if (sConsentManager == null) {
+ synchronized (LOCK) {
+ if (sConsentManager == null) {
+ // Execute one-time consent migration if needed.
+ int consentSourceOfTruth = FlagsFactory.getFlags().getConsentSourceOfTruth();
+ BooleanFileDatastore datastore = createAndInitializeDataStore(context);
+ AdServicesStorageManager adServicesManager =
+ AdServicesStorageManager.getInstance(
+ AdServicesManager.getInstance(context));
+ AppConsentDao appConsentDao = AppConsentDao.getInstance(context);
+
+ // It is possible that the old value of the flag lingers after OTA until the
+ // first PH sync. In that case, we should not use the stale value, but use the
+ // default instead. The next PH sync will restore the T+ value.
+ if (SdkLevel.isAtLeastT() && consentSourceOfTruth == Flags.APPSEARCH_ONLY) {
+ consentSourceOfTruth = Flags.DEFAULT_CONSENT_SOURCE_OF_TRUTH;
+ }
+ AppSearchConsentStorageManager appSearchConsentStorageManager = null;
+ StatsdAdServicesLogger statsdAdServicesLogger =
+ StatsdAdServicesLogger.getInstance();
+ // Flag enable_appsearch_consent_data is true on S- and T+ only when we want to
+ // use AppSearch to write to or read from.
+ boolean enableAppsearchConsentData =
+ FlagsFactory.getFlags().getEnableAppsearchConsentData();
+ if (enableAppsearchConsentData) {
+ appSearchConsentStorageManager =
+ AppSearchConsentStorageManager.getInstance();
+ handleConsentMigrationFromAppSearchIfNeeded(
+ context,
+ datastore,
+ appConsentDao,
+ appSearchConsentStorageManager,
+ adServicesManager,
+ statsdAdServicesLogger);
+ }
+ UxStatesDao uxStatesDao = UxStatesDao.getInstance(context);
+ AppConsentForRStorageManager mAppConsentForRStorageManager = null;
+ // Flag enable_adext_service_consent_data is true on R and S+ only when
+ // we want to use AdServicesExtDataStorageService to write to or read from.
+ boolean enableAdExtServiceConsentData =
+ FlagsFactory.getFlags().getEnableAdExtServiceConsentData();
+ if (enableAdExtServiceConsentData) {
+ AdServicesExtDataStorageServiceManager adServicesExtDataManager =
+ AdServicesExtDataStorageServiceManager.getInstance(context);
+ if (FlagsFactory.getFlags().getEnableAdExtServiceToAppSearchMigration()) {
+ ConsentMigrationUtils.handleConsentMigrationToAppSearchIfNeededV2(
+ context,
+ datastore,
+ appSearchConsentStorageManager,
+ adServicesExtDataManager);
+ }
+ mAppConsentForRStorageManager =
+ new AppConsentForRStorageManager(
+ datastore,
+ appConsentDao,
+ uxStatesDao,
+ adServicesExtDataManager);
+ }
+
+ // Attempt to migrate consent data from PPAPI to System server if needed.
+ handleConsentMigrationIfNeeded(
+ context,
+ datastore,
+ adServicesManager,
+ statsdAdServicesLogger,
+ consentSourceOfTruth);
+
+ AppConsentStorageManager appConsentStorageManager =
+ new AppConsentStorageManager(datastore, appConsentDao, uxStatesDao);
+ sConsentManager =
+ new ConsentManagerV2(
+ TopicsWorker.getInstance(context),
+ appConsentDao,
+ EnrollmentDao.getInstance(context),
+ MeasurementImpl.getInstance(context),
+ CustomAudienceDatabase.getInstance(context).customAudienceDao(),
+ appConsentStorageManager,
+ SharedStorageDatabase.getInstance(context).appInstallDao(),
+ SharedStorageDatabase.getInstance(context).frequencyCapDao(),
+ adServicesManager,
+ datastore,
+ appSearchConsentStorageManager,
+ UserProfileIdManager.getInstance(context),
+ // TODO(b/260601944): Remove Flag Instance.
+ mAppConsentForRStorageManager,
+ FlagsFactory.getFlags(),
+ consentSourceOfTruth,
+ enableAppsearchConsentData,
+ enableAdExtServiceConsentData);
+ }
+ }
+ }
+ return sConsentManager;
+ }
+
+ /**
+ * Enables all PP API services. It gives consent to Topics, Fledge and Measurements services.
+ *
+ * <p>To write consent to PPAPI if consent source of truth is PPAPI_ONLY or dual sources. To
+ * write to system server consent if source of truth is system server or dual sources.
+ */
+ public void enable(@NonNull Context context) {
+ Objects.requireNonNull(context);
+
+ // Check current value, if it is already enabled, skip this enable process. so that the Api
+ // won't be reset. Only add this logic to "enable" not "disable", since if it already
+ // disabled, there is no harm to reset the api again.
+ if (mFlags.getConsentManagerLazyEnableMode() && getConsentFromSourceOfTruth()) {
+ LogUtil.d("CONSENT_KEY already enable. Skipping enable process.");
+ return;
+ }
+ UiStatsLogger.logOptInSelected();
+
+ BackgroundJobsManager.scheduleAllBackgroundJobs(context);
+ try {
+ // reset all state data which should be removed
+ resetTopicsAndBlockedTopics();
+ clearAllAppConsentData();
+ resetMeasurement();
+ resetUserProfileId();
+ mUserProfileIdManager.getOrCreateId();
+ } catch (IOException e) {
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_WHILE_SET_CONTENT, e);
+ }
+ setConsentToSourceOfTruth(/* isGiven */ true);
+ }
+
+ /**
+ * Disables all PP API services. It revokes consent to Topics, Fledge and Measurements services.
+ *
+ * <p>To write consent to PPAPI if consent source of truth is PPAPI_ONLY or dual sources. To
+ * write to system server consent if source of truth is system server or dual sources.
+ */
+ public void disable(@NonNull Context context) {
+ Objects.requireNonNull(context);
+ UiStatsLogger.logOptOutSelected();
+ // Disable all the APIs
+ try {
+ // reset all data
+ resetTopicsAndBlockedTopics();
+ clearAllAppConsentData();
+ resetMeasurement();
+ resetEnrollment();
+ resetUserProfileId();
+
+ BackgroundJobsManager.unscheduleAllBackgroundJobs(
+ context.getSystemService(JobScheduler.class));
+ } catch (IOException e) {
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_WHILE_SET_CONTENT, e);
+ }
+ setConsentToSourceOfTruth(/* isGiven */ false);
+ }
+
+ /**
+ * Enables the {@code apiType} PP API service. It gives consent to an API which is provided in
+ * the parameter.
+ *
+ * <p>To write consent to PPAPI if consent source of truth is PPAPI_ONLY or dual sources. To
+ * write to system server consent if source of truth is system server or dual sources.
+ *
+ * @param context Context of the application.
+ * @param apiType Type of the API (Topics, Fledge, Measurement) which should be enabled.
+ */
+ public void enable(@NonNull Context context, AdServicesApiType apiType) {
+ Objects.requireNonNull(context);
+ // Check current value, if it is already enabled, skip this enable process. so that the Api
+ // won't be reset.
+ if (mFlags.getConsentManagerLazyEnableMode()
+ && getPerApiConsentFromSourceOfTruth(apiType)) {
+ LogUtil.d(
+ "ApiType: is %s already enable. Skipping enable process.",
+ apiType.toPpApiDatastoreKey());
+ return;
+ }
+
+ UiStatsLogger.logOptInSelected(apiType);
+
+ BackgroundJobsManager.scheduleJobsPerApi(context, apiType);
+
+ try {
+ // reset all state data which should be removed
+ resetByApi(apiType);
+
+ if (AdServicesApiType.FLEDGE == apiType) {
+ mUserProfileIdManager.getOrCreateId();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_WHILE_SET_CONTENT, e);
+ }
+
+ setPerApiConsentToSourceOfTruth(/* isGiven */ true, apiType);
+ }
+
+ /**
+ * Disables {@code apiType} PP API service. It revokes consent to an API which is provided in
+ * the parameter.
+ *
+ * <p>To write consent to PPAPI if consent source of truth is PPAPI_ONLY or dual sources. To
+ * write to system server consent if source of truth is system server or dual sources.
+ */
+ public void disable(@NonNull Context context, AdServicesApiType apiType) {
+ Objects.requireNonNull(context);
+
+ UiStatsLogger.logOptOutSelected(apiType);
+
+ try {
+ resetByApi(apiType);
+ BackgroundJobsManager.unscheduleJobsPerApi(
+ context.getSystemService(JobScheduler.class), apiType);
+ } catch (IOException e) {
+ throw new RuntimeException(ConsentConstants.ERROR_MESSAGE_WHILE_SET_CONTENT, e);
+ }
+
+ setPerApiConsentToSourceOfTruth(/* isGiven */ false, apiType);
+
+ if (areAllApisDisabled()) {
+ BackgroundJobsManager.unscheduleAllBackgroundJobs(
+ context.getSystemService(JobScheduler.class));
+ }
+ }
+
+ private boolean areAllApisDisabled() {
+ if (getConsent(AdServicesApiType.TOPICS).isGiven()
+ || getConsent(AdServicesApiType.MEASUREMENTS).isGiven()
+ || getConsent(AdServicesApiType.FLEDGE).isGiven()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Retrieves the consent for all PP API services.
+ *
+ * <p>To read from PPAPI consent if source of truth is PPAPI. To read from system server consent
+ * if source of truth is system server or dual sources.
+ *
+ * @return AdServicesApiConsent the consent
+ */
+ public AdServicesApiConsent getConsent() {
+ if (mFlags.getConsentManagerDebugMode()) {
+ return AdServicesApiConsent.GIVEN;
+ }
+ return mConsentCompositeStorage.getConsent(AdServicesApiType.ALL_API);
+ }
+
+ /**
+ * Retrieves the consent per API.
+ *
+ * @param apiType apiType for which the consent should be provided
+ * @return {@link AdServicesApiConsent} providing information whether the consent was given or
+ * revoked.
+ */
+ public AdServicesApiConsent getConsent(AdServicesApiType apiType) {
+ if (mFlags.getConsentManagerDebugMode()) {
+ return AdServicesApiConsent.GIVEN;
+ }
+ return mConsentCompositeStorage.getConsent(apiType);
+ }
+
+ /**
+ * Returns whether the user is adult user who OTA from R.
+ *
+ * @return true if user is adult user who OTA from R, otherwise false.
+ */
+ public boolean isOtaAdultUserFromRvc() {
+ if (mFlags.getConsentManagerOTADebugMode()) {
+ return true;
+ }
+ // TODO(313672368) clean up getRvcPostOtaNotifAgeCheck flag after u18 is qualified on R/S
+ return mAppConsentForRStorageManager != null
+ && mAppConsentForRStorageManager.wasU18NotificationDisplayed()
+ && (mFlags.getRvcPostOtaNotifAgeCheck()
+ ? !mAppConsentForRStorageManager.isU18Account()
+ && mAppConsentForRStorageManager.isAdultAccount()
+ : true);
+ }
+
+ /**
+ * Proxy call to {@link TopicsWorker} to get {@link ImmutableList} of {@link Topic}s which could
+ * be returned to the {@link TopicsWorker} clients.
+ *
+ * @return {@link ImmutableList} of {@link Topic}s.
+ */
+ @NonNull
+ public ImmutableList<Topic> getKnownTopicsWithConsent() {
+ return mTopicsWorker.getKnownTopicsWithConsent();
+ }
+
+ /**
+ * Proxy call to {@link TopicsWorker} to get {@link ImmutableList} of {@link Topic}s which were
+ * blocked by the user.
+ *
+ * @return {@link ImmutableList} of blocked {@link Topic}s.
+ */
+ @NonNull
+ public ImmutableList<Topic> getTopicsWithRevokedConsent() {
+ return mTopicsWorker.getTopicsWithRevokedConsent();
+ }
+
+ /**
+ * Proxy call to {@link TopicsWorker} to revoke consent for provided {@link Topic} (block
+ * topic).
+ *
+ * @param topic {@link Topic} to block.
+ */
+ @NonNull
+ public void revokeConsentForTopic(@NonNull Topic topic) {
+ mTopicsWorker.revokeConsentForTopic(topic);
+ }
+
+ /**
+ * Proxy call to {@link TopicsWorker} to restore consent for provided {@link Topic} (unblock the
+ * topic).
+ *
+ * @param topic {@link Topic} to restore consent for.
+ */
+ @NonNull
+ public void restoreConsentForTopic(@NonNull Topic topic) {
+ mTopicsWorker.restoreConsentForTopic(topic);
+ }
+
+ /** Wipes out all the data gathered by Topics API but blocked topics. */
+ public void resetTopics() {
+ ArrayList<String> tablesToBlock = new ArrayList<>();
+ tablesToBlock.add(TopicsTables.BlockedTopicsContract.TABLE);
+ mTopicsWorker.clearAllTopicsData(tablesToBlock);
+ }
+
+ /** Wipes out all the data gathered by Topics API. */
+ public void resetTopicsAndBlockedTopics() {
+ mTopicsWorker.clearAllTopicsData(new ArrayList<>());
+ }
+
+ /**
+ * @return an {@link ImmutableList} of all known apps in the database that have not had user
+ * consent revoked
+ */
+ public ImmutableList<App> getKnownAppsWithConsent() {
+ return ImmutableList.copyOf(
+ mConsentCompositeStorage.getKnownAppsWithConsent().stream()
+ .map(App::create)
+ .collect(Collectors.toList()));
+ }
+
+ /**
+ * @return an {@link ImmutableList} of all known apps in the database that have had user consent
+ * revoked
+ */
+ public ImmutableList<App> getAppsWithRevokedConsent() {
+ return ImmutableList.copyOf(
+ mConsentCompositeStorage.getAppsWithRevokedConsent().stream()
+ .map(App::create)
+ .collect(Collectors.toList()));
+ }
+
+ /**
+ * Proxy call to {@link AppConsentDao} to revoke consent for provided {@link App}.
+ *
+ * <p>Also clears all app data related to the provided {@link App}.
+ *
+ * @param app {@link App} to block.
+ * @throws IOException if the operation fails
+ */
+ public void revokeConsentForApp(@NonNull App app) throws IOException {
+ mConsentCompositeStorage.setConsentForApp(app.getPackageName(), true);
+
+ asyncExecute(
+ () -> mCustomAudienceDao.deleteCustomAudienceDataByOwner(app.getPackageName()));
+ if (mFlags.getFledgeAdSelectionFilteringEnabled()) {
+ asyncExecute(() -> mAppInstallDao.deleteByPackageName(app.getPackageName()));
+ asyncExecute(
+ () -> mFrequencyCapDao.deleteHistogramDataBySourceApp(app.getPackageName()));
+ }
+ }
+
+ /**
+ * Proxy call to {@link AppConsentDao} to restore consent for provided {@link App}.
+ *
+ * @param app {@link App} to restore consent for.
+ * @throws IOException if the operation fails
+ */
+ public void restoreConsentForApp(@NonNull App app) throws IOException {
+ mConsentCompositeStorage.setConsentForApp(app.getPackageName(), false);
+ }
+
+ /**
+ * Deletes all app consent data and all app data gathered or generated by the Privacy Sandbox.
+ *
+ * <p>This should be called when the Privacy Sandbox has been disabled.
+ *
+ * @throws IOException if the operation fails
+ */
+ public void clearAllAppConsentData() throws IOException {
+ mConsentCompositeStorage.clearAllAppConsentData();
+
+ asyncExecute(mCustomAudienceDao::deleteAllCustomAudienceData);
+ if (mFlags.getFledgeAdSelectionFilteringEnabled()) {
+ asyncExecute(mAppInstallDao::deleteAllAppInstallData);
+ asyncExecute(mFrequencyCapDao::deleteAllHistogramData);
+ }
+ }
+
+ /**
+ * Deletes the list of known allowed apps as well as all app data from the Privacy Sandbox.
+ *
+ * <p>The list of blocked apps is not reset.
+ *
+ * @throws IOException if the operation fails
+ */
+ public void clearKnownAppsWithConsent() throws IOException {
+ mConsentCompositeStorage.clearKnownAppsWithConsent();
+ asyncExecute(mCustomAudienceDao::deleteAllCustomAudienceData);
+ if (mFlags.getFledgeAdSelectionFilteringEnabled()) {
+ asyncExecute(mAppInstallDao::deleteAllAppInstallData);
+ asyncExecute(mFrequencyCapDao::deleteAllHistogramData);
+ }
+ }
+
+ /**
+ * Checks whether a single given installed application (identified by its package name) has had
+ * user consent to use the FLEDGE APIs revoked.
+ *
+ * <p>This method also checks whether a user has opted out of the FLEDGE Privacy Sandbox
+ * initiative.
+ *
+ * @param packageName String package name that uniquely identifies an installed application to
+ * check
+ * @return {@code true} if either the FLEDGE Privacy Sandbox initiative has been opted out or if
+ * the user has revoked consent for the given application to use the FLEDGE APIs
+ * @throws IllegalArgumentException if the package name is invalid or not found as an installed
+ * application
+ */
+ public boolean isFledgeConsentRevokedForApp(@NonNull String packageName)
+ throws IllegalArgumentException {
+ AdServicesApiConsent consent = getConsent(AdServicesApiType.FLEDGE);
+
+ if (!consent.isGiven()) {
+ return true;
+ }
+
+ return mConsentCompositeStorage.isConsentRevokedForApp(packageName);
+ }
+
+ /**
+ * Persists the use of a FLEDGE API by a single given installed application (identified by its
+ * package name) if the app has not already had its consent revoked.
+ *
+ * <p>This method also checks whether a user has opted out of the FLEDGE Privacy Sandbox
+ * initiative.
+ *
+ * <p>This is only meant to be called by the FLEDGE APIs.
+ *
+ * @param packageName String package name that uniquely identifies an installed application that
+ * has used a FLEDGE API
+ * @return {@code true} if user consent has been revoked for the application or API, {@code
+ * false} otherwise
+ * @throws IllegalArgumentException if the package name is invalid or not found as an installed
+ * application
+ */
+ public boolean isFledgeConsentRevokedForAppAfterSettingFledgeUse(@NonNull String packageName)
+ throws IllegalArgumentException {
+ AdServicesApiConsent consent = getConsent(AdServicesApiType.FLEDGE);
+
+ if (!consent.isGiven()) {
+ return true;
+ }
+
+ return mConsentCompositeStorage.setConsentForAppIfNew(packageName, false);
+ }
+
+ /**
+ * Clear consent data after an app was uninstalled.
+ *
+ * @param packageName the package name that had been uninstalled.
+ */
+ public void clearConsentForUninstalledApp(String packageName, int packageUid) {
+ mConsentCompositeStorage.clearConsentForUninstalledApp(packageName, packageUid);
+ }
+
+ /**
+ * Clear consent data after an app was uninstalled, but the package Uid is unavailable. This
+ * could happen because the INTERACT_ACROSS_USERS_FULL permission is not available on Android
+ * versions prior to T.
+ *
+ * <p><strong>This method should only be used for R/S back-compat scenarios.</strong>
+ *
+ * @param packageName the package name that had been uninstalled.
+ */
+ public void clearConsentForUninstalledApp(@NonNull String packageName) {
+ mConsentCompositeStorage.clearConsentForUninstalledApp(packageName);
+ }
+
+ /** Wipes out all the data gathered by Measurement API. */
+ public void resetMeasurement() {
+ mMeasurementImpl.deleteAllMeasurementData(List.of());
+ // Log wipeout event triggered by consent flip to delete data of package
+ WipeoutStatus wipeoutStatus = new WipeoutStatus();
+ wipeoutStatus.setWipeoutType(WipeoutStatus.WipeoutType.CONSENT_FLIP);
+ logWipeoutStats(wipeoutStatus);
+ }
+
+ /** Wipes out all the Enrollment data */
+ @VisibleForTesting
+ void resetEnrollment() {
+ mEnrollmentDao.deleteAll();
+ }
+
+ /**
+ * Saves information to the storage that notification was displayed for the first time to the
+ * user.
+ */
+ public void recordNotificationDisplayed(boolean wasNotificationDisplayed) {
+ mConsentCompositeStorage.recordNotificationDisplayed(wasNotificationDisplayed);
+ }
+
+ /**
+ * Retrieves if notification has been displayed.
+ *
+ * @return true if Consent Notification was displayed, otherwise false.
+ */
+ public Boolean wasNotificationDisplayed() {
+ return mConsentCompositeStorage.wasNotificationDisplayed();
+ }
+
+ /**
+ * Saves information to the storage that GA UX notification was displayed for the first time to
+ * the user.
+ */
+ public void recordGaUxNotificationDisplayed(boolean wasGaUxDisplayed) {
+ mConsentCompositeStorage.recordGaUxNotificationDisplayed(wasGaUxDisplayed);
+ }
+
+ /**
+ * Retrieves if GA UX notification has been displayed.
+ *
+ * @return true if GA UX Consent Notification was displayed, otherwise false.
+ */
+ public Boolean wasGaUxNotificationDisplayed() {
+ return mConsentCompositeStorage.wasGaUxNotificationDisplayed();
+ }
+
+ /**
+ * Retrieves the PP API default consent.
+ *
+ * @return true if the topics default consent is true, false otherwise.
+ */
+ public Boolean getDefaultConsent() {
+ return mConsentCompositeStorage.getDefaultConsent(AdServicesApiType.ALL_API).isGiven();
+ }
+
+ /**
+ * Retrieves the topics default consent.
+ *
+ * @return true if the topics default consent is true, false otherwise.
+ */
+ public Boolean getTopicsDefaultConsent() {
+ return mConsentCompositeStorage.getDefaultConsent(AdServicesApiType.TOPICS).isGiven();
+ }
+
+ /**
+ * Retrieves the FLEDGE default consent.
+ *
+ * @return true if the FLEDGE default consent is true, false otherwise.
+ */
+ public Boolean getFledgeDefaultConsent() {
+ return mConsentCompositeStorage.getDefaultConsent(AdServicesApiType.FLEDGE).isGiven();
+ }
+
+ /**
+ * Retrieves the measurement default consent.
+ *
+ * @return true if the measurement default consent is true, false otherwise.
+ */
+ public Boolean getMeasurementDefaultConsent() {
+ return mConsentCompositeStorage.getDefaultConsent(AdServicesApiType.MEASUREMENTS).isGiven();
+ }
+
+ /**
+ * Retrieves the default AdId state.
+ *
+ * @return true if the AdId is enabled by default, false otherwise.
+ */
+ public Boolean getDefaultAdIdState() {
+ return mConsentCompositeStorage.getDefaultAdIdState();
+ }
+
+ /** Saves the default consent bit to data stores based on source of truth. */
+ public void recordDefaultConsent(boolean defaultConsent) {
+ mConsentCompositeStorage.recordDefaultConsent(AdServicesApiType.ALL_API, defaultConsent);
+ }
+
+ /** Saves the topics default consent bit to data stores based on source of truth. */
+ public void recordTopicsDefaultConsent(boolean defaultConsent) {
+ mConsentCompositeStorage.recordDefaultConsent(AdServicesApiType.TOPICS, defaultConsent);
+ }
+
+ /** Saves the FLEDGE default consent bit to data stores based on source of truth. */
+ public void recordFledgeDefaultConsent(boolean defaultConsent) {
+ mConsentCompositeStorage.recordDefaultConsent(AdServicesApiType.FLEDGE, defaultConsent);
+ }
+
+ /** Saves the measurement default consent bit to data stores based on source of truth. */
+ public void recordMeasurementDefaultConsent(boolean defaultConsent) {
+ mConsentCompositeStorage.recordDefaultConsent(
+ AdServicesApiType.MEASUREMENTS, defaultConsent);
+ }
+
+ /** Saves the default AdId state bit to data stores based on source of truth. */
+ public void recordDefaultAdIdState(boolean defaultAdIdState) {
+ mConsentCompositeStorage.recordDefaultAdIdState(defaultAdIdState);
+ }
+
+ /** Set the current privacy sandbox feature. */
+ public void setCurrentPrivacySandboxFeature(PrivacySandboxFeatureType currentFeatureType) {
+ mConsentCompositeStorage.setCurrentPrivacySandboxFeature(currentFeatureType);
+ }
+
+ /** Saves information to the storage that user interacted with consent manually. */
+ public void recordUserManualInteractionWithConsent(@UserManualInteraction int interaction) {
+ mConsentCompositeStorage.recordUserManualInteractionWithConsent(interaction);
+ }
+
+ /**
+ * Get the current privacy sandbox feature.
+ *
+ * <p>To write to PPAPI if consent source of truth is PPAPI_ONLY or dual sources. To write to
+ * system server if consent source of truth is SYSTEM_SERVER_ONLY or dual sources.
+ */
+ public PrivacySandboxFeatureType getCurrentPrivacySandboxFeature() {
+ return mConsentCompositeStorage.getCurrentPrivacySandboxFeature();
+ }
+
+ /**
+ * Returns information whether user interacted with consent manually.
+ *
+ * @return true if the user interacted with the consent manually, otherwise false.
+ */
+ public @UserManualInteraction int getUserManualInteractionWithConsent() {
+ return mConsentCompositeStorage.getUserManualInteractionWithConsent();
+ }
+
+ @VisibleForTesting
+ static BooleanFileDatastore createAndInitializeDataStore(@NonNull Context context) {
+ BooleanFileDatastore booleanFileDatastore =
+ new BooleanFileDatastore(
+ context,
+ ConsentConstants.STORAGE_XML_IDENTIFIER,
+ ConsentConstants.STORAGE_VERSION);
+
+ try {
+ booleanFileDatastore.initialize();
+ // TODO(b/259607624): implement a method in the datastore which would support
+ // this exact scenario - if the value is null, return default value provided
+ // in the parameter (similar to SP apply etc.)
+ if (booleanFileDatastore.get(ConsentConstants.NOTIFICATION_DISPLAYED_ONCE) == null) {
+ booleanFileDatastore.put(ConsentConstants.NOTIFICATION_DISPLAYED_ONCE, false);
+ }
+ if (booleanFileDatastore.get(ConsentConstants.GA_UX_NOTIFICATION_DISPLAYED_ONCE)
+ == null) {
+ booleanFileDatastore.put(ConsentConstants.GA_UX_NOTIFICATION_DISPLAYED_ONCE, false);
+ }
+ } catch (IOException | IllegalArgumentException | NullPointerException e) {
+ throw new RuntimeException("Failed to initialize the File Datastore!", e);
+ }
+
+ return booleanFileDatastore;
+ }
+
+ // Handle different migration requests based on current consent source of Truth
+ // PPAPI_ONLY: reset the shared preference to reset status of migrating consent from PPAPI to
+ // system server.
+ // PPAPI_AND_SYSTEM_SERVER: migrate consent from PPAPI to system server.
+ // SYSTEM_SERVER_ONLY: migrate consent from PPAPI to system server and clear PPAPI consent
+ @VisibleForTesting
+ static void handleConsentMigrationIfNeeded(
+ @NonNull Context context,
+ @NonNull BooleanFileDatastore datastore,
+ AdServicesStorageManager adServicesManager,
+ @NonNull StatsdAdServicesLogger statsdAdServicesLogger,
+ @Flags.ConsentSourceOfTruth int consentSourceOfTruth) {
+ Objects.requireNonNull(context);
+ // On R/S, handleConsentMigrationIfNeeded should never be executed.
+ // It is a T+ feature. On T+, this function should only execute if it's within the
+ // AdServices
+ // APK and not ExtServices. So check if it's within ExtServices, and bail out if that's the
+ // case on any platform.
+ String packageName = context.getPackageName();
+ if (packageName != null && packageName.endsWith(ADEXTSERVICES_PACKAGE_NAME_SUFFIX)) {
+ LogUtil.d("Aborting attempt to migrate consent in ExtServices");
+ return;
+ }
+ Objects.requireNonNull(datastore);
+ if (consentSourceOfTruth == Flags.PPAPI_AND_SYSTEM_SERVER
+ || consentSourceOfTruth == Flags.SYSTEM_SERVER_ONLY) {
+ Objects.requireNonNull(adServicesManager);
+ }
+
+ switch (consentSourceOfTruth) {
+ case Flags.PPAPI_ONLY:
+ // Technically we only need to reset the SHARED_PREFS_KEY_HAS_MIGRATED bit once.
+ // What we need is clearIfSet operation which is not available in SP. So here we
+ // always reset the bit since otherwise we need to read the SP to read the value and
+ // the clear the value.
+ // The only flow we would do are:
+ // Case 1: DUAL-> PPAPI if there is a bug in System Server
+ // Case 2: DUAL -> SYSTEM_SERVER_ONLY: if everything goes smoothly.
+ resetSharedPreference(context, ConsentConstants.SHARED_PREFS_KEY_HAS_MIGRATED);
+ break;
+ case Flags.PPAPI_AND_SYSTEM_SERVER:
+ migratePpApiConsentToSystemService(
+ context, datastore, adServicesManager, statsdAdServicesLogger);
+ break;
+ case Flags.SYSTEM_SERVER_ONLY:
+ migratePpApiConsentToSystemService(
+ context, datastore, adServicesManager, statsdAdServicesLogger);
+ clearPpApiConsent(context, datastore);
+ break;
+ case Flags.APPSEARCH_ONLY:
+ // If this is an S- device, the consent source of truth is always APPSEARCH_ONLY.
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Reset data for the specific AdServicesApiType
+ @VisibleForTesting
+ void resetByApi(AdServicesApiType apiType) throws IOException {
+ switch (apiType) {
+ case TOPICS:
+ resetTopicsAndBlockedTopics();
+ break;
+ case FLEDGE:
+ clearAllAppConsentData();
+ resetUserProfileId();
+ break;
+ case MEASUREMENTS:
+ resetMeasurement();
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void resetUserProfileId() {
+ mUserProfileIdManager.deleteId();
+ }
+
+ // Perform a one-time migration to migrate existing PPAPI Consent
+ @VisibleForTesting
+ // Suppress lint warning for context.getUser in R since this code is unused in R
+ @SuppressWarnings("NewApi")
+ static void migratePpApiConsentToSystemService(
+ @NonNull Context context,
+ @NonNull BooleanFileDatastore datastore,
+ @NonNull AdServicesStorageManager adServicesManager,
+ @NonNull StatsdAdServicesLogger statsdAdServicesLogger) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(datastore);
+ Objects.requireNonNull(adServicesManager);
+
+ AppConsents appConsents = null;
+ try {
+ // Exit if migration has happened.
+ SharedPreferences sharedPreferences =
+ FileCompatUtils.getSharedPreferencesHelper(
+ context, ConsentConstants.SHARED_PREFS_CONSENT, Context.MODE_PRIVATE);
+ // If we migrated data to system server either from PPAPI or from AppSearch, do not
+ // attempt another migration of data to system server.
+ boolean shouldSkipMigration =
+ sharedPreferences.getBoolean(
+ ConsentConstants.SHARED_PREFS_KEY_APPSEARCH_HAS_MIGRATED,
+ /* default= */ false)
+ || sharedPreferences.getBoolean(
+ ConsentConstants.SHARED_PREFS_KEY_HAS_MIGRATED,
+ /* default= */ false);
+ if (shouldSkipMigration) {
+ LogUtil.v(
+ "Consent migration has happened to user %d, skip...",
+ context.getUser().getIdentifier());
+ return;
+ }
+ LogUtil.d("Started migrating Consent from PPAPI to System Service");
+
+ Boolean consentKey = Boolean.TRUE.equals(datastore.get(ConsentConstants.CONSENT_KEY));
+
+ // Migrate Consent and Notification Displayed to System Service.
+ // Set consent enabled only when value is TRUE. FALSE and null are regarded as disabled.
+ adServicesManager.setConsent(AdServicesApiType.ALL_API, consentKey);
+ // Set notification displayed only when value is TRUE. FALSE and null are regarded as
+ // not displayed.
+ if (Boolean.TRUE.equals(datastore.get(ConsentConstants.NOTIFICATION_DISPLAYED_ONCE))) {
+ adServicesManager.recordNotificationDisplayed(true);
+ }
+
+ Boolean manualInteractionRecorded =
+ datastore.get(ConsentConstants.MANUAL_INTERACTION_WITH_CONSENT_RECORDED);
+ if (manualInteractionRecorded != null) {
+ adServicesManager.recordUserManualInteractionWithConsent(
+ manualInteractionRecorded ? 1 : -1);
+ }
+
+ // Save migration has happened into shared preferences.
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putBoolean(ConsentConstants.SHARED_PREFS_KEY_HAS_MIGRATED, true);
+ appConsents =
+ AppConsents.builder()
+ .setDefaultConsent(consentKey)
+ .setMsmtConsent(consentKey)
+ .setFledgeConsent(consentKey)
+ .setTopicsConsent(consentKey)
+ .build();
+
+ if (editor.commit()) {
+ LogUtil.d("Finished migrating Consent from PPAPI to System Service");
+ statsdAdServicesLogger.logConsentMigrationStats(
+ getConsentManagerStatsForLogging(
+ appConsents,
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_UPDATED,
+ ConsentMigrationStats.MigrationType.PPAPI_TO_SYSTEM_SERVICE,
+ context));
+ } else {
+ LogUtil.e(
+ "Finished migrating Consent from PPAPI to System Service but shared"
+ + " preference is not updated.");
+ ErrorLogUtil.e(
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_UPDATE_FAILURE,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ statsdAdServicesLogger.logConsentMigrationStats(
+ getConsentManagerStatsForLogging(
+ appConsents,
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_NOT_UPDATED,
+ ConsentMigrationStats.MigrationType.PPAPI_TO_SYSTEM_SERVICE,
+ context));
+ }
+ } catch (Exception e) {
+ LogUtil.e("PPAPI consent data migration failed: ", e);
+ statsdAdServicesLogger.logConsentMigrationStats(
+ getConsentManagerStatsForLogging(
+ appConsents,
+ ConsentMigrationStats.MigrationStatus.FAILURE,
+ ConsentMigrationStats.MigrationType.PPAPI_TO_SYSTEM_SERVICE,
+ context));
+ }
+ }
+
+ // Clear PPAPI Consent if fully migrated to use system server consent. This is because system
+ // consent cannot be migrated back to PPAPI. This data clearing should only happen once.
+ @VisibleForTesting
+ static void clearPpApiConsent(
+ @NonNull Context context, @NonNull BooleanFileDatastore datastore) {
+ // Exit if PPAPI consent has cleared.
+ SharedPreferences sharedPreferences =
+ FileCompatUtils.getSharedPreferencesHelper(
+ context, ConsentConstants.SHARED_PREFS_CONSENT, Context.MODE_PRIVATE);
+ if (sharedPreferences.getBoolean(
+ ConsentConstants.SHARED_PREFS_KEY_PPAPI_HAS_CLEARED, /* defValue */ false)) {
+ return;
+ }
+
+ LogUtil.d("Started clearing Consent in PPAPI.");
+
+ try {
+ datastore.clear();
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to clear PPAPI Consent", e);
+ }
+
+ // Save that PPAPI consent has cleared into shared preferences.
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putBoolean(ConsentConstants.SHARED_PREFS_KEY_PPAPI_HAS_CLEARED, true);
+
+ if (editor.commit()) {
+ LogUtil.d("Finished clearing Consent in PPAPI.");
+ } else {
+ LogUtil.e("Finished clearing Consent in PPAPI but shared preference is not updated.");
+ ErrorLogUtil.e(
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_UPDATE_FAILURE,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ }
+ }
+
+ // Set the shared preference to false for given key.
+ @VisibleForTesting
+ static void resetSharedPreference(
+ @NonNull Context context, @NonNull String sharedPreferenceKey) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(sharedPreferenceKey);
+
+ SharedPreferences sharedPreferences =
+ FileCompatUtils.getSharedPreferencesHelper(
+ context, ConsentConstants.SHARED_PREFS_CONSENT, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putBoolean(sharedPreferenceKey, false);
+
+ if (editor.commit()) {
+ LogUtil.d("Finished resetting shared preference for " + sharedPreferenceKey);
+ } else {
+ LogUtil.e("Failed to reset shared preference for " + sharedPreferenceKey);
+ ErrorLogUtil.e(
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_RESET_FAILURE,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ }
+ }
+
+ // To write to PPAPI if consent source of truth is PPAPI_ONLY or dual sources.
+ // To write to system server if consent source of truth is SYSTEM_SERVER_ONLY or dual sources.
+ @VisibleForTesting
+ void setConsentToSourceOfTruth(boolean isGiven) {
+ mConsentCompositeStorage.setConsent(AdServicesApiType.ALL_API, isGiven);
+ }
+
+ @VisibleForTesting
+ boolean getConsentFromSourceOfTruth() {
+ return mConsentCompositeStorage.getConsent(AdServicesApiType.ALL_API).isGiven();
+ }
+
+ @VisibleForTesting
+ boolean getPerApiConsentFromSourceOfTruth(AdServicesApiType apiType) {
+ return mConsentCompositeStorage.getConsent(apiType).isGiven();
+ }
+
+ @VisibleForTesting
+ void setPerApiConsentToSourceOfTruth(boolean isGiven, AdServicesApiType apiType) {
+ mConsentCompositeStorage.setConsent(apiType, isGiven);
+ }
+
+ private static void storeUserManualInteractionToPpApi(
+ @ConsentManagerV2.UserManualInteraction int interaction, BooleanFileDatastore datastore)
+ throws IOException {
+ switch (interaction) {
+ case NO_MANUAL_INTERACTIONS_RECORDED:
+ datastore.put(ConsentConstants.MANUAL_INTERACTION_WITH_CONSENT_RECORDED, false);
+ break;
+ case UNKNOWN:
+ datastore.remove(ConsentConstants.MANUAL_INTERACTION_WITH_CONSENT_RECORDED);
+ break;
+ case MANUAL_INTERACTIONS_RECORDED:
+ datastore.put(ConsentConstants.MANUAL_INTERACTION_WITH_CONSENT_RECORDED, true);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ String.format("InteractionId < %d > can not be handled.", interaction));
+ }
+ }
+
+ /**
+ * This method handles migration of consent data from AppSearch to AdServices. Consent data is
+ * written to AppSearch on S- and ported to AdServices after OTA to T. If any new data is
+ * written for consent, we need to make sure it is migrated correctly post-OTA in this method.
+ */
+ @VisibleForTesting
+ static void handleConsentMigrationFromAppSearchIfNeeded(
+ @NonNull Context context,
+ @NonNull BooleanFileDatastore datastore,
+ @NonNull AppConsentDao appConsentDao,
+ @NonNull AppSearchConsentStorageManager appSearchConsentStorageManager,
+ @NonNull AdServicesStorageManager adServicesStorageManager,
+ @NonNull StatsdAdServicesLogger statsdAdServicesLogger) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(appSearchConsentStorageManager);
+ LogUtil.d("Check migrating Consent from AppSearch to PPAPI and System Service");
+
+ // On R/S, this function should never be executed because AppSearch to PPAPI and
+ // System Server migration is a T+ feature. On T+, this function should only execute
+ // if it's within the AdServices APK and not ExtServices. So check if it's within
+ // ExtServices, and bail out if that's the case on any platform.
+ String packageName = context.getPackageName();
+ if (packageName != null && packageName.endsWith(ADEXTSERVICES_PACKAGE_NAME_SUFFIX)) {
+ LogUtil.d(
+ "Aborting attempt to migrate AppSearch to PPAPI and System Service in"
+ + " ExtServices");
+ return;
+ }
+
+ AppConsents appConsents = null;
+ try {
+ // This should be called only once after OTA (if flag is enabled). If we did not record
+ // showing the notification on T+ yet and we have shown the notification on S- (as
+ // recorded
+ // in AppSearch), initialize T+ consent data so that we don't show notification twice
+ // (after
+ // OTA upgrade).
+ SharedPreferences sharedPreferences =
+ FileCompatUtils.getSharedPreferencesHelper(
+ context, ConsentConstants.SHARED_PREFS_CONSENT, Context.MODE_PRIVATE);
+ // If we did not migrate notification data, we should not attempt to migrate anything.
+ if (!appSearchConsentStorageManager.migrateConsentDataIfNeeded(
+ sharedPreferences, datastore, adServicesStorageManager, appConsentDao)) {
+ LogUtil.d("Skipping consent migration from AppSearch");
+ return;
+ }
+ // Migrate Consent for all APIs and per API to PP API and System Service.
+ appConsents =
+ migrateAppSearchConsents(
+ appSearchConsentStorageManager, adServicesStorageManager, datastore);
+ // Record interactions data only if we recorded an interaction in AppSearch.
+ int manualInteractionRecorded =
+ appSearchConsentStorageManager.getUserManualInteractionWithConsent();
+ if (manualInteractionRecorded == MANUAL_INTERACTIONS_RECORDED) {
+ // Initialize PP API datastore.
+ storeUserManualInteractionToPpApi(MANUAL_INTERACTIONS_RECORDED, datastore);
+ // Initialize system service.
+ adServicesStorageManager.recordUserManualInteractionWithConsent(
+ manualInteractionRecorded);
+ }
+
+ // Record that we migrated consent data from AppSearch. We write the notification data
+ // to system server and perform migration only if system server did not record any
+ // notification having been displayed.
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putBoolean(ConsentConstants.SHARED_PREFS_KEY_APPSEARCH_HAS_MIGRATED, true);
+ if (editor.commit()) {
+ LogUtil.d("Finished migrating Consent from AppSearch to PPAPI + System Service");
+ statsdAdServicesLogger.logConsentMigrationStats(
+ getConsentManagerStatsForLogging(
+ appConsents,
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_UPDATED,
+ ConsentMigrationStats.MigrationType.APPSEARCH_TO_SYSTEM_SERVICE,
+ context));
+ } else {
+ LogUtil.e(
+ "Finished migrating Consent from AppSearch to PPAPI + System Service "
+ + "but shared preference is not updated.");
+ statsdAdServicesLogger.logConsentMigrationStats(
+ getConsentManagerStatsForLogging(
+ appConsents,
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_NOT_UPDATED,
+ ConsentMigrationStats.MigrationType.APPSEARCH_TO_SYSTEM_SERVICE,
+ context));
+ }
+ } catch (IOException e) {
+ LogUtil.e("AppSearch consent data migration failed: ", e);
+ ErrorLogUtil.e(
+ e,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__APP_SEARCH_DATA_MIGRATION_FAILURE,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX);
+ statsdAdServicesLogger.logConsentMigrationStats(
+ getConsentManagerStatsForLogging(
+ appConsents,
+ ConsentMigrationStats.MigrationStatus.FAILURE,
+ ConsentMigrationStats.MigrationType.APPSEARCH_TO_SYSTEM_SERVICE,
+ context));
+ }
+ }
+
+ /**
+ * This method returns and migrates the consent states (opt in/out) for all PPAPIs, each API and
+ * their default consent values.
+ */
+ @VisibleForTesting
+ static AppConsents migrateAppSearchConsents(
+ AppSearchConsentStorageManager appSearchConsentManager,
+ AdServicesStorageManager adServicesManager,
+ BooleanFileDatastore datastore)
+ throws IOException {
+ Map<String, Boolean> consentMap = new HashMap<>();
+ for (AdServicesApiType apiType : AdServicesApiType.values()) {
+ if (apiType == AdServicesApiType.UNKNOWN) {
+ continue;
+ }
+ boolean consented = appSearchConsentManager.getConsent(apiType).isGiven();
+ datastore.put(apiType.toPpApiDatastoreKey(), consented);
+ adServicesManager.setConsent(apiType, consented);
+ boolean defaultConsent = appSearchConsentManager.getDefaultConsent(apiType).isGiven();
+ datastore.put(apiType.toDefaultConsentDatastoreKey(), defaultConsent);
+ adServicesManager.recordDefaultConsent(apiType, defaultConsent);
+ consentMap.put(apiType.toPpApiDatastoreKey(), consented);
+ consentMap.put(apiType.toDefaultConsentDatastoreKey(), defaultConsent);
+ }
+ return AppConsents.builder()
+ .setMsmtConsent(
+ consentMap.get(AdServicesApiType.MEASUREMENTS.toPpApiDatastoreKey()))
+ .setTopicsConsent(consentMap.get(AdServicesApiType.TOPICS.toPpApiDatastoreKey()))
+ .setFledgeConsent(consentMap.get(AdServicesApiType.FLEDGE.toPpApiDatastoreKey()))
+ .setDefaultConsent(
+ consentMap.get(AdServicesApiType.ALL_API.toDefaultConsentDatastoreKey()))
+ .build();
+ }
+
+ /**
+ * Represents revoked consent as internally determined by the PP APIs.
+ *
+ * <p>This is an internal-only exception and is not meant to be returned to external callers.
+ */
+ public static class RevokedConsentException extends IllegalStateException {
+ public static final String REVOKED_CONSENT_ERROR_MESSAGE =
+ "Error caused by revoked user consent";
+
+ /** Creates an instance of a {@link RevokedConsentException}. */
+ public RevokedConsentException() {
+ super(REVOKED_CONSENT_ERROR_MESSAGE);
+ }
+ }
+
+ private void asyncExecute(Runnable runnable) {
+ AdServicesExecutors.getBackgroundExecutor().execute(runnable);
+ }
+
+ private void logWipeoutStats(WipeoutStatus wipeoutStatus) {
+ AdServicesLoggerImpl.getInstance()
+ .logMeasurementWipeoutStats(
+ new MeasurementWipeoutStats.Builder()
+ .setCode(AD_SERVICES_MEASUREMENT_WIPEOUT)
+ .setWipeoutType(wipeoutStatus.getWipeoutType().getValue())
+ .build());
+ }
+
+ /** Returns whether the isAdIdEnabled bit is true based on consent_source_of_truth. */
+ public Boolean isAdIdEnabled() {
+ return mConsentCompositeStorage.isAdIdEnabled();
+ }
+
+ /** Set the AdIdEnabled bit to storage based on consent_source_of_truth. */
+ public void setAdIdEnabled(boolean isAdIdEnabled) {
+ mConsentCompositeStorage.setAdIdEnabled(isAdIdEnabled);
+ }
+
+ /** Returns whether the isU18Account bit is true based on consent_source_of_truth. */
+ public Boolean isU18Account() {
+ return mConsentCompositeStorage.isU18Account();
+ }
+
+ /** Set the U18Account bit to storage based on consent_source_of_truth. */
+ public void setU18Account(boolean isU18Account) {
+ mConsentCompositeStorage.setU18Account(isU18Account);
+ }
+
+ /** Returns whether the isEntryPointEnabled bit is true based on consent_source_of_truth. */
+ public Boolean isEntryPointEnabled() {
+ return mConsentCompositeStorage.isEntryPointEnabled();
+ }
+
+ /** Set the EntryPointEnabled bit to storage based on consent_source_of_truth. */
+ public void setEntryPointEnabled(boolean isEntryPointEnabled) {
+ mConsentCompositeStorage.setEntryPointEnabled(isEntryPointEnabled);
+ }
+
+ /** Returns whether the isAdultAccount bit is true based on consent_source_of_truth. */
+ public Boolean isAdultAccount() {
+ return mConsentCompositeStorage.isAdultAccount();
+ }
+
+ /** Set the AdultAccount bit to storage based on consent_source_of_truth. */
+ public void setAdultAccount(boolean isAdultAccount) {
+ mConsentCompositeStorage.setAdultAccount(isAdultAccount);
+ }
+
+ /**
+ * Returns whether the wasU18NotificationDisplayed bit is true based on consent_source_of_truth.
+ */
+ public Boolean wasU18NotificationDisplayed() {
+ return mConsentCompositeStorage.wasU18NotificationDisplayed();
+ }
+
+ /** Set the U18NotificationDisplayed bit to storage based on consent_source_of_truth. */
+ public void setU18NotificationDisplayed(boolean wasU18NotificationDisplayed) {
+ mConsentCompositeStorage.setU18NotificationDisplayed(wasU18NotificationDisplayed);
+ }
+
+ /** Returns current UX based on consent_source_of_truth. */
+ public PrivacySandboxUxCollection getUx() {
+ return mConsentCompositeStorage.getUx();
+ }
+
+ /** Set the current UX to storage based on consent_source_of_truth. */
+ public void setUx(PrivacySandboxUxCollection ux) {
+ mConsentCompositeStorage.setUx(ux);
+ }
+
+ /** Returns current enrollment channel based on consent_source_of_truth. */
+ public PrivacySandboxEnrollmentChannelCollection getEnrollmentChannel(
+ PrivacySandboxUxCollection ux) {
+ return mConsentCompositeStorage.getEnrollmentChannel(ux);
+ }
+
+ /** Set the current enrollment channel to storage based on consent_source_of_truth. */
+ public void setEnrollmentChannel(
+ PrivacySandboxUxCollection ux, PrivacySandboxEnrollmentChannelCollection channel) {
+ mConsentCompositeStorage.setEnrollmentChannel(ux, channel);
+ }
+
+ @VisibleForTesting
+ void setConsentToPpApi(boolean isGiven) throws IOException {
+ mDatastore.put(ConsentConstants.CONSENT_KEY, isGiven);
+ }
+
+ /* Returns the region od the device */
+ private static int getConsentRegion(@NonNull Context context) {
+ return DeviceRegionProvider.isEuDevice(context)
+ ? AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__EU
+ : AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__ROW;
+ }
+
+ /* Returns an object of ConsentMigrationStats */
+ private static ConsentMigrationStats getConsentManagerStatsForLogging(
+ AppConsents appConsents,
+ ConsentMigrationStats.MigrationStatus migrationStatus,
+ ConsentMigrationStats.MigrationType migrationType,
+ Context context) {
+ ConsentMigrationStats consentMigrationStats =
+ ConsentMigrationStats.builder()
+ .setMigrationType(migrationType)
+ .setMigrationStatus(migrationStatus)
+ // When appConsents is null we log it as a failure
+ .setMigrationStatus(
+ appConsents != null
+ ? migrationStatus
+ : ConsentMigrationStats.MigrationStatus.FAILURE)
+ .setMsmtConsent(appConsents == null || appConsents.getMsmtConsent())
+ .setTopicsConsent(appConsents == null || appConsents.getTopicsConsent())
+ .setFledgeConsent(appConsents == null || appConsents.getFledgeConsent())
+ .setDefaultConsent(appConsents == null || appConsents.getDefaultConsent())
+ .setRegion(getConsentRegion(context))
+ .build();
+ return consentMigrationStats;
+ }
+}
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/ConsentMigrationUtils.java b/adservices/service-core/java/com/android/adservices/service/consent/ConsentMigrationUtils.java
index d5ccb28f3..9bd7afd61 100644
--- a/adservices/service-core/java/com/android/adservices/service/consent/ConsentMigrationUtils.java
+++ b/adservices/service-core/java/com/android/adservices/service/consent/ConsentMigrationUtils.java
@@ -20,6 +20,8 @@ import static android.adservices.extdata.AdServicesExtDataParams.BOOLEAN_TRUE;
import static android.adservices.extdata.AdServicesExtDataParams.BOOLEAN_UNKNOWN;
import static android.adservices.extdata.AdServicesExtDataParams.STATE_MANUAL_INTERACTIONS_RECORDED;
+import static com.android.adservices.service.consent.ConsentManager.getConsentManagerStatsForLogging;
+
import android.adservices.extdata.AdServicesExtDataParams;
import android.annotation.NonNull;
import android.annotation.TargetApi;
@@ -32,8 +34,11 @@ import androidx.annotation.Nullable;
import com.android.adservices.LogUtil;
import com.android.adservices.data.common.BooleanFileDatastore;
import com.android.adservices.service.appsearch.AppSearchConsentManager;
+import com.android.adservices.service.appsearch.AppSearchConsentStorageManager;
import com.android.adservices.service.common.compat.FileCompatUtils;
import com.android.adservices.service.extdata.AdServicesExtDataStorageServiceManager;
+import com.android.adservices.service.stats.ConsentMigrationStats;
+import com.android.adservices.service.stats.StatsdAdServicesLogger;
import com.android.modules.utils.build.SdkLevel;
import java.util.Objects;
@@ -50,10 +55,77 @@ public final class ConsentMigrationUtils {
* as it's the new consent source of truth. If any new data is written for consent, we need to
* make sure it is migrated correctly post-OTA in this method.
*/
+ @TargetApi(Build.VERSION_CODES.S)
public static void handleConsentMigrationToAppSearchIfNeeded(
@NonNull Context context,
@NonNull BooleanFileDatastore datastore,
@Nullable AppSearchConsentManager appSearchConsentManager,
+ @Nullable AdServicesExtDataStorageServiceManager adExtDataManager,
+ @Nullable StatsdAdServicesLogger statsdAdServicesLogger) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(datastore);
+ Objects.requireNonNull(statsdAdServicesLogger);
+ LogUtil.d("Check if consent migration to AppSearch is needed.");
+ AppConsents appConsents = null;
+ try {
+ SharedPreferences sharedPreferences =
+ FileCompatUtils.getSharedPreferencesHelper(
+ context, ConsentConstants.SHARED_PREFS_CONSENT, Context.MODE_PRIVATE);
+
+ if (!isMigrationToAppSearchNeeded(
+ context, sharedPreferences, appSearchConsentManager, adExtDataManager)) {
+ LogUtil.d("Skipping consent migration to AppSearch");
+ return;
+ }
+
+ // Reduce number of read calls by fetching all the AdExt data at once.
+ AdServicesExtDataParams dataFromR = adExtDataManager.getAdServicesExtData();
+ if (dataFromR.getIsNotificationDisplayed() != BOOLEAN_TRUE) {
+ LogUtil.d("Skipping consent migration to AppSearch; notification not shown on R");
+ return;
+ }
+
+ appConsents = migrateDataToAppSearch(appSearchConsentManager, dataFromR, datastore);
+
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putBoolean(ConsentConstants.SHARED_PREFS_KEY_HAS_MIGRATED_TO_APP_SEARCH, true);
+ if (editor.commit()) {
+ LogUtil.d("Finished migrating consent to AppSearch.");
+ logMigrationToAppSearch(
+ statsdAdServicesLogger,
+ appConsents,
+ ConsentMigrationStats.MigrationStatus.SUCCESS_WITH_SHARED_PREF_UPDATED,
+ context);
+ } else {
+ LogUtil.e("Finished migrating consent to AppSearch. Shared prefs not updated.");
+ logMigrationToAppSearch(
+ statsdAdServicesLogger,
+ appConsents,
+ ConsentMigrationStats.MigrationStatus.SUCCESS_WITH_SHARED_PREF_NOT_UPDATED,
+ context);
+ }
+ // No longer need access to Android R data. Safe to clear here.
+ adExtDataManager.clearDataOnOtaAsync();
+ } catch (Exception e) {
+ LogUtil.e("Consent migration to AppSearch failed: ", e);
+ logMigrationToAppSearch(
+ statsdAdServicesLogger,
+ appConsents,
+ ConsentMigrationStats.MigrationStatus.FAILURE,
+ context);
+ }
+ }
+
+ /**
+ * This method handles migration of consent data to AppSearch post-OTA R -> S. Consent data is
+ * written to AdServicesExtDataStorageService on R and ported over to AppSearch after OTA to S
+ * as it's the new consent source of truth. If any new data is written for consent, we need to
+ * make sure it is migrated correctly post-OTA in this method.
+ */
+ public static void handleConsentMigrationToAppSearchIfNeededV2(
+ @NonNull Context context,
+ @NonNull BooleanFileDatastore datastore,
+ @Nullable AppSearchConsentStorageManager appSearchConsentManager,
@Nullable AdServicesExtDataStorageServiceManager adExtDataManager) {
Objects.requireNonNull(context);
Objects.requireNonNull(datastore);
@@ -65,7 +137,7 @@ public final class ConsentMigrationUtils {
FileCompatUtils.getSharedPreferencesHelper(
context, ConsentConstants.SHARED_PREFS_CONSENT, Context.MODE_PRIVATE);
- if (!isMigrationToAppSearchNeeded(
+ if (!isMigrationToAppSearchNeededV2(
context, sharedPreferences, appSearchConsentManager, adExtDataManager)) {
LogUtil.d("Skipping consent migration to AppSearch");
return;
@@ -78,7 +150,7 @@ public final class ConsentMigrationUtils {
return;
}
- migrateDataToAppSearch(appSearchConsentManager, dataFromR, datastore);
+ migrateDataToAppSearchV2(appSearchConsentManager, dataFromR, datastore);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(ConsentConstants.SHARED_PREFS_KEY_HAS_MIGRATED_TO_APP_SEARCH, true);
@@ -143,8 +215,56 @@ public final class ConsentMigrationUtils {
return !isNotificationDisplayedOnS;
}
+ private static boolean isMigrationToAppSearchNeededV2(
+ Context context,
+ SharedPreferences sharedPreferences,
+ AppSearchConsentStorageManager appSearchConsentManager,
+ AdServicesExtDataStorageServiceManager adExtDataManager) {
+ if (SdkLevel.isAtLeastT() || !SdkLevel.isAtLeastS()) {
+ LogUtil.d("Not S device. Consent migration to AppSearch not needed");
+ return false;
+ }
+
+ // Cannot be null on S since the consent source of truth has to be APPSEARCH_ONLY.
+ Objects.requireNonNull(appSearchConsentManager);
+
+ // There could be a case where we may need to ramp down enable_adext_service_consent_data
+ // flag on S, in which case we should gracefully handle consent migration by skipping.
+ if (adExtDataManager == null) {
+ LogUtil.d("AdExtDataManager is null. Consent migration to AppSearch not needed");
+ return false;
+ }
+
+ boolean isMigrationToAppSearchDone =
+ sharedPreferences.getBoolean(
+ ConsentConstants.SHARED_PREFS_KEY_HAS_MIGRATED_TO_APP_SEARCH,
+ /* defValue= */ false);
+ if (isMigrationToAppSearchDone) {
+ LogUtil.d(
+ "Consent migration to AppSearch is already done for user %d.",
+ context.getUser().getIdentifier());
+ return false;
+ }
+
+ // Just in case, check all notification types to ensure notification is not shown. We do not
+ // want to override consent if notification is already shown.
+ boolean isNotificationDisplayedOnS =
+ appSearchConsentManager.wasU18NotificationDisplayed()
+ || appSearchConsentManager.wasNotificationDisplayed()
+ || appSearchConsentManager.wasGaUxNotificationDisplayed();
+ LogUtil.d(
+ "Notification shown status on S for migrating consent to AppSearch: "
+ + isNotificationDisplayedOnS);
+
+ // If notification is not shown, we will need to perform another check to ensure
+ // notification was shown on R before performing migration. This check will be performed
+ // later in order to reduce number of calls to AdExtDataService in the consent migration
+ // process.
+ return !isNotificationDisplayedOnS;
+ }
+
@TargetApi(Build.VERSION_CODES.S)
- private static void migrateDataToAppSearch(
+ private static AppConsents migrateDataToAppSearch(
AppSearchConsentManager appSearchConsentManager,
AdServicesExtDataParams dataFromR,
BooleanFileDatastore datastore) {
@@ -178,5 +298,72 @@ public final class ConsentMigrationUtils {
if (dataFromR.getIsAdultAccount() != BOOLEAN_UNKNOWN) {
appSearchConsentManager.setAdultAccount(dataFromR.getIsAdultAccount() == BOOLEAN_TRUE);
}
+
+ // Logging false for fledge and topics consent by default because only measurement is
+ // supported on R.
+ AppConsents appConsents =
+ AppConsents.builder()
+ .setDefaultConsent(
+ measurementDefaultConsent != null
+ ? measurementDefaultConsent
+ : false)
+ .setMsmtConsent(isMeasurementConsented)
+ .setFledgeConsent(false)
+ .setTopicsConsent(false)
+ .build();
+ return appConsents;
+ }
+
+ @TargetApi(Build.VERSION_CODES.S)
+ private static void logMigrationToAppSearch(
+ StatsdAdServicesLogger statsdAdServicesLogger,
+ AppConsents appConsents,
+ ConsentMigrationStats.MigrationStatus migrationStatus,
+ Context context) {
+ statsdAdServicesLogger.logConsentMigrationStats(
+ getConsentManagerStatsForLogging(
+ appConsents,
+ migrationStatus,
+ ConsentMigrationStats.MigrationType.ADEXT_SERVICE_TO_APPSEARCH,
+ context));
+ }
+
+ @TargetApi(Build.VERSION_CODES.S)
+ private static void migrateDataToAppSearchV2(
+ AppSearchConsentStorageManager appSearchConsentStorageManager,
+ AdServicesExtDataParams dataFromR,
+ BooleanFileDatastore datastore) {
+ // Default measurement consent is stored using PPAPI_ONLY source on R.
+ Boolean measurementDefaultConsent =
+ datastore.get(ConsentConstants.MEASUREMENT_DEFAULT_CONSENT);
+ if (measurementDefaultConsent != null) {
+ appSearchConsentStorageManager.recordDefaultConsent(
+ AdServicesApiType.MEASUREMENTS, measurementDefaultConsent);
+ }
+
+ boolean isMeasurementConsented = dataFromR.getIsMeasurementConsented() == BOOLEAN_TRUE;
+ appSearchConsentStorageManager.setConsent(
+ AdServicesApiType.MEASUREMENTS, isMeasurementConsented);
+
+ appSearchConsentStorageManager.setU18NotificationDisplayed(
+ dataFromR.getIsNotificationDisplayed() == BOOLEAN_TRUE);
+
+ // Record interaction data only if we recorded an interaction in
+ // AdServicesExtDataStorageService.
+ int manualInteractionRecorded = dataFromR.getManualInteractionWithConsentStatus();
+ if (manualInteractionRecorded == STATE_MANUAL_INTERACTIONS_RECORDED) {
+ appSearchConsentStorageManager.recordUserManualInteractionWithConsent(
+ manualInteractionRecorded);
+ }
+
+ if (dataFromR.getIsU18Account() != BOOLEAN_UNKNOWN) {
+ appSearchConsentStorageManager.setU18Account(
+ dataFromR.getIsU18Account() == BOOLEAN_TRUE);
+ }
+
+ if (dataFromR.getIsAdultAccount() != BOOLEAN_UNKNOWN) {
+ appSearchConsentStorageManager.setAdultAccount(
+ dataFromR.getIsAdultAccount() == BOOLEAN_TRUE);
+ }
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/IConsentStorage.java b/adservices/service-core/java/com/android/adservices/service/consent/IConsentStorage.java
index 0c21645d7..ebd47b8da 100644
--- a/adservices/service-core/java/com/android/adservices/service/consent/IConsentStorage.java
+++ b/adservices/service-core/java/com/android/adservices/service/consent/IConsentStorage.java
@@ -117,7 +117,7 @@ public interface IConsentStorage {
*
* @return true if the AdId is enabled by default, false otherwise.
*/
- boolean getDefaultAdIdState();
+ boolean getDefaultAdIdState() throws IOException;
/**
* Retrieves the default consent.
@@ -130,7 +130,7 @@ public interface IConsentStorage {
/** Returns current enrollment channel. */
@NonNull
PrivacySandboxEnrollmentChannelCollection getEnrollmentChannel(
- @NonNull PrivacySandboxUxCollection ux);
+ @NonNull PrivacySandboxUxCollection ux) throws IOException;
/**
* @return an {@link ImmutableList} of all known apps in the database that have not had user
@@ -148,13 +148,13 @@ public interface IConsentStorage {
/** Returns current UX. */
@NonNull
- PrivacySandboxUxCollection getUx();
+ PrivacySandboxUxCollection getUx() throws IOException;
/** Returns whether the isAdIdEnabled bit is true. */
- boolean isAdIdEnabled();
+ boolean isAdIdEnabled() throws IOException;
/** Returns whether the isAdultAccount bit is true. */
- boolean isAdultAccount();
+ boolean isAdultAccount() throws IOException;
/**
* Returns whether a given application (identified by package name) has had user consent
@@ -167,13 +167,14 @@ public interface IConsentStorage {
* application
* @throws IOException if the operation fails
*/
- boolean isConsentRevokedForApp(@NonNull String packageName) throws IllegalArgumentException;
+ boolean isConsentRevokedForApp(@NonNull String packageName)
+ throws IllegalArgumentException, IOException;
/** Returns whether the isEntryPointEnabled bit is true. */
- boolean isEntryPointEnabled();
+ boolean isEntryPointEnabled() throws IOException;
/** Returns whether the isU18Account bit is true. */
- boolean isU18Account();
+ boolean isU18Account() throws IOException;
/** Saves the default AdId state bit to data stores based on source of truth. */
void recordDefaultAdIdState(boolean defaultAdIdState) throws IOException;
@@ -242,7 +243,8 @@ public interface IConsentStorage {
/** Sets the current enrollment channel to storage. */
void setEnrollmentChannel(
@NonNull PrivacySandboxUxCollection ux,
- @NonNull PrivacySandboxEnrollmentChannelCollection channel);
+ @NonNull PrivacySandboxEnrollmentChannelCollection channel)
+ throws IOException;
/** Sets the EntryPointEnabled bit to storage . */
void setEntryPointEnabled(boolean isEntryPointEnabled) throws IOException;
@@ -254,14 +256,14 @@ public interface IConsentStorage {
void setU18NotificationDisplayed(boolean wasU18NotificationDisplayed) throws IOException;
/** Sets the current UX to storage. */
- void setUx(PrivacySandboxUxCollection ux);
+ void setUx(PrivacySandboxUxCollection ux) throws IOException;
/**
* Retrieves if GA UX notification has been displayed.
*
* @return true if GA UX Consent Notification was displayed, otherwise false.
*/
- boolean wasGaUxNotificationDisplayed();
+ boolean wasGaUxNotificationDisplayed() throws IOException;
/**
* Retrieves if notification has been displayed.
@@ -271,5 +273,5 @@ public interface IConsentStorage {
boolean wasNotificationDisplayed() throws IOException;
/** Returns whether the wasU18NotificationDisplayed bit is true. */
- boolean wasU18NotificationDisplayed();
+ boolean wasU18NotificationDisplayed() throws IOException;
}
diff --git a/adservices/service-core/java/com/android/adservices/service/customaudience/CustomAudienceServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/customaudience/CustomAudienceServiceImpl.java
index 8373bb5eb..fcab6c9a8 100644
--- a/adservices/service-core/java/com/android/adservices/service/customaudience/CustomAudienceServiceImpl.java
+++ b/adservices/service-core/java/com/android/adservices/service/customaudience/CustomAudienceServiceImpl.java
@@ -203,8 +203,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
- mContext, ownerPackageName, apiName);
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(mContext, ownerPackageName, apiName);
final int callerUid = getCallingUid(apiName);
final DevContext devContext = mDevContextFilter.createDevContext();
@@ -301,7 +300,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, input.getCallerPackageName(), apiName);
final int callerUid = getCallingUid(apiName);
@@ -386,8 +385,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
- mContext, ownerPackageName, apiName);
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(mContext, ownerPackageName, apiName);
final int callerUid = getCallingUid(apiName);
final DevContext devContext = mDevContextFilter.createDevContext();
@@ -506,7 +504,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
CustomAudienceDao customAudienceDao = mCustomAudienceImpl.getCustomAudienceDao();
@@ -567,7 +565,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
CustomAudienceDao customAudienceDao = mCustomAudienceImpl.getCustomAudienceDao();
@@ -616,7 +614,7 @@ public class CustomAudienceServiceImpl extends ICustomAudienceService.Stub {
}
// Caller permissions must be checked with a non-null callingAppPackageName
- mFledgeAuthorizationFilter.assertAppDeclaredCustomAudiencePermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, devContext.getCallingAppPackageName(), apiName);
CustomAudienceDao customAudienceDao = mCustomAudienceImpl.getCustomAudienceDao();
diff --git a/adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java b/adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java
index 9e4b05ddc..5a78bdaea 100644
--- a/adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java
+++ b/adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java
@@ -147,7 +147,7 @@ public class DevContextFilter {
} catch (PackageManager.NameNotFoundException e) {
LogUtil.w(
- "Unable to retrieve application info for app with ID %d and resolved package "
+ "Unable to retrieve application info for app with ID %s and resolved package "
+ "name '%s', considering not debuggable for safety.",
callingAppPackage, callingAppPackage);
return false;
diff --git a/adservices/service-core/java/com/android/adservices/service/encryptionkey/EncryptionKey.java b/adservices/service-core/java/com/android/adservices/service/encryptionkey/EncryptionKey.java
index 193897963..07dc2aa9c 100644
--- a/adservices/service-core/java/com/android/adservices/service/encryptionkey/EncryptionKey.java
+++ b/adservices/service-core/java/com/android/adservices/service/encryptionkey/EncryptionKey.java
@@ -135,6 +135,21 @@ public class EncryptionKey {
return mLastFetchTime;
}
+ /** Returns the builder for the instance */
+ public EncryptionKey.Builder cloneToBuilder() {
+ return new EncryptionKey.Builder()
+ .setId(this.mId)
+ .setKeyType(this.mKeyType)
+ .setEnrollmentId(this.mEnrollmentId)
+ .setReportingOrigin(this.mReportingOrigin)
+ .setEncryptionKeyUrl(this.mEncryptionKeyUrl)
+ .setProtocolType(this.mProtocolType)
+ .setKeyCommitmentId(this.mKeyCommitmentId)
+ .setBody(this.mBody)
+ .setExpiration(this.mExpiration)
+ .setLastFetchTime(this.mLastFetchTime);
+ }
+
/** Builder for {@link EncryptionKey}. */
public static final class Builder {
private final EncryptionKey mBuilding;
diff --git a/adservices/service-core/java/com/android/adservices/service/enrollment/EnrollmentData.java b/adservices/service-core/java/com/android/adservices/service/enrollment/EnrollmentData.java
index d166f3b6a..6cb1f8c0a 100644
--- a/adservices/service-core/java/com/android/adservices/service/enrollment/EnrollmentData.java
+++ b/adservices/service-core/java/com/android/adservices/service/enrollment/EnrollmentData.java
@@ -140,6 +140,21 @@ public class EnrollmentData {
return Arrays.asList(input.trim().split(SEPARATOR));
}
+ /** Returns the builder for the instance */
+ @NonNull
+ public EnrollmentData.Builder cloneToBuilder() {
+ return new EnrollmentData.Builder()
+ .setEnrollmentId(this.mEnrollmentId)
+ .setCompanyId(this.mCompanyId)
+ .setSdkNames(this.mSdkNames)
+ .setAttributionSourceRegistrationUrl(this.mAttributionSourceRegistrationUrl)
+ .setAttributionTriggerRegistrationUrl(this.mAttributionTriggerRegistrationUrl)
+ .setAttributionReportingUrl(this.mAttributionReportingUrl)
+ .setRemarketingResponseBasedRegistrationUrl(
+ this.mRemarketingResponseBasedRegistrationUrl)
+ .setEncryptionKeyUrl(this.mEncryptionKeyUrl);
+ }
+
/** Builder for {@link EnrollmentData}. */
public static final class Builder {
private final EnrollmentData mBuilding;
diff --git a/adservices/service-core/java/com/android/adservices/service/exception/ConsentStorageDeferException.java b/adservices/service-core/java/com/android/adservices/service/exception/ConsentStorageDeferException.java
new file mode 100644
index 000000000..5edf8e68f
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/service/exception/ConsentStorageDeferException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 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.service.exception;
+
+import java.io.IOException;
+
+/**
+ * Exception class to indicate operation is not supported by current storage manager. This exception
+ * will always be caught in {@link ConsentCompositeStorage}, and ConsentCompositeStorage will call
+ * the next IConsentStorage instance to get/set the right value.
+ */
+public final class ConsentStorageDeferException extends IOException {}
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/PrivacyParams.java b/adservices/service-core/java/com/android/adservices/service/measurement/PrivacyParams.java
index 00a945fa9..b62df0267 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/PrivacyParams.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/PrivacyParams.java
@@ -37,11 +37,6 @@ public final class PrivacyParams {
public static final int EVENT_SOURCE_MAX_REPORTS = 1;
/**
- * Max reports for Install Attributed 'Navigation' {@link Source}.
- */
- public static final int INSTALL_ATTR_NAVIGATION_SOURCE_MAX_REPORTS = 3;
-
- /**
* Max reports for Install Attributed 'Event' {@link Source}.
*/
public static final int INSTALL_ATTR_EVENT_SOURCE_MAX_REPORTS = 2;
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/Source.java b/adservices/service-core/java/com/android/adservices/service/measurement/Source.java
index 2fe5e16b0..35da5c705 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/Source.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/Source.java
@@ -121,6 +121,7 @@ public class Source {
if (mParsedEventReportWindows != null) {
return mParsedEventReportWindows;
}
+
if (mEventReportWindows == null) {
return null;
}
@@ -140,7 +141,8 @@ public class Source {
}
/**
- * Returns parsed or default value of event report windows.
+ * Returns parsed or default value of event report windows (can be used during {@code Source}
+ * construction since the method does not require a {@code Source} object).
*
* @param eventReportWindows string to be parsed
* @param sourceType Source's Type
@@ -149,13 +151,13 @@ public class Source {
* @return parsed or default value
*/
@Nullable
- public static List<Pair<Long, Long>> getOrDefaultEventReportWindows(
+ public static List<Pair<Long, Long>> getOrDefaultEventReportWindowsForFlex(
@Nullable JSONObject eventReportWindows,
@NonNull SourceType sourceType,
long expiryDelta,
@NonNull Flags flags) {
if (eventReportWindows == null) {
- return getDefaultEventReportWindows(expiryDelta, sourceType, flags);
+ return getDefaultEventReportWindowsForFlex(expiryDelta, sourceType, flags);
}
return parseEventReportWindows(eventReportWindows);
}
@@ -180,17 +182,17 @@ public class Source {
@NonNull JSONObject jsonObject) {
List<Pair<Long, Long>> result = new ArrayList<>();
try {
- long startDuration = 0;
+ long startTime = 0L;
if (!jsonObject.isNull("start_time")) {
- startDuration = jsonObject.getLong("start_time");
+ startTime = jsonObject.getLong("start_time");
}
JSONArray endTimesJSON = jsonObject.getJSONArray("end_times");
for (int i = 0; i < endTimesJSON.length(); i++) {
- long endDuration = endTimesJSON.getLong(i);
- Pair<Long, Long> window = new Pair<>(startDuration, endDuration);
+ long endTime = endTimesJSON.getLong(i);
+ Pair<Long, Long> window = Pair.create(startTime, endTime);
result.add(window);
- startDuration = endDuration;
+ startTime = endTime;
}
} catch (JSONException e) {
LoggerFactory.getMeasurementLogger()
@@ -200,24 +202,25 @@ public class Source {
return result;
}
- private static List<Pair<Long, Long>> getDefaultEventReportWindows(
+ private static List<Pair<Long, Long>> getDefaultEventReportWindowsForFlex(
long expiryDelta, SourceType sourceType, Flags flags) {
List<Pair<Long, Long>> result = new ArrayList<>();
- List<Long> defaultEarlyWindows =
- EventReportWindowCalcDelegate.getDefaultEarlyReportingWindows(sourceType, false);
- List<Long> earlyWindows =
+ // Obtain default early report windows without regard to install-related behaviour.
+ List<Long> defaultEarlyWindowEnds =
+ EventReportWindowCalcDelegate.getDefaultEarlyReportingWindowEnds(sourceType, false);
+ List<Long> earlyWindowEnds =
new EventReportWindowCalcDelegate(flags)
- .getConfiguredOrDefaultEarlyReportingWindows(
- sourceType, defaultEarlyWindows, false);
+ .getConfiguredOrDefaultEarlyReportingWindowEnds(
+ sourceType, defaultEarlyWindowEnds);
long windowStart = 0;
- for (long earlyWindow : earlyWindows) {
- if (earlyWindow >= expiryDelta) {
- continue;
+ for (long earlyWindowEnd : earlyWindowEnds) {
+ if (earlyWindowEnd >= expiryDelta) {
+ break;
}
- result.add(new Pair<>(windowStart, earlyWindow));
- windowStart = earlyWindow;
+ result.add(Pair.create(windowStart, earlyWindowEnd));
+ windowStart = earlyWindowEnd;
}
- result.add(new Pair<>(windowStart, expiryDelta));
+ result.add(Pair.create(windowStart, expiryDelta));
return result;
}
@@ -234,8 +237,7 @@ public class Source {
}
private double getInformationGainThreshold(Flags flags) {
- int destinationMultiplier = getDestinationTypeMultiplier(flags);
- if (destinationMultiplier == 2) {
+ if (getDestinationTypeMultiplier(flags) == 2) {
return mSourceType == SourceType.EVENT
? flags.getMeasurementFlexApiMaxInformationGainDualDestinationEvent()
: flags.getMeasurementFlexApiMaxInformationGainDualDestinationNavigation();
@@ -262,32 +264,31 @@ public class Source {
setFlipProbability(mTriggerSpecs.getFlipProbability(this, flags));
return;
}
- boolean installCase = SourceNoiseHandler.isInstallDetectionEnabled(this);
EventReportWindowCalcDelegate eventReportWindowCalcDelegate =
new EventReportWindowCalcDelegate(flags);
int reportingWindowCountForNoising =
- eventReportWindowCalcDelegate.getReportingWindowCountForNoising(this, installCase);
- int maxReportCount =
- eventReportWindowCalcDelegate.getMaxReportCount(this, installCase);
- int destinationMultiplier = getDestinationTypeMultiplier(flags);
+ eventReportWindowCalcDelegate.getReportingWindowCountForNoising(this);
long numberOfStates =
Combinatorics.getNumberOfStarsAndBarsSequences(
- /*numStars=*/ maxReportCount,
+ /*numStars=*/ eventReportWindowCalcDelegate.getMaxReportCount(this),
/*numBars=*/ getTriggerDataCardinality()
* reportingWindowCountForNoising
- * destinationMultiplier);
+ * getDestinationTypeMultiplier(flags));
setNumStates(numberOfStates);
setFlipProbability(Combinatorics.getFlipProbability(numberOfStates));
}
+ /** Should source report coarse destinations */
+ public boolean shouldReportCoarseDestinations(Flags flags) {
+ return flags.getMeasurementEnableCoarseEventReportDestinations()
+ && hasCoarseEventReportDestinations();
+ }
+
/**
* Returns the number of destination types to use in privacy computations.
*/
public int getDestinationTypeMultiplier(Flags flags) {
- boolean shouldReportCoarseDestinations =
- flags.getMeasurementEnableCoarseEventReportDestinations()
- && hasCoarseEventReportDestinations();
- return !shouldReportCoarseDestinations && hasAppDestinations()
+ return !shouldReportCoarseDestinations(flags) && hasAppDestinations()
&& hasWebDestinations()
? SourceNoiseHandler.DUAL_DESTINATION_IMPRESSION_NOISE_MULTIPLIER
: SourceNoiseHandler.SINGLE_DESTINATION_IMPRESSION_NOISE_MULTIPLIER;
@@ -650,9 +651,9 @@ public class Source {
/**
* Time when {@link Source} event report window will expire. (Appends the Event Time to window)
*/
- public Long getProcessedEventReportWindow() {
+ public long getEffectiveEventReportWindow() {
if (mEventReportWindow == null) {
- return null;
+ return getExpiryTime();
}
// TODO(b/290098169): Cleanup after a few releases
// Handling cases where ReportWindow is already stored as mEventTime + mEventReportWindow
@@ -744,6 +745,11 @@ public class Source {
return mInstallCooldownWindow;
}
+ /** Check if install detection is enabled for the source. */
+ public boolean isInstallDetectionEnabled() {
+ return getInstallCooldownWindow() > 0 && hasAppDestinations();
+ }
+
/**
* Is an App-install attributed to the {@link Source}.
*/
@@ -971,10 +977,9 @@ public class Source {
@Nullable Integer maxEventLevelReports,
@NonNull Flags flags) {
if (maxEventLevelReports == null) {
- maxEventLevelReports =
- sourceType == Source.SourceType.NAVIGATION
- ? PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS
- : flags.getMeasurementVtcConfigurableMaxEventReportsCount();
+ return sourceType == Source.SourceType.NAVIGATION
+ ? PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS
+ : flags.getMeasurementVtcConfigurableMaxEventReportsCount();
}
return maxEventLevelReports;
}
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/attribution/AttributionJobHandler.java b/adservices/service-core/java/com/android/adservices/service/measurement/attribution/AttributionJobHandler.java
index 20dbe424e..3d2eec8c2 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/attribution/AttributionJobHandler.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/attribution/AttributionJobHandler.java
@@ -57,6 +57,7 @@ import com.android.adservices.service.measurement.reporting.DebugKeyAccessor;
import com.android.adservices.service.measurement.reporting.DebugReportApi;
import com.android.adservices.service.measurement.reporting.DebugReportApi.Type;
import com.android.adservices.service.measurement.reporting.EventReportWindowCalcDelegate;
+import com.android.adservices.service.measurement.reporting.EventReportWindowCalcDelegate.MomentPlacement;
import com.android.adservices.service.measurement.util.BaseUriExtractor;
import com.android.adservices.service.measurement.util.Filter;
import com.android.adservices.service.measurement.util.UnsignedLong;
@@ -813,12 +814,8 @@ class AttributionJobHandler {
return TriggeringStatus.DROPPED;
}
- if (mEventReportWindowCalcDelegate.getReportingTime(
- source, trigger.getTriggerTime(), trigger.getDestinationType()) == -1
- && (source.getTriggerSpecsString() == null
- || source.getTriggerSpecsString().isEmpty())) {
- mDebugReportApi.scheduleTriggerDebugReport(
- source, trigger, null, measurementDao, Type.TRIGGER_EVENT_REPORT_WINDOW_PASSED);
+ if (source.getTriggerSpecs() == null
+ && !isTriggerFallsWithinWindow(source, trigger, measurementDao)) {
return TriggeringStatus.DROPPED;
}
@@ -1332,16 +1329,10 @@ class AttributionJobHandler {
private boolean isWithinReportLimit(
Source source, int existingReportCount, @EventSurfaceType int destinationType) {
- return mEventReportWindowCalcDelegate.getMaxReportCount(
- source, hasAppInstallAttributionOccurred(source, destinationType))
+ return mEventReportWindowCalcDelegate.getMaxReportCount(source, destinationType)
> existingReportCount;
}
- private static boolean hasAppInstallAttributionOccurred(
- Source source, @EventSurfaceType int destinationType) {
- return destinationType == EventSurfaceType.APP && source.isInstallAttributed();
- }
-
private static boolean isWithinInstallCooldownWindow(Source source, Trigger trigger) {
return trigger.getTriggerTime()
< (source.getEventTime() + source.getInstallCooldownWindow());
@@ -1754,4 +1745,27 @@ class AttributionJobHandler {
attributionStatus.setAggregateDebugReportCount(
attributionStatus.getAggregateDebugReportCount() + count);
}
+
+ private boolean isTriggerFallsWithinWindow(
+ Source source, Trigger trigger, IMeasurementDao measurementDao)
+ throws DatastoreException {
+ MomentPlacement momentPlacement =
+ mEventReportWindowCalcDelegate.fallsWithinWindow(
+ source, trigger.getTriggerTime(), trigger.getDestinationType());
+ if (momentPlacement == MomentPlacement.BEFORE) {
+ mDebugReportApi.scheduleTriggerDebugReport(
+ source,
+ trigger,
+ null,
+ measurementDao,
+ Type.TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED);
+ return false;
+ }
+ if (momentPlacement == MomentPlacement.AFTER) {
+ mDebugReportApi.scheduleTriggerDebugReport(
+ source, trigger, null, measurementDao, Type.TRIGGER_EVENT_REPORT_WINDOW_PASSED);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/noising/ImpressionNoiseUtil.java b/adservices/service-core/java/com/android/adservices/service/measurement/noising/ImpressionNoiseUtil.java
index 0a456919f..c83f608b6 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/noising/ImpressionNoiseUtil.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/noising/ImpressionNoiseUtil.java
@@ -29,72 +29,6 @@ import java.util.concurrent.ThreadLocalRandom;
*/
public final class ImpressionNoiseUtil {
- /**
- * This is used in the scenario where both app and web destinations are available with the
- * {@link com.android.adservices.service.measurement.Source} and the source is of {@link
- * com.android.adservices.service.measurement.Source.SourceType#EVENT} type and post-install
- * detection is enabled (cooldown window being available). It's a special case because in this
- * condition an extra early window is added only if install detection is enabled (install
- * cool-down window is available) and only app conversions are relevant in that window.
- *
- * <p>Reading guide - The outermost array signifies different states of reporting - one of them
- * will be picked at a time. The middle array holds reports in 1st and 2nd window, so there will
- * be either 0 elements (no conversions in either window), 1 element (a conversion report in one
- * of the windows) and 2 elements (conversions in both windows). The innermost array represents
- * a single report. 3 elements in the innermost array are trigger metadata (0 - trigger1 or 1 -
- * trigger2), window index (0 - window1, 1 - window2) and destination type (0 - app or 1 - web).
- *
- * <p>E.g. The element at index 5 is {{0, 1, 0}, {0, 1, 0}}, it means 2 conversions with trigger
- * metadata as 0 in window2 (1) of app destination type(0).
- */
- public static final int[][][] DUAL_DESTINATION_POST_INSTALL_FAKE_REPORT_CONFIG =
- new int[][][] {
- // window1 - no conversion, window 2 - no conversion
- {},
- // window1 - no conversion, window 2 - 1 conversion with metadata 0
- {{0, 1, 0}},
- {{0, 1, 1}},
- // window1 - no conversion, window 2 - 1 conversion with metadata 1
- {{1, 1, 0}},
- {{1, 1, 1}},
- // window1 - no conversion, window 2 - 2 conversions with metadata 0 and 0
- {{0, 1, 0}, {0, 1, 0}},
- {{0, 1, 0}, {0, 1, 1}},
- // window1 - no conversion, window 2 - 2 conversions with metadata 0 and 1
- {{0, 1, 0}, {1, 1, 0}},
- {{0, 1, 0}, {1, 1, 1}},
- {{0, 1, 1}, {1, 1, 0}},
- // window1 - no conversion, window 2 - 2 conversions with metadata 1 and 1
- {{1, 1, 0}, {1, 1, 0}},
- {{1, 1, 0}, {1, 1, 1}},
- // window1 - 1 app conversion with metadata 0, window 2 - no conversion
- {{0, 0, 0}},
- // window1 - 1 app conversion with metadata 1, window 2 - no conversion
- {{1, 0, 0}},
- // window1 - 2 conversions with metadata 0 and 0, window 2 - no conversion
- {{0, 0, 0}, {0, 0, 0}},
- // window1 - 2 app conversions with metadata 0 and 1, window 2 - no conversion
- {{0, 0, 0}, {1, 0, 0}},
- // window1 - 2 app conversions with metadata 1 and 1, window 2 - no conversion
- {{1, 0, 0}, {1, 0, 0}},
- // window1 - 1 app conversion with metadata 0, window 2 - 1 conversion with
- // metadata 0
- {{0, 0, 0}, {0, 1, 0}},
- {{0, 0, 0}, {0, 1, 1}},
- // window1 - 1 app conversion with metadata 0, window 2 - 1 conversion with
- // metadata 1
- {{0, 0, 0}, {1, 1, 0}},
- {{0, 0, 0}, {1, 1, 1}},
- // window1 - 1 app conversion with metadata 1, window 2 - 1 conversions with
- // metadata 0
- {{1, 0, 0}, {0, 1, 0}},
- {{1, 0, 0}, {0, 1, 1}},
- // window1 - 1 app conversion with metadata 1, window 2 - 1 conversions with
- // metadata 1
- {{1, 0, 0}, {1, 1, 0}},
- {{1, 0, 0}, {1, 1, 1}}
- };
-
private ImpressionNoiseUtil() {}
/**
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/noising/SourceNoiseHandler.java b/adservices/service-core/java/com/android/adservices/service/measurement/noising/SourceNoiseHandler.java
index 2c28fa51e..8897662a9 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/noising/SourceNoiseHandler.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/noising/SourceNoiseHandler.java
@@ -30,11 +30,9 @@ import com.google.common.collect.ImmutableList;
import java.math.BigDecimal;
import java.math.RoundingMode;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
-import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
@@ -85,33 +83,24 @@ public class SourceNoiseHandler {
List<Source.FakeReport> fakeReports;
TriggerSpecs triggerSpecs = source.getTriggerSpecs();
if (triggerSpecs == null) {
- if (isVtcDualDestinationModeWithPostInstallEnabled(source)) {
- // Source is 'EVENT' type, both app and web destination are set and install
- // exclusivity
- // window is provided. Pick one of the static reporting states randomly.
- fakeReports = generateVtcDualDestinationPostInstallFakeReports(source);
- } else {
- // There will at least be one (app or web) destination available
- ImpressionNoiseParams noiseParams = getImpressionNoiseParams(source);
- fakeReports =
- ImpressionNoiseUtil.selectRandomStateAndGenerateReportConfigs(
- noiseParams, rand)
- .stream()
- .map(
- reportConfig ->
- new Source.FakeReport(
- new UnsignedLong(
- Long.valueOf(reportConfig[0])),
- mEventReportWindowCalcDelegate
- .getReportingTimeForNoising(
- source,
- reportConfig[1],
- isInstallDetectionEnabled(
- source)),
- resolveFakeReportDestinations(
- source, reportConfig[2])))
- .collect(Collectors.toList());
- }
+ // There will at least be one (app or web) destination available
+ ImpressionNoiseParams noiseParams = getImpressionNoiseParams(source);
+ fakeReports =
+ ImpressionNoiseUtil.selectRandomStateAndGenerateReportConfigs(
+ noiseParams, rand)
+ .stream()
+ .map(
+ reportConfig ->
+ new Source.FakeReport(
+ new UnsignedLong(
+ Long.valueOf(reportConfig[0])),
+ mEventReportWindowCalcDelegate
+ .getReportingTimeForNoising(
+ source,
+ reportConfig[1]),
+ resolveFakeReportDestinations(
+ source, reportConfig[2])))
+ .collect(Collectors.toList());
} else {
int destinationTypeMultiplier = source.getDestinationTypeMultiplier(mFlags);
List<int[]> fakeReportConfigs =
@@ -144,51 +133,11 @@ public class SourceNoiseHandler {
/** @return Probability of selecting random state for attribution */
public double getRandomAttributionProbability(@NonNull Source source) {
- if (source.getTriggerSpecs() != null
- || mFlags.getMeasurementEnableConfigurableEventReportingWindows()
- || mFlags.getMeasurementEnableVtcConfigurableMaxEventReports()
- || (mFlags.getMeasurementFlexLiteApiEnabled()
- && (source.getMaxEventLevelReports() != null
- || source.hasManualEventReportWindows()))) {
- return convertToDoubleAndLimitDecimal(source.getFlipProbability(mFlags));
- }
- // TODO(b/290117352): Remove Hardcoded noise values
-
- // Both destinations are set and install attribution is supported
- if (!shouldReportCoarseDestinations(source)
- && source.hasWebDestinations()
- && isInstallDetectionEnabled(source)) {
- return source.getSourceType() == Source.SourceType.EVENT
- ? convertToDoubleAndLimitDecimal(
- mFlags.getMeasurementInstallAttrDualDestinationEventNoiseProbability())
- : convertToDoubleAndLimitDecimal(
- mFlags.getMeasurementInstallAttrDualDestinationNavigationNoiseProbability());
- }
-
- // Both destinations are set but install attribution isn't supported
- if (!shouldReportCoarseDestinations(source)
- && source.hasAppDestinations()
- && source.hasWebDestinations()) {
- return source.getSourceType() == Source.SourceType.EVENT
- ? convertToDoubleAndLimitDecimal(
- mFlags.getMeasurementDualDestinationEventNoiseProbability())
- : convertToDoubleAndLimitDecimal(
- mFlags.getMeasurementDualDestinationNavigationNoiseProbability());
- }
-
- // App destination is set and install attribution is supported
- if (isInstallDetectionEnabled(source)) {
- return source.getSourceType() == Source.SourceType.EVENT
- ? convertToDoubleAndLimitDecimal(
- mFlags.getMeasurementInstallAttrEventNoiseProbability())
- : convertToDoubleAndLimitDecimal(
- mFlags.getMeasurementInstallAttrNavigationNoiseProbability());
- }
-
- // One of the destinations is available without install attribution support
- return source.getSourceType() == Source.SourceType.EVENT
- ? convertToDoubleAndLimitDecimal(mFlags.getMeasurementEventNoiseProbability())
- : convertToDoubleAndLimitDecimal(mFlags.getMeasurementNavigationNoiseProbability());
+ // Methods on Source and EventReportWindowCalcDelegate that calculate flip probability for
+ // the source rely on reporting windows and max reports that are obtained with consideration
+ // to install-state and its interaction with configurable report windows and configurable
+ // max reports.
+ return convertToDoubleAndLimitDecimal(source.getFlipProbability(mFlags));
}
private double convertToDoubleAndLimitDecimal(double probability) {
@@ -197,15 +146,6 @@ public class SourceNoiseHandler {
.doubleValue();
}
- private boolean isVtcDualDestinationModeWithPostInstallEnabled(Source source) {
- return !shouldReportCoarseDestinations(source)
- && !source.hasManualEventReportWindows()
- && source.getMaxEventLevelReports() == null
- && source.getSourceType() == Source.SourceType.EVENT
- && source.hasWebDestinations()
- && isInstallDetectionEnabled(source);
- }
-
/**
* Either both app and web destinations can be available or one of them will be available. When
* both destinations are available, we double the number of states at noise generation to be
@@ -216,7 +156,7 @@ public class SourceNoiseHandler {
* @return app or web destination {@link Uri}
*/
private List<Uri> resolveFakeReportDestinations(Source source, int destinationIdentifier) {
- if (shouldReportCoarseDestinations(source)) {
+ if (source.shouldReportCoarseDestinations(mFlags)) {
ImmutableList.Builder<Uri> destinations = new ImmutableList.Builder<>();
Optional.ofNullable(source.getAppDestinations()).ifPresent(destinations::addAll);
Optional.ofNullable(source.getWebDestinations()).ifPresent(destinations::addAll);
@@ -234,44 +174,13 @@ public class SourceNoiseHandler {
: source.getWebDestinations();
}
- /** Check if install detection is enabled for the source. */
- public static boolean isInstallDetectionEnabled(@NonNull Source source) {
- return source.getInstallCooldownWindow() > 0 && source.hasAppDestinations();
- }
-
- private boolean shouldReportCoarseDestinations(Source source) {
- return mFlags.getMeasurementEnableCoarseEventReportDestinations()
- && source.hasCoarseEventReportDestinations();
- }
-
- private List<Source.FakeReport> generateVtcDualDestinationPostInstallFakeReports(
- Source source) {
- int[][][] fakeReportsConfig =
- ImpressionNoiseUtil.DUAL_DESTINATION_POST_INSTALL_FAKE_REPORT_CONFIG;
- int randomIndex = new Random().nextInt(fakeReportsConfig.length);
- int[][] reportsConfig = fakeReportsConfig[randomIndex];
- return Arrays.stream(reportsConfig)
- .map(
- reportConfig ->
- new Source.FakeReport(
- new UnsignedLong(Long.valueOf(reportConfig[0])),
- mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- source,
- /* window index */ reportConfig[1],
- isInstallDetectionEnabled(source)),
- resolveFakeReportDestinations(source, reportConfig[2])))
- .collect(Collectors.toList());
- }
-
@VisibleForTesting
ImpressionNoiseParams getImpressionNoiseParams(Source source) {
int destinationTypeMultiplier = source.getDestinationTypeMultiplier(mFlags);
return new ImpressionNoiseParams(
- mEventReportWindowCalcDelegate.getMaxReportCount(
- source, isInstallDetectionEnabled(source)),
+ mEventReportWindowCalcDelegate.getMaxReportCount(source),
source.getTriggerDataCardinality(),
- mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- source, isInstallDetectionEnabled(source)),
+ mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(source),
destinationTypeMultiplier);
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRedirect.java b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRedirect.java
index 1c76ade57..6106b1a52 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRedirect.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRedirect.java
@@ -18,46 +18,31 @@ package com.android.adservices.service.measurement.registration;
import android.net.Uri;
-import java.util.ArrayList;
-import java.util.List;
-
-/** Wrapper for a list of redirect Uris and a redirect type */
public class AsyncRedirect {
- private final List<Uri> mLocationRedirects;
- private final List<Uri> mListRedirects;
-
- public AsyncRedirect() {
- mLocationRedirects = new ArrayList<>();
- mListRedirects = new ArrayList<>();
+ public enum RedirectBehavior {
+ /** Do not modify redirect path */
+ AS_IS,
+ /** Prepend well known path prefix to path of redirect url for Location type redirects */
+ LOCATION_TO_WELL_KNOWN,
}
- public AsyncRedirect(List<Uri> locationRedirects, List<Uri> listRedirects) {
- mLocationRedirects = locationRedirects;
- mListRedirects = listRedirects;
- }
+ private final Uri mUri;
+ private final RedirectBehavior mRedirectBehavior;
- /** The list the redirect Uris */
- public List<Uri> getRedirects() {
- List<Uri> allRedirects = new ArrayList<>(mListRedirects);
- allRedirects.addAll(mLocationRedirects);
- return allRedirects;
+ public AsyncRedirect(Uri uri, RedirectBehavior redirectBehavior) {
+ mUri = uri;
+ mRedirectBehavior = redirectBehavior;
}
- /** Get list by redirect type */
- public List<Uri> getRedirectsByType(AsyncRegistration.RedirectType redirectType) {
- if (redirectType == AsyncRegistration.RedirectType.LOCATION) {
- return new ArrayList<>(mLocationRedirects);
- } else {
- return new ArrayList<>(mListRedirects);
- }
+ public Uri getUri() {
+ return mUri;
}
- /** Add to the list the redirect Uris based on type */
- public void addToRedirects(AsyncRegistration.RedirectType redirectType, List<Uri> uris) {
- if (redirectType == AsyncRegistration.RedirectType.LOCATION) {
- mLocationRedirects.addAll(uris);
- } else {
- mListRedirects.addAll(uris);
- }
+ public RedirectBehavior getRedirectBehavior() {
+ return mRedirectBehavior;
}
+
+
+
+
}
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRedirects.java b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRedirects.java
new file mode 100644
index 000000000..d05cb2903
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRedirects.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 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.service.measurement.registration;
+
+import android.net.Uri;
+
+import com.android.adservices.service.Flags;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/** Class for handling redirects */
+public class AsyncRedirects {
+ public static final String HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG =
+ "Attribution-Reporting-Redirect-Config";
+ public static final String REDIRECT_302_TO_WELL_KNOWN = "redirect-302-to-well-known";
+ public static final String WELL_KNOWN_PATH_SEGMENT =
+ ".well-known/attribution-reporting/register-redirect";
+ public static final String WELL_KNOWN_QUERY_PARAM = "302_url";
+ public static final String REDIRECT_LIST_HEADER_KEY = "Attribution-Reporting-Redirect";
+ public static final String REDIRECT_LOCATION_HEADER_KEY = "Location";
+ private final List<AsyncRedirect> mLocationRedirects;
+ private final List<AsyncRedirect> mListRedirects;
+
+ public AsyncRedirects() {
+ mLocationRedirects = new ArrayList<>();
+ mListRedirects = new ArrayList<>();
+ }
+
+ /** Return flattened list of {@link AsyncRedirect} */
+ public List<AsyncRedirect> getRedirects() {
+ List<AsyncRedirect> allRedirects = new ArrayList<>(mListRedirects);
+ allRedirects.addAll(mLocationRedirects);
+
+ return allRedirects;
+ }
+
+ /** Get list of {@link AsyncRedirect} by redirect type */
+ public List<AsyncRedirect> getRedirectsByType(AsyncRegistration.RedirectType redirectType) {
+ if (redirectType == AsyncRegistration.RedirectType.LOCATION) {
+ return new ArrayList<>(mLocationRedirects);
+ } else {
+ return new ArrayList<>(mListRedirects);
+ }
+ }
+
+ /** Process redirects based on the given headers */
+ public void configure(
+ Map<String, List<String>> headers, Flags flags, AsyncRegistration parentRegistration) {
+ if (!parentRegistration.shouldProcessRedirects()) {
+ return;
+ }
+
+ Map<AsyncRegistration.RedirectType, List<Uri>> urisByType =
+ FetcherUtil.parseRedirects(headers);
+
+ for (Uri locationRedirectUri : urisByType.get(AsyncRegistration.RedirectType.LOCATION)) {
+ if (shouldRedirect302ToWellKnown(headers, flags, parentRegistration)) {
+ mLocationRedirects.add(
+ new AsyncRedirect(
+ getLocationRedirectToWellKnownUri(locationRedirectUri),
+ AsyncRedirect.RedirectBehavior.LOCATION_TO_WELL_KNOWN));
+ } else {
+ mLocationRedirects.add(
+ new AsyncRedirect(
+ locationRedirectUri, AsyncRedirect.RedirectBehavior.AS_IS));
+ }
+ }
+
+ for (Uri listRedirectUri : urisByType.get(AsyncRegistration.RedirectType.LIST)) {
+ mListRedirects.add(
+ new AsyncRedirect(listRedirectUri, AsyncRedirect.RedirectBehavior.AS_IS));
+ }
+ }
+
+ private static boolean shouldRedirect302ToWellKnown(
+ Map<String, List<String>> headers, Flags flags, AsyncRegistration parentRegistration) {
+ boolean isParentRegistrationRedirectsToWellKnown =
+ AsyncRedirect.RedirectBehavior.LOCATION_TO_WELL_KNOWN.equals(
+ parentRegistration.getRedirectBehavior());
+
+ return flags.getMeasurementEnableRedirectToWellKnownPath()
+ && (isParentRegistrationRedirectsToWellKnown
+ || isRedirect302ToWellKnownPath(headers));
+ }
+
+ /**
+ * Return true if the given headers indicate redirects should prepend well known prefix to the
+ * path.
+ */
+ private static boolean isRedirect302ToWellKnownPath(Map<String, List<String>> headers) {
+ if (!headers.containsKey(HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG)) {
+ return false;
+ }
+ List<String> config = headers.get(HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG);
+ if (config == null || config.size() != 1) {
+ return false;
+ }
+
+ return config.get(0).equalsIgnoreCase(REDIRECT_302_TO_WELL_KNOWN);
+ }
+
+ private Uri getLocationRedirectToWellKnownUri(Uri redirectUri) {
+ return redirectUri
+ .buildUpon()
+ .encodedPath(WELL_KNOWN_PATH_SEGMENT)
+ .clearQuery()
+ .appendQueryParameter(WELL_KNOWN_QUERY_PARAM, redirectUri.toString())
+ .build();
+ }
+}
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistration.java b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistration.java
index 98c95bfe0..ade38df69 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistration.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistration.java
@@ -51,9 +51,9 @@ public class AsyncRegistration {
private final boolean mDebugKeyAllowed;
private final boolean mAdIdPermission;
@Nullable private String mRegistrationId;
-
@Nullable private final String mPlatformAdId;
@Nullable private String mPostBody;
+ private final AsyncRedirect.RedirectBehavior mRedirectBehavior;
public enum RedirectType {
LOCATION,
@@ -77,6 +77,7 @@ public class AsyncRegistration {
mRegistrationId = builder.mRegistrationId;
mPlatformAdId = builder.mPlatformAdId;
mPostBody = builder.mPostBody;
+ mRedirectBehavior = builder.mRedirectBehavior;
}
@Override
@@ -99,7 +100,8 @@ public class AsyncRegistration {
&& mType == that.mType
&& Objects.equals(mRegistrationId, that.mRegistrationId)
&& mPlatformAdId.equals(that.mPlatformAdId)
- && Objects.equals(mPostBody, that.mPostBody);
+ && Objects.equals(mPostBody, that.mPostBody)
+ && Objects.equals(mRedirectBehavior, that.mRedirectBehavior);
}
@Override
@@ -120,7 +122,8 @@ public class AsyncRegistration {
mAdIdPermission,
mRegistrationId,
mPlatformAdId,
- mPostBody);
+ mPostBody,
+ mRedirectBehavior);
}
/** Unique identifier for the {@link AsyncRegistration}. */
@@ -214,6 +217,11 @@ public class AsyncRegistration {
return mPostBody;
}
+ /** Return the configuration for redirect behavior. */
+ public AsyncRedirect.RedirectBehavior getRedirectBehavior() {
+ return mRedirectBehavior;
+ }
+
/** Increments the retry count of the current record. */
public void incrementRetryCount() {
++mRetryCount;
@@ -260,9 +268,9 @@ public class AsyncRegistration {
private boolean mDebugKeyAllowed;
private boolean mAdIdPermission;
@Nullable private String mRegistrationId;
-
@Nullable private String mPlatformAdId;
@Nullable private String mPostBody;
+ private AsyncRedirect.RedirectBehavior mRedirectBehavior;
/** See {@link AsyncRegistration#getId()}. */
@NonNull
@@ -385,6 +393,12 @@ public class AsyncRegistration {
return this;
}
+ /** See {@link AsyncRegistration#getRedirectBehavior()}. */
+ public Builder setRedirectBehavior(AsyncRedirect.RedirectBehavior redirectBehavior) {
+ mRedirectBehavior = redirectBehavior;
+ return this;
+ }
+
/** Build the {@link AsyncRegistration}. */
@NonNull
public AsyncRegistration build() {
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunner.java b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunner.java
index 207f8b3f0..41f66aea2 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunner.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunner.java
@@ -210,10 +210,11 @@ public class AsyncRegistrationQueueRunner {
AsyncRegistration asyncRegistration, Set<Uri> failedOrigins) {
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
asyncFetchStatus.setRetryCount(Long.valueOf(asyncRegistration.getRetryCount()).intValue());
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
long startTime = asyncRegistration.getRequestTime();
Optional<Source> resultSource =
- mAsyncSourceFetcher.fetchSource(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mAsyncSourceFetcher.fetchSource(
+ asyncRegistration, asyncFetchStatus, asyncRedirects);
long endTime = System.currentTimeMillis();
asyncFetchStatus.setRegistrationDelay(endTime - startTime);
@@ -225,7 +226,7 @@ public class AsyncRegistrationQueueRunner {
storeSource(resultSource.get(), asyncRegistration, dao);
}
handleSuccess(
- asyncRegistration, asyncFetchStatus, asyncRedirect, dao);
+ asyncRegistration, asyncFetchStatus, asyncRedirects, dao);
} else {
handleFailure(
asyncRegistration, asyncFetchStatus, failedOrigins, dao);
@@ -273,10 +274,11 @@ public class AsyncRegistrationQueueRunner {
AsyncRegistration asyncRegistration, Set<Uri> failedOrigins) {
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
asyncFetchStatus.setRetryCount(Long.valueOf(asyncRegistration.getRetryCount()).intValue());
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
long startTime = asyncRegistration.getRequestTime();
- Optional<Trigger> resultTrigger = mAsyncTriggerFetcher.fetchTrigger(
- asyncRegistration, asyncFetchStatus, asyncRedirect);
+ Optional<Trigger> resultTrigger =
+ mAsyncTriggerFetcher.fetchTrigger(
+ asyncRegistration, asyncFetchStatus, asyncRedirects);
long endTime = System.currentTimeMillis();
asyncFetchStatus.setRegistrationDelay(endTime - startTime);
@@ -288,7 +290,7 @@ public class AsyncRegistrationQueueRunner {
storeTrigger(resultTrigger.get(), dao);
}
handleSuccess(
- asyncRegistration, asyncFetchStatus, asyncRedirect, dao);
+ asyncRegistration, asyncFetchStatus, asyncRedirects, dao);
} else {
handleFailure(
asyncRegistration, asyncFetchStatus, failedOrigins, dao);
@@ -583,11 +585,11 @@ public class AsyncRegistrationQueueRunner {
< FlagsFactory.getFlags().getMeasurementMaxTriggersPerDestination();
}
- private static AsyncRegistration createAsyncRegistrationFromRedirect(
- AsyncRegistration asyncRegistration, Uri redirectUri) {
+ private AsyncRegistration createAsyncRegistrationFromRedirect(
+ AsyncRegistration asyncRegistration, AsyncRedirect asyncRedirect) {
return new AsyncRegistration.Builder()
.setId(UUID.randomUUID().toString())
- .setRegistrationUri(redirectUri)
+ .setRegistrationUri(asyncRedirect.getUri())
.setWebDestination(asyncRegistration.getWebDestination())
.setOsDestination(asyncRegistration.getOsDestination())
.setRegistrant(asyncRegistration.getRegistrant())
@@ -600,6 +602,7 @@ public class AsyncRegistrationQueueRunner {
.setDebugKeyAllowed(asyncRegistration.getDebugKeyAllowed())
.setAdIdPermission(asyncRegistration.hasAdIdPermission())
.setRegistrationId(asyncRegistration.getRegistrationId())
+ .setRedirectBehavior(asyncRedirect.getRedirectBehavior())
.build();
}
@@ -690,14 +693,14 @@ public class AsyncRegistrationQueueRunner {
private void handleSuccess(
AsyncRegistration asyncRegistration,
AsyncFetchStatus asyncFetchStatus,
- AsyncRedirect asyncRedirect,
+ AsyncRedirects asyncRedirects,
IMeasurementDao dao)
throws DatastoreException {
// deleteAsyncRegistration will throw an exception & rollback the transaction if the record
// is already deleted. This can happen if both fallback & regular job are running at the
// same time or if deletion job deletes the records.
dao.deleteAsyncRegistration(asyncRegistration.getId());
- if (asyncRedirect.getRedirects().isEmpty()) {
+ if (asyncRedirects.getRedirects().isEmpty()) {
return;
}
int maxRedirects = FlagsFactory.getFlags().getMeasurementMaxRegistrationRedirects();
@@ -706,16 +709,17 @@ public class AsyncRegistrationQueueRunner {
asyncRegistration.getRegistrationId(),
DataType.REGISTRATION_REDIRECT_COUNT);
int currentCount = keyValueData.getRegistrationRedirectCount();
- if (currentCount == maxRedirects) {
+ if (currentCount >= maxRedirects) {
asyncFetchStatus.setRedirectError(true);
return;
}
- for (Uri uri : asyncRedirect.getRedirects()) {
+
+ for (AsyncRedirect asyncRedirect : asyncRedirects.getRedirects()) {
if (currentCount >= maxRedirects) {
break;
}
dao.insertAsyncRegistration(
- createAsyncRegistrationFromRedirect(asyncRegistration, uri));
+ createAsyncRegistrationFromRedirect(asyncRegistration, asyncRedirect));
currentCount++;
}
keyValueData.setRegistrationRedirectCount(currentCount);
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncSourceFetcher.java b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncSourceFetcher.java
index c1f3a30c7..26157a01b 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncSourceFetcher.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncSourceFetcher.java
@@ -492,8 +492,9 @@ public class AsyncSourceFetcher {
Source.SourceType sourceType,
int maxEventLevelReports,
Source.TriggerDataMatching triggerDataMatching) {
- List<Pair<Long, Long>> parsedEventReportWindows = Source.getOrDefaultEventReportWindows(
- eventReportWindows, sourceType, expiry, mFlags);
+ List<Pair<Long, Long>> parsedEventReportWindows =
+ Source.getOrDefaultEventReportWindowsForFlex(
+ eventReportWindows, sourceType, expiry, mFlags);
long defaultStart = parsedEventReportWindows.get(0).first;
List<Long> defaultEnds =
parsedEventReportWindows.stream().map((x) -> x.second).collect(Collectors.toList());
@@ -799,7 +800,7 @@ public class AsyncSourceFetcher {
public Optional<Source> fetchSource(
AsyncRegistration asyncRegistration,
AsyncFetchStatus asyncFetchStatus,
- AsyncRedirect asyncRedirect) {
+ AsyncRedirects asyncRedirects) {
HttpURLConnection urlConnection = null;
Map<String, List<String>> headers;
if (!asyncRegistration.getRegistrationUri().getScheme().equalsIgnoreCase("https")) {
@@ -852,9 +853,7 @@ public class AsyncSourceFetcher {
}
}
- if (asyncRegistration.shouldProcessRedirects()) {
- FetcherUtil.parseRedirects(headers).forEach(asyncRedirect::addToRedirects);
- }
+ asyncRedirects.configure(headers, mFlags, asyncRegistration);
if (!isSourceHeaderPresent(headers)) {
asyncFetchStatus.setEntityStatus(AsyncFetchStatus.EntityStatus.HEADER_MISSING);
@@ -864,7 +863,9 @@ public class AsyncSourceFetcher {
Optional<String> enrollmentId =
mFlags.isDisableMeasurementEnrollmentCheck()
- ? Optional.of(Enrollment.FAKE_ENROLLMENT)
+ ? WebAddresses.topPrivateDomainAndScheme(
+ asyncRegistration.getRegistrationUri())
+ .map(Uri::toString)
: Enrollment.getValidEnrollmentId(
asyncRegistration.getRegistrationUri(),
asyncRegistration.getRegistrant().getAuthority(),
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncTriggerFetcher.java b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncTriggerFetcher.java
index 9fd56f6c6..d7d5e9e95 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncTriggerFetcher.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/registration/AsyncTriggerFetcher.java
@@ -308,7 +308,7 @@ public class AsyncTriggerFetcher {
public Optional<Trigger> fetchTrigger(
AsyncRegistration asyncRegistration,
AsyncFetchStatus asyncFetchStatus,
- AsyncRedirect asyncRedirect) {
+ AsyncRedirects asyncRedirects) {
HttpURLConnection urlConnection = null;
Map<String, List<String>> headers;
if (!asyncRegistration.getRegistrationUri().getScheme().equalsIgnoreCase("https")) {
@@ -347,9 +347,7 @@ public class AsyncTriggerFetcher {
}
}
- if (asyncRegistration.shouldProcessRedirects()) {
- FetcherUtil.parseRedirects(headers).forEach(asyncRedirect::addToRedirects);
- }
+ asyncRedirects.configure(headers, mFlags, asyncRegistration);
if (!isTriggerHeaderPresent(headers)) {
asyncFetchStatus.setEntityStatus(AsyncFetchStatus.EntityStatus.HEADER_MISSING);
@@ -359,7 +357,9 @@ public class AsyncTriggerFetcher {
Optional<String> enrollmentId =
mFlags.isDisableMeasurementEnrollmentCheck()
- ? Optional.of(Enrollment.FAKE_ENROLLMENT)
+ ? WebAddresses.topPrivateDomainAndScheme(
+ asyncRegistration.getRegistrationUri())
+ .map(Uri::toString)
: Enrollment.getValidEnrollmentId(
asyncRegistration.getRegistrationUri(),
asyncRegistration.getRegistrant().getAuthority(),
@@ -627,8 +627,7 @@ public class AsyncTriggerFetcher {
JSONArray aggregateDeduplicationKeys) throws JSONException {
JSONArray validAggregateDeduplicationKeys = new JSONArray();
if (aggregateDeduplicationKeys.length()
- > FlagsFactory.getFlags()
- .getMeasurementMaxAggregateDeduplicationKeysPerRegistration()) {
+ > mFlags.getMeasurementMaxAggregateDeduplicationKeysPerRegistration()) {
LoggerFactory.getMeasurementLogger()
.d(
"Aggregate deduplication keys have more keys than permitted. %s",
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistration.java b/adservices/service-core/java/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistration.java
index 0c8a801b0..f6a7bdfb5 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistration.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistration.java
@@ -255,6 +255,7 @@ public class EnqueueAsyncRegistration {
.setPlatformAdId(platformAdIdValue)
.setPostBody(postBody)
.setRegistrationId(registrationId)
+ .setRedirectBehavior(AsyncRedirect.RedirectBehavior.AS_IS)
.build();
dao.insertAsyncRegistration(asyncRegistration);
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/registration/FetcherUtil.java b/adservices/service-core/java/com/android/adservices/service/measurement/registration/FetcherUtil.java
index d5d268e7c..50c64886d 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/registration/FetcherUtil.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/registration/FetcherUtil.java
@@ -48,15 +48,12 @@ import java.util.regex.Pattern;
* @hide
*/
class FetcherUtil {
- static final String REDIRECT_LIST_HEADER_KEY = "Attribution-Reporting-Redirect";
- static final String REDIRECT_LOCATION_HEADER_KEY = "Location";
static final Pattern HEX_PATTERN = Pattern.compile("\\p{XDigit}+");
/**
* Determine all redirects.
*
- * <p>Generates a list of: (url, allows_regular_redirects) tuples. Returns true if all steps
- * succeed. Returns false if there are any failures.
+ * <p>Generates a map of: (redirectType, List&lt;Uri&gt;)
*/
static Map<AsyncRegistration.RedirectType, List<Uri>> parseRedirects(
@NonNull Map<String, List<String>> headers) {
@@ -304,7 +301,7 @@ class FetcherUtil {
private static List<Uri> parseListRedirects(Map<String, List<String>> headers) {
List<Uri> redirects = new ArrayList<>();
- List<String> field = headers.get(REDIRECT_LIST_HEADER_KEY);
+ List<String> field = headers.get(AsyncRedirects.REDIRECT_LIST_HEADER_KEY);
int maxRedirects = FlagsFactory.getFlags().getMeasurementMaxRegistrationRedirects();
if (field != null) {
for (int i = 0; i < Math.min(field.size(), maxRedirects); i++) {
@@ -316,7 +313,7 @@ class FetcherUtil {
private static List<Uri> parseLocationRedirects(Map<String, List<String>> headers) {
List<Uri> redirects = new ArrayList<>();
- List<String> field = headers.get(REDIRECT_LOCATION_HEADER_KEY);
+ List<String> field = headers.get(AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY);
if (field != null && !field.isEmpty()) {
redirects.add(Uri.parse(field.get(0)));
if (field.size() > 1) {
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java
index a4d197107..0498d4a85 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java
@@ -50,7 +50,8 @@ public class AggregateReportBody {
private static final String API_NAME = "attribution-reporting";
- private interface PayloadBodyKeys {
+ @VisibleForTesting
+ interface PayloadBodyKeys {
String SHARED_INFO = "shared_info";
String AGGREGATION_SERVICE_PAYLOADS = "aggregation_service_payloads";
String SOURCE_DEBUG_KEY = "source_debug_key";
@@ -64,7 +65,8 @@ public class AggregateReportBody {
String DEBUG_CLEARTEXT_PAYLOAD = "debug_cleartext_payload";
}
- private interface SharedInfoKeys {
+ @VisibleForTesting
+ interface SharedInfoKeys {
String API_NAME = "api";
String ATTRIBUTION_DESTINATION = "attribution_destination";
String REPORT_ID = "report_id";
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java
index 4367ee1b8..849ec8164 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java
@@ -16,7 +16,10 @@
package com.android.adservices.service.measurement.reporting;
-import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_ENCRYPTION_ERROR;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_NETWORK_ERROR;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_PARSING_ERROR;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_UNKNOWN_ERROR;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_MESUREMENT_REPORTS_UPLOADED;
@@ -289,7 +292,7 @@ public class AggregateReportingJobHandler {
// TODO(b/298330312): Change to defined error codes
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_NETWORK_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
return AdServicesStatusUtils.STATUS_IO_ERROR;
} catch (JSONException e) {
@@ -299,7 +302,7 @@ public class AggregateReportingJobHandler {
// TODO(b/298330312): Change to defined error codes
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_PARSING_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
if (mFlags.getMeasurementEnableReportDeletionOnUnrecoverableException()) {
// Unrecoverable state - delete the report.
@@ -324,7 +327,7 @@ public class AggregateReportingJobHandler {
// TODO(b/298330312): Change to defined error codes
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_ENCRYPTION_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
if (mFlags.getMeasurementEnableReportingJobsThrowCryptoException()
&& ThreadLocalRandom.current().nextFloat()
@@ -338,7 +341,7 @@ public class AggregateReportingJobHandler {
// TODO(b/298330312): Change to defined error codes
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_UNKNOWN_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
if (mFlags.getMeasurementEnableReportingJobsThrowUnaccountedException()
&& ThreadLocalRandom.current().nextFloat()
@@ -371,8 +374,7 @@ public class AggregateReportingJobHandler {
.setTriggerDebugKey(aggregateReport.getTriggerDebugKey())
.setAggregationCoordinatorOrigin(aggregateReport.getAggregationCoordinatorOrigin())
.setDebugMode(
- mIsDebugInstance
- && aggregateReport.getSourceDebugKey() != null
+ aggregateReport.getSourceDebugKey() != null
&& aggregateReport.getTriggerDebugKey() != null
? "enabled"
: null)
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportApi.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportApi.java
index c4a6d7201..778570c24 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportApi.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportApi.java
@@ -80,6 +80,7 @@ public class DebugReportApi {
String TRIGGER_UNKNOWN_ERROR = "trigger-unknown-error";
String TRIGGER_AGGREGATE_STORAGE_LIMIT = "trigger-aggregate-storage-limit";
String TRIGGER_AGGREGATE_EXCESSIVE_REPORTS = "trigger-aggregate-excessive-reports";
+ String TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED = "trigger-event-report-window-not-started";
}
/** Defines different verbose debug report body parameters. */
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportingJobHandler.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportingJobHandler.java
index 0650f67e9..4391b3725 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportingJobHandler.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/DebugReportingJobHandler.java
@@ -16,7 +16,9 @@
package com.android.adservices.service.measurement.reporting;
-import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_NETWORK_ERROR;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_PARSING_ERROR;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_UNKNOWN_ERROR;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_MESUREMENT_REPORTS_UPLOADED;
@@ -184,7 +186,7 @@ public class DebugReportingJobHandler {
.d(e, "Network error occurred when attempting to deliver debug report.");
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_NETWORK_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
reportingStatus.setFailureStatus(ReportingStatus.FailureStatus.NETWORK);
// TODO(b/298330312): Change to defined error codes
@@ -195,7 +197,7 @@ public class DebugReportingJobHandler {
// TODO(b/298330312): Change to defined error codes
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_PARSING_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
reportingStatus.setFailureStatus(ReportingStatus.FailureStatus.SERIALIZATION_ERROR);
if (mFlags.getMeasurementEnableReportDeletionOnUnrecoverableException()) {
@@ -216,7 +218,7 @@ public class DebugReportingJobHandler {
// TODO(b/298330312): Change to defined error codes
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_UNKNOWN_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
reportingStatus.setFailureStatus(ReportingStatus.FailureStatus.UNKNOWN);
if (mFlags.getMeasurementEnableReportingJobsThrowUnaccountedException()
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegate.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegate.java
index 9d7564c43..93f791385 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegate.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegate.java
@@ -54,36 +54,42 @@ public class EventReportWindowCalcDelegate {
}
/**
- * Max reports count based on conversion destination type and installation state.
+ * Max reports count given the Source object.
*
- * @param isInstallCase is app installed
+ * @param source the Source object
* @return maximum number of reports allowed
*/
- public int getMaxReportCount(@NonNull Source source, boolean isInstallCase) {
+ public int getMaxReportCount(Source source) {
+ return getMaxReportCount(source, source.isInstallDetectionEnabled());
+ }
+
+ /**
+ * Max reports count based on conversion destination type.
+ *
+ * @param source the Source object
+ * @param destinationType destination type
+ * @return maximum number of reports allowed
+ */
+ public int getMaxReportCount(@NonNull Source source, @EventSurfaceType int destinationType) {
+ return getMaxReportCount(source, isInstallCase(source, destinationType));
+ }
+
+ private int getMaxReportCount(@NonNull Source source, boolean isInstallCase) {
// TODO(b/290101531): Cleanup flags
if (mFlags.getMeasurementFlexLiteApiEnabled() && source.getMaxEventLevelReports() != null) {
return source.getMaxEventLevelReports();
}
- if (source.getSourceType() == Source.SourceType.EVENT
- && mFlags.getMeasurementEnableVtcConfigurableMaxEventReports()) {
- // Max VTC event reports are configurable
- int configuredMaxReports = mFlags.getMeasurementVtcConfigurableMaxEventReportsCount();
+
+ if (source.getSourceType() == Source.SourceType.EVENT) {
// Additional report essentially for first open + 1 post install conversion. If there
// is already more than 1 report allowed, no need to have that additional report.
- if (isInstallCase && configuredMaxReports == PrivacyParams.EVENT_SOURCE_MAX_REPORTS) {
+ if (isInstallCase && !source.hasWebDestinations() && isDefaultConfiguredVtc()) {
return PrivacyParams.INSTALL_ATTR_EVENT_SOURCE_MAX_REPORTS;
}
- return configuredMaxReports;
+ return mFlags.getMeasurementVtcConfigurableMaxEventReportsCount();
}
- if (isInstallCase) {
- return source.getSourceType() == Source.SourceType.EVENT
- ? PrivacyParams.INSTALL_ATTR_EVENT_SOURCE_MAX_REPORTS
- : PrivacyParams.INSTALL_ATTR_NAVIGATION_SOURCE_MAX_REPORTS;
- }
- return source.getSourceType() == Source.SourceType.EVENT
- ? PrivacyParams.EVENT_SOURCE_MAX_REPORTS
- : PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS;
+ return PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS;
}
/**
@@ -100,18 +106,14 @@ public class EventReportWindowCalcDelegate {
// Cases where source could have both web and app destinations, there if the trigger
// destination is an app, and it was installed, then installState should be considered true.
- boolean isAppInstalled = isAppInstalled(source, destinationType);
- List<Pair<Long, Long>> earlyReportingWindows =
- getEarlyReportingWindows(source, isAppInstalled);
- for (Pair<Long, Long> window : earlyReportingWindows) {
+ List<Pair<Long, Long>> reportingWindows =
+ getEffectiveReportingWindows(source, isInstallCase(source, destinationType));
+ for (Pair<Long, Long> window : reportingWindows) {
if (isWithinWindow(triggerTime, window)) {
return window.second + mFlags.getMeasurementMinEventReportDelayMillis();
}
}
- Pair<Long, Long> finalWindow = getFinalReportingWindow(source, earlyReportingWindows);
- if (isWithinWindow(triggerTime, finalWindow)) {
- return finalWindow.second + mFlags.getMeasurementMinEventReportDelayMillis();
- }
+
return -1;
}
@@ -120,45 +122,60 @@ public class EventReportWindowCalcDelegate {
}
/**
+ * Enum shows trigger time and source window time relationship. It is used to generate different
+ * verbose debug reports.
+ */
+ public enum MomentPlacement {
+ BEFORE,
+ AFTER,
+ WITHIN;
+ }
+
+ /**
+ * @param source source for which the window is calculated
+ * @param triggerTime time for the trigger
+ * @param destinationType trigger destination type
+ * @return how trigger time falls in source windows
+ */
+ public MomentPlacement fallsWithinWindow(
+ @NonNull Source source, long triggerTime, @EventSurfaceType int destinationType) {
+ List<Pair<Long, Long>> reportingWindows =
+ getEffectiveReportingWindows(source, isInstallCase(source, destinationType));
+ if (triggerTime < reportingWindows.get(0).first) {
+ return MomentPlacement.BEFORE;
+ }
+ if (triggerTime >= reportingWindows.get(reportingWindows.size() - 1).second) {
+ return MomentPlacement.AFTER;
+ }
+ return MomentPlacement.WITHIN;
+ }
+
+ /**
* Return reporting time by index for noising based on the index
*
* @param windowIndex index of the reporting window for which
* @return reporting time in milliseconds
*/
public long getReportingTimeForNoising(
- @NonNull Source source, int windowIndex, boolean isInstallCase) {
- List<Pair<Long, Long>> earlyWindows = getEarlyReportingWindows(source, isInstallCase);
- Pair<Long, Long> finalWindow = getFinalReportingWindow(source, earlyWindows);
- return windowIndex < earlyWindows.size()
- ? earlyWindows.get(windowIndex).second
+ @NonNull Source source, int windowIndex) {
+ List<Pair<Long, Long>> reportingWindows = getEffectiveReportingWindows(
+ source, source.isInstallDetectionEnabled());
+ Pair<Long, Long> finalWindow = reportingWindows.get(reportingWindows.size() - 1);
+ // TODO: (b/288646239) remove this check, confirming noising indexing accuracy.
+ return windowIndex < reportingWindows.size()
+ ? reportingWindows.get(windowIndex).second
+ mFlags.getMeasurementMinEventReportDelayMillis()
: finalWindow.second + mFlags.getMeasurementMinEventReportDelayMillis();
}
- private Pair<Long, Long> getFinalReportingWindow(
- Source source, List<Pair<Long, Long>> earlyWindows) {
- if (mFlags.getMeasurementFlexLiteApiEnabled() && source.hasManualEventReportWindows()) {
- List<Pair<Long, Long>> windowList = source.parsedProcessedEventReportWindows();
- return windowList.get(windowList.size() - 1);
- }
- long secondToLastWindowEnd =
- !earlyWindows.isEmpty() ? earlyWindows.get(earlyWindows.size() - 1).second : 0;
- if (source.getProcessedEventReportWindow() != null) {
- return new Pair<>(secondToLastWindowEnd, source.getProcessedEventReportWindow());
- }
- return new Pair<>(secondToLastWindowEnd, source.getExpiryTime());
- }
-
/**
- * Returns effective, i.e. the ones that occur before {@link
- * Source#getProcessedEventReportWindow()}, event reporting windows count for noising cases.
+ * Returns effective, that is, the ones that occur before {@link
+ * Source#getEffectiveEventReportWindow()}, event reporting windows count for noising cases.
*
* @param source source for which the count is requested
- * @param isInstallCase true of cool down window was specified
*/
- public int getReportingWindowCountForNoising(@NonNull Source source, boolean isInstallCase) {
- // Early Count + lastWindow
- return getEarlyReportingWindows(source, isInstallCase).size() + 1;
+ public int getReportingWindowCountForNoising(@NonNull Source source) {
+ return getEffectiveReportingWindows(source, source.isInstallDetectionEnabled()).size();
}
/**
@@ -213,47 +230,53 @@ public class EventReportWindowCalcDelegate {
return -1L;
}
- private boolean isAppInstalled(Source source, int destinationType) {
+ private static boolean isInstallCase(Source source, @EventSurfaceType int destinationType) {
return destinationType == EventSurfaceType.APP && source.isInstallAttributed();
}
/**
* If the flag is enabled and the specified report windows are valid, picks from flag controlled
- * configurable early reporting windows. Otherwise, falls back to the statical {@link
- * com.android.adservices.service.measurement.PrivacyParams} values. It curtails the windows
- * that occur after {@link Source#getProcessedEventReportWindow()} because they would
- * effectively be unusable.
+ * configurable early reporting windows. Otherwise, falls back to the values provided in
+ * {@code getDefaultEarlyReportingWindowEnds}, which can have install-related custom behaviour.
+ * It curtails the windows that occur after {@link Source#getEffectiveEventReportWindow()}
+ * because they would effectively be unusable.
*/
- private List<Pair<Long, Long>> getEarlyReportingWindows(Source source, boolean installState) {
+ private List<Pair<Long, Long>> getEffectiveReportingWindows(Source source,
+ boolean installState) {
// TODO(b/290221611) Remove early reporting windows from code, only use them for flags.
if (mFlags.getMeasurementFlexLiteApiEnabled() && source.hasManualEventReportWindows()) {
- List<Pair<Long, Long>> windows = source.parsedProcessedEventReportWindows();
- // Select early windows only i.e. skip the last element
- return windows.subList(0, windows.size() - 1);
+ return source.parsedProcessedEventReportWindows();
}
- List<Long> earlyWindows;
- List<Long> defaultEarlyWindows =
- getDefaultEarlyReportingWindows(source.getSourceType(), installState);
- earlyWindows =
- getConfiguredOrDefaultEarlyReportingWindows(
- source.getSourceType(), defaultEarlyWindows, true);
+ List<Long> defaultEarlyWindowEnds =
+ getDefaultEarlyReportingWindowEnds(
+ source.getSourceType(),
+ installState && !source.hasWebDestinations());
+ List<Long> earlyWindowEnds =
+ getConfiguredOrDefaultEarlyReportingWindowEnds(
+ source.getSourceType(), defaultEarlyWindowEnds);
// Add source event time to windows
- earlyWindows =
- earlyWindows.stream()
+ earlyWindowEnds =
+ earlyWindowEnds.stream()
.map((x) -> source.getEventTime() + x)
.collect(Collectors.toList());
List<Pair<Long, Long>> windowList = new ArrayList<>();
- long windowStart = 0;
+ long windowStart = 0L;
Pair<Long, Long> finalWindow =
- getFinalReportingWindow(source, createStartEndWindow(earlyWindows));
- for (long windowEnd : earlyWindows) {
- if (finalWindow.second <= windowEnd) {
- continue;
+ getFinalReportingWindow(source, earlyWindowEnds);
+
+ for (long windowEnd : earlyWindowEnds) {
+ // Start time of `finalWindow` is either 0 or one of `earlyWindowEnds` times; stop
+ // iterating if we see it, and add `finalWindow`.
+ if (windowStart == finalWindow.first) {
+ break;
}
- windowList.add(new Pair<>(windowStart, windowEnd));
+ windowList.add(Pair.create(windowStart, windowEnd));
windowStart = windowEnd;
}
+
+ windowList.add(finalWindow);
+
return ImmutableList.copyOf(windowList);
}
@@ -261,13 +284,13 @@ public class EventReportWindowCalcDelegate {
* Returns the default early reporting windows
*
* @param sourceType Source's Type
- * @param installState Install State of the source
+ * @param installAttributionEnabled whether windows for install attribution should be provided
* @return a list of windows
*/
- public static List<Long> getDefaultEarlyReportingWindows(
- Source.SourceType sourceType, boolean installState) {
+ public static List<Long> getDefaultEarlyReportingWindowEnds(
+ Source.SourceType sourceType, boolean installAttributionEnabled) {
long[] earlyWindows;
- if (installState) {
+ if (installAttributionEnabled) {
earlyWindows =
sourceType == Source.SourceType.EVENT
? INSTALL_ATTR_EVENT_EARLY_REPORTING_WINDOW_MILLISECONDS
@@ -281,53 +304,34 @@ public class EventReportWindowCalcDelegate {
return asList(earlyWindows);
}
- private List<Pair<Long, Long>> createStartEndWindow(List<Long> windowEnds) {
- List<Pair<Long, Long>> windows = new ArrayList<>();
- long start = 0;
- for (Long end : windowEnds) {
- windows.add(new Pair<>(start, end));
- start = end;
- }
- return windows;
- }
-
/**
* Returns default or configured (via flag) early reporting windows for the SourceType
*
* @param sourceType Source's Type
* @param defaultEarlyWindows default value for early windows
- * @param checkEnableFlag set true if configurable window flag should be checked
* @return list of windows
*/
- public List<Long> getConfiguredOrDefaultEarlyReportingWindows(
- Source.SourceType sourceType, List<Long> defaultEarlyWindows, boolean checkEnableFlag) {
- // TODO(b/290101531): Cleanup flags
- if (checkEnableFlag && !mFlags.getMeasurementEnableConfigurableEventReportingWindows()) {
- return defaultEarlyWindows;
+ public List<Long> getConfiguredOrDefaultEarlyReportingWindowEnds(
+ Source.SourceType sourceType, List<Long> defaultEarlyWindowEnds) {
+ // `defaultEarlyWindowEnds` may contain custom install-related logic, which we only apply if
+ // the configurable report windows (and max reports) are in their default state. Without
+ // this check, we may construct default-value report windows without the custom
+ // install-related logic applied.
+ if ((sourceType == Source.SourceType.EVENT && isDefaultConfiguredVtc())
+ || (sourceType == Source.SourceType.NAVIGATION && isDefaultConfiguredCtc())) {
+ return defaultEarlyWindowEnds;
}
String earlyReportingWindowsString = pickEarlyReportingWindowsConfig(mFlags, sourceType);
- if (earlyReportingWindowsString == null) {
- LoggerFactory.getMeasurementLogger()
- .d("Invalid configurable early reporting windows; null");
- return defaultEarlyWindows;
- }
-
if (earlyReportingWindowsString.isEmpty()) {
// No early reporting windows specified. It needs to be handled separately because
- // splitting an empty string results into an array containing a single element,
- // i.e. "". We want to handle it as an array having no element.
-
- if (Source.SourceType.EVENT.equals(sourceType)) {
- // We need to add a reporting window at 2d for post-install case. Non-install case
- // has no early reporting window by default.
- return defaultEarlyWindows;
- }
+ // splitting an empty string results in an array containing a single empty string. We
+ // want to handle it as an empty array.
return Collections.emptyList();
}
- ImmutableList.Builder<Long> earlyWindows = new ImmutableList.Builder<>();
+ ImmutableList.Builder<Long> earlyWindowEnds = new ImmutableList.Builder<>();
String[] split =
earlyReportingWindowsString.split(EARLY_REPORTING_WINDOWS_CONFIG_DELIMITER);
if (split.length > MAX_CONFIGURABLE_EVENT_REPORT_EARLY_REPORTING_WINDOWS) {
@@ -335,22 +339,54 @@ public class EventReportWindowCalcDelegate {
.d(
"Invalid configurable early reporting window; more than allowed size: "
+ MAX_CONFIGURABLE_EVENT_REPORT_EARLY_REPORTING_WINDOWS);
- return defaultEarlyWindows;
+ return defaultEarlyWindowEnds;
}
- for (String window : split) {
+ for (String windowEnd : split) {
try {
- earlyWindows.add(TimeUnit.SECONDS.toMillis(Long.parseLong(window)));
+ earlyWindowEnds.add(TimeUnit.SECONDS.toMillis(Long.parseLong(windowEnd)));
} catch (NumberFormatException e) {
LoggerFactory.getMeasurementLogger()
.d(e, "Configurable early reporting window parsing failed.");
- return defaultEarlyWindows;
+ return defaultEarlyWindowEnds;
+ }
+ }
+ return earlyWindowEnds.build();
+ }
+
+ private Pair<Long, Long> getFinalReportingWindow(
+ Source source, List<Long> earlyWindowEnds) {
+ // The latest end-time we can associate with a report for this source
+ long effectiveExpiry = Math.min(
+ source.getEffectiveEventReportWindow(), source.getExpiryTime());
+ // Find the latest end-time that can start a window ending at effectiveExpiry
+ for (int i = earlyWindowEnds.size() - 1; i >= 0; i--) {
+ long windowEnd = earlyWindowEnds.get(i);
+ if (windowEnd < effectiveExpiry) {
+ return Pair.create(windowEnd, effectiveExpiry);
}
}
- return earlyWindows.build();
+ return Pair.create(0L, effectiveExpiry);
+ }
+
+ /** Indicates whether VTC report windows and max reports are default configured, which can
+ * affect custom install-related attribution.
+ */
+ public boolean isDefaultConfiguredVtc() {
+ return mFlags.getMeasurementEventReportsVtcEarlyReportingWindows().isEmpty()
+ && mFlags.getMeasurementVtcConfigurableMaxEventReportsCount() == 1;
+ }
+
+ /** Indicates whether CTC report windows are default configured, which can affect custom
+ * install-related attribution.
+ */
+ private boolean isDefaultConfiguredCtc() {
+ return mFlags.getMeasurementEventReportsCtcEarlyReportingWindows().equals(
+ Flags.MEASUREMENT_EVENT_REPORTS_CTC_EARLY_REPORTING_WINDOWS);
}
- private String pickEarlyReportingWindowsConfig(Flags flags, Source.SourceType sourceType) {
+ private static String pickEarlyReportingWindowsConfig(Flags flags,
+ Source.SourceType sourceType) {
return sourceType == Source.SourceType.EVENT
? flags.getMeasurementEventReportsVtcEarlyReportingWindows()
: flags.getMeasurementEventReportsCtcEarlyReportingWindows();
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportingJobHandler.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportingJobHandler.java
index f5042f3af..c67f0acd6 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportingJobHandler.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/EventReportingJobHandler.java
@@ -16,7 +16,9 @@
package com.android.adservices.service.measurement.reporting;
-import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_NETWORK_ERROR;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_PARSING_ERROR;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_UNKNOWN_ERROR;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_MESUREMENT_REPORTS_UPLOADED;
@@ -270,7 +272,7 @@ public class EventReportingJobHandler {
// TODO(b/298330312): Change to defined error codes
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_NETWORK_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
return AdServicesStatusUtils.STATUS_IO_ERROR;
} catch (JSONException e) {
@@ -281,7 +283,7 @@ public class EventReportingJobHandler {
// TODO(b/298330312): Change to defined error codes
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_PARSING_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
if (mFlags.getMeasurementEnableReportDeletionOnUnrecoverableException()) {
// Unrecoverable state - delete the report.
@@ -305,7 +307,7 @@ public class EventReportingJobHandler {
reportingStatus.setFailureStatus(ReportingStatus.FailureStatus.UNKNOWN);
ErrorLogUtil.e(
e,
- AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_CODE_UNSPECIFIED,
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__MEASUREMENT_REPORTING_UNKNOWN_ERROR,
AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__MEASUREMENT);
if (mFlags.getMeasurementEnableReportingJobsThrowUnaccountedException()
&& ThreadLocalRandom.current().nextFloat()
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/ReportingStatus.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/ReportingStatus.java
index 8e7b1780f..4e83edb8c 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/ReportingStatus.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/ReportingStatus.java
@@ -52,7 +52,9 @@ public class ReportingStatus {
VERBOSE_DEBUG_TRIGGER_UNKNOWN_ERROR(26),
VERBOSE_DEBUG_TRIGGER_AGGREGATE_STORAGE_LIMIT(27),
VERBOSE_DEBUG_TRIGGER_AGGREGATE_EXCESSIVE_REPORTS(28),
- VERBOSE_DEBUG_UNKNOWN(29);
+ VERBOSE_DEBUG_TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED(29),
+ VERBOSE_DEBUG_UNKNOWN(9999);
+
private final int mValue;
ReportType(int value) {
@@ -202,6 +204,10 @@ public class ReportingStatus {
mReportType = ReportType.VERBOSE_DEBUG_TRIGGER_AGGREGATE_STORAGE_LIMIT;
} else if (reportType.equals(DebugReportApi.Type.TRIGGER_AGGREGATE_EXCESSIVE_REPORTS)) {
mReportType = ReportType.VERBOSE_DEBUG_TRIGGER_AGGREGATE_EXCESSIVE_REPORTS;
+ } else if (reportType.equals(DebugReportApi.Type.TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED)) {
+ mReportType = ReportType.VERBOSE_DEBUG_TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED;
+ } else {
+ mReportType = ReportType.VERBOSE_DEBUG_UNKNOWN;
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/util/Enrollment.java b/adservices/service-core/java/com/android/adservices/service/measurement/util/Enrollment.java
index 7f71d2eb0..f98f138fb 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/util/Enrollment.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/util/Enrollment.java
@@ -30,7 +30,6 @@ import java.util.Optional;
/** Enrollment utilities for measurement. */
public final class Enrollment {
- public static final String FAKE_ENROLLMENT = "fake_enrollment";
public static final String LOCALHOST_ENROLLMENT_ID = "localhost_enrollment_id";
public static final String LOCALHOST_IP_ENROLLMENT_ID = "localhost_ip_enrollment_id";
diff --git a/adservices/service-core/java/com/android/adservices/service/shell/AdServicesShellCommandHandler.java b/adservices/service-core/java/com/android/adservices/service/shell/AdServicesShellCommandHandler.java
index ab2227b46..d93eba2db 100644
--- a/adservices/service-core/java/com/android/adservices/service/shell/AdServicesShellCommandHandler.java
+++ b/adservices/service-core/java/com/android/adservices/service/shell/AdServicesShellCommandHandler.java
@@ -21,6 +21,7 @@ import android.util.Log;
import com.android.adservices.service.common.AppManifestConfigHelper;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -45,24 +46,30 @@ public final class AdServicesShellCommandHandler {
@VisibleForTesting
static final String CMD_IS_ALLOWED_ATTRIBUTION_ACCESS = "is-allowed-attribution-access";
+
@VisibleForTesting
static final String CMD_IS_ALLOWED_CUSTOM_AUDIENCES_ACCESS =
"is-allowed-custom-audiences-access";
+
@VisibleForTesting
static final String CMD_IS_ALLOWED_TOPICS_ACCESS = "is-allowed-topics-access";
+
@VisibleForTesting
static final String HELP_ECHO =
CMD_ECHO + " <message> - prints the given message (useful to check cmd is working).";
+
@VisibleForTesting
static final String HELP_IS_ALLOWED_ATTRIBUTION_ACCESS =
CMD_IS_ALLOWED_ATTRIBUTION_ACCESS
+ " <package_name> <enrollment_id> - checks if the given enrollment id is"
+ " allowed to use the Attribution APIs in the given app.";
+
@VisibleForTesting
static final String HELP_IS_ALLOWED_CUSTOM_AUDIENCES_ACCESS =
CMD_IS_ALLOWED_CUSTOM_AUDIENCES_ACCESS
+ " <package_name> <enrollment_id> - checks if the given enrollment id is"
+ " allowed to use the Custom Audience APIs in the given app.";
+
@VisibleForTesting
static final String HELP_IS_ALLOWED_TOPICS_ACCESS =
CMD_IS_ALLOWED_TOPICS_ACCESS
@@ -74,6 +81,7 @@ public final class AdServicesShellCommandHandler {
@VisibleForTesting
static final String ERROR_TEMPLATE_INVALID_ARGS = "Invalid cmd (%s). Syntax: %s";
+
// TODO(b/280460130): use adservice helpers for tag name / logging methods
private static final String TAG = "AdServicesShellCmd";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -81,23 +89,27 @@ public final class AdServicesShellCommandHandler {
private static final int RESULT_GENERIC_ERROR = -1;
private final PrintWriter mOut;
+ private final PrintWriter mErr;
private String[] mArgs;
private int mArgPos;
private String mCurArgData;
+ /** If PrintWriter {@code err} is not provided, we use {@code out} for the {@code err}. */
public AdServicesShellCommandHandler(PrintWriter out) {
+ this(out, /* err= */ out);
+ }
+
+ public AdServicesShellCommandHandler(PrintWriter out, PrintWriter err) {
mOut = Objects.requireNonNull(out, "out cannot be null");
+ mErr = Objects.requireNonNull(err, "err cannot be null");
}
/** Runs the given command ({@code args[0]}) and optional arguments */
public int run(String... args) {
Objects.requireNonNull(args, "args cannot be null");
- // TODO(b/303886367): use Preconditions
- if (args.length < 1) {
- throw new IllegalArgumentException(
- "must have at least one argument (the command itself)");
- }
+ Preconditions.checkArgument(
+ args.length >= 1, "must have at least one argument (the command itself)");
if (DEBUG) {
Log.d(TAG, "run(): " + Arrays.toString(args));
}
@@ -112,13 +124,14 @@ public final class AdServicesShellCommandHandler {
}
} catch (Throwable e) {
// TODO(b/308009734): need to test this
- mOut.printf("Exception occurred while executing %s\n", Arrays.toString(mArgs));
+ mErr.printf("Exception occurred while executing %s\n", Arrays.toString(mArgs));
e.printStackTrace(mOut);
} finally {
if (DEBUG) {
Log.d(TAG, "Flushing output");
}
mOut.flush();
+ mErr.flush();
}
if (DEBUG) {
Log.d(TAG, "Sending command result: " + res);
@@ -168,7 +181,7 @@ public final class AdServicesShellCommandHandler {
}
private int invalidArgsError(String syntax) {
- mOut.println(String.format(ERROR_TEMPLATE_INVALID_ARGS, Arrays.toString(mArgs), syntax));
+ mErr.println(String.format(ERROR_TEMPLATE_INVALID_ARGS, Arrays.toString(mArgs), syntax));
return RESULT_GENERIC_ERROR;
}
@@ -188,9 +201,9 @@ public final class AdServicesShellCommandHandler {
case CMD_SHORT_HELP:
case CMD_HELP:
onHelp();
- return RESULT_GENERIC_ERROR;
+ return RESULT_OK;
case "":
- mOut.println(ERROR_EMPTY_COMMAND);
+ mErr.println(ERROR_EMPTY_COMMAND);
return RESULT_GENERIC_ERROR;
case CMD_ECHO:
return runEcho();
@@ -199,7 +212,7 @@ public final class AdServicesShellCommandHandler {
case CMD_IS_ALLOWED_TOPICS_ACCESS:
return runIsAllowedApiAccess(cmd);
default:
- mOut.printf("Unknown command: %s\n", cmd);
+ mErr.printf("Unknown command: %s\n", cmd);
return RESULT_GENERIC_ERROR;
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/shell/ShellCommandServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/shell/ShellCommandServiceImpl.java
new file mode 100644
index 000000000..285396c15
--- /dev/null
+++ b/adservices/service-core/java/com/android/adservices/service/shell/ShellCommandServiceImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 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.service.shell;
+
+import android.adservices.shell.IShellCommand;
+import android.adservices.shell.IShellCommandCallback;
+import android.adservices.shell.ShellCommandParam;
+import android.adservices.shell.ShellCommandResult;
+import android.os.RemoteException;
+
+import com.android.adservices.LogUtil;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * Implements a service which runs shell command in the AdServices process.
+ *
+ * <p>This internally calls {@link AdServicesShellCommandHandler} which has main logic to execute
+ * the shell command.
+ *
+ * @hide
+ */
+public final class ShellCommandServiceImpl extends IShellCommand.Stub {
+ @Override
+ public void runShellCommand(ShellCommandParam param, IShellCommandCallback callback) {
+ StringWriter outStringWriter = new StringWriter();
+ StringWriter ErrStringWriter = new StringWriter();
+
+ try (PrintWriter outPw = new PrintWriter(outStringWriter);
+ PrintWriter errPw = new PrintWriter(ErrStringWriter); ) {
+ AdServicesShellCommandHandler handler = new AdServicesShellCommandHandler(outPw, errPw);
+ int resultCode = handler.run(param.getCommandArgs());
+ ShellCommandResult response =
+ new ShellCommandResult.Builder()
+ .setResultCode(resultCode)
+ .setOut(outStringWriter.toString())
+ .setErr(ErrStringWriter.toString())
+ .build();
+ callback.onResult(response);
+ } catch (RemoteException e) {
+ LogUtil.e(e, "Unable to send result to the callback for request: %s", param);
+ }
+ }
+}
diff --git a/adservices/service-core/java/com/android/adservices/service/signals/PeriodicEncodingJobWorker.java b/adservices/service-core/java/com/android/adservices/service/signals/PeriodicEncodingJobWorker.java
index 08a6c6525..b792dc773 100644
--- a/adservices/service-core/java/com/android/adservices/service/signals/PeriodicEncodingJobWorker.java
+++ b/adservices/service-core/java/com/android/adservices/service/signals/PeriodicEncodingJobWorker.java
@@ -24,10 +24,11 @@ import com.android.adservices.LoggerFactory;
import com.android.adservices.concurrency.AdServicesExecutors;
import com.android.adservices.data.signals.DBEncodedPayload;
import com.android.adservices.data.signals.DBEncoderLogicMetadata;
+import com.android.adservices.data.signals.DBSignalsUpdateMetadata;
import com.android.adservices.data.signals.EncodedPayloadDao;
import com.android.adservices.data.signals.EncoderLogicHandler;
import com.android.adservices.data.signals.EncoderLogicMetadataDao;
-import com.android.adservices.data.signals.EncoderPersistenceDao;
+import com.android.adservices.data.signals.ProtectedSignalsDao;
import com.android.adservices.data.signals.ProtectedSignalsDatabase;
import com.android.adservices.service.Flags;
import com.android.adservices.service.FlagsFactory;
@@ -75,9 +76,9 @@ public class PeriodicEncodingJobWorker {
private final EncoderLogicHandler mEncoderLogicHandler;
private final EncoderLogicMetadataDao mEncoderLogicMetadataDao;
- private final EncoderPersistenceDao mEncoderPersistenceDao;
private final EncodedPayloadDao mEncodedPayloadDao;
private final SignalsProvider mSignalsProvider;
+ private final ProtectedSignalsDao mProtectedSignalsDao;
private final AdSelectionScriptEngine mScriptEngine;
private final ListeningExecutorService mBackgroundExecutor;
private final ListeningExecutorService mLightWeightExecutor;
@@ -92,9 +93,9 @@ public class PeriodicEncodingJobWorker {
protected PeriodicEncodingJobWorker(
@NonNull EncoderLogicHandler encoderLogicHandler,
@NonNull EncoderLogicMetadataDao encoderLogicMetadataDao,
- @NonNull EncoderPersistenceDao encoderPersistenceDao,
@NonNull EncodedPayloadDao encodedPayloadDao,
@NonNull SignalsProviderImpl signalStorageManager,
+ @NonNull ProtectedSignalsDao protectedSignalsDao,
@NonNull AdSelectionScriptEngine scriptEngine,
@NonNull ListeningExecutorService backgroundExecutor,
@NonNull ListeningExecutorService lightWeightExecutor,
@@ -102,9 +103,9 @@ public class PeriodicEncodingJobWorker {
@NonNull Flags flags) {
mEncoderLogicHandler = encoderLogicHandler;
mEncoderLogicMetadataDao = encoderLogicMetadataDao;
- mEncoderPersistenceDao = encoderPersistenceDao;
mEncodedPayloadDao = encodedPayloadDao;
mSignalsProvider = signalStorageManager;
+ mProtectedSignalsDao = protectedSignalsDao;
mScriptEngine = scriptEngine;
mBackgroundExecutor = backgroundExecutor;
mLightWeightExecutor = lightWeightExecutor;
@@ -135,9 +136,9 @@ public class PeriodicEncodingJobWorker {
new PeriodicEncodingJobWorker(
new EncoderLogicHandler(context),
signalsDatabase.getEncoderLogicMetadataDao(),
- EncoderPersistenceDao.getInstance(context),
signalsDatabase.getEncodedPayloadDao(),
new SignalsProviderImpl(signalsDatabase.protectedSignalsDao()),
+ signalsDatabase.protectedSignalsDao(),
new AdSelectionScriptEngine(
context,
() ->
@@ -242,12 +243,30 @@ public class PeriodicEncodingJobWorker {
FluentFuture<Void> runEncodingPerBuyer(
DBEncoderLogicMetadata encoderLogicMetadata, int timeout) {
AdTechIdentifier buyer = encoderLogicMetadata.getBuyer();
+
Map<String, List<ProtectedSignal>> signals = mSignalsProvider.getSignals(buyer);
if (signals.isEmpty()) {
mEncoderLogicHandler.deleteEncoderForBuyer(buyer);
return FluentFuture.from(Futures.immediateFuture(null));
}
+ DBSignalsUpdateMetadata signalsUpdateMetadata =
+ mProtectedSignalsDao.getSignalsUpdateMetadata(buyer);
+ DBEncodedPayload existingPayload = mEncodedPayloadDao.getEncodedPayload(buyer);
+ if (signalsUpdateMetadata != null && existingPayload != null) {
+ boolean isNoNewSignalUpdateAfterLastEncoding =
+ signalsUpdateMetadata
+ .getLastSignalsUpdatedTime()
+ .isBefore(existingPayload.getCreationTime());
+ boolean isEncoderLogicNotUpdatedAfterLastEncoding =
+ encoderLogicMetadata
+ .getCreationTime()
+ .isBefore(existingPayload.getCreationTime());
+ if (isNoNewSignalUpdateAfterLastEncoding && isEncoderLogicNotUpdatedAfterLastEncoding) {
+ return FluentFuture.from(Futures.immediateFuture(null));
+ }
+ }
+
int failedCount = encoderLogicMetadata.getFailedEncodingCount();
if (failedCount >= mEncoderLogicMaximumFailure) {
return FluentFuture.from(Futures.immediateFuture(null));
diff --git a/adservices/service-core/java/com/android/adservices/service/signals/ProtectedSignalsServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/signals/ProtectedSignalsServiceImpl.java
index 902ac7411..9cac9eef5 100644
--- a/adservices/service-core/java/com/android/adservices/service/signals/ProtectedSignalsServiceImpl.java
+++ b/adservices/service-core/java/com/android/adservices/service/signals/ProtectedSignalsServiceImpl.java
@@ -58,6 +58,7 @@ import com.android.adservices.service.stats.AdServicesLogger;
import com.android.adservices.service.stats.AdServicesLoggerImpl;
import com.android.internal.annotations.VisibleForTesting;
+import java.time.Clock;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -104,7 +105,8 @@ public class ProtectedSignalsServiceImpl extends IProtectedSignalsService.Stub {
new UpdateProcessorSelector(),
new UpdateEncoderEventHandler(context),
new SignalEvictionController()),
- new AdTechUriValidator(ADTECH_CALLER_NAME, "", CLASS_NAME, FIELD_NAME)),
+ new AdTechUriValidator(ADTECH_CALLER_NAME, "", CLASS_NAME, FIELD_NAME),
+ Clock.systemUTC()),
FledgeAuthorizationFilter.create(context, AdServicesLoggerImpl.getInstance()),
ConsentManager.getInstance(context),
DevContextFilter.create(context),
@@ -187,7 +189,7 @@ public class ProtectedSignalsServiceImpl extends IProtectedSignalsService.Stub {
}
// Caller permissions must be checked in the binder thread, before anything else
- mFledgeAuthorizationFilter.assertAppDeclaredProtectedSignalsPermission(
+ mFledgeAuthorizationFilter.assertAppDeclaredPermission(
mContext, updateSignalsInput.getCallerPackageName(), apiName);
final int callerUid = getCallingUid(apiName);
diff --git a/adservices/service-core/java/com/android/adservices/service/signals/SignalsMaintenanceTasksWorker.java b/adservices/service-core/java/com/android/adservices/service/signals/SignalsMaintenanceTasksWorker.java
index 2df832c1a..0205389b1 100644
--- a/adservices/service-core/java/com/android/adservices/service/signals/SignalsMaintenanceTasksWorker.java
+++ b/adservices/service-core/java/com/android/adservices/service/signals/SignalsMaintenanceTasksWorker.java
@@ -109,18 +109,20 @@ public class SignalsMaintenanceTasksWorker {
* </ul>
*/
public void clearInvalidProtectedSignalsData() {
- Instant expirationInstant =
- mClock.instant().minusSeconds(ProtectedSignal.EXPIRATION_SECONDS);
- clearInvalidSignals(expirationInstant);
+ Instant now = mClock.instant();
+ Instant expirationInstant = now.minusSeconds(ProtectedSignal.EXPIRATION_SECONDS);
+ clearInvalidSignals(expirationInstant, now);
clearInvalidEncoders(expirationInstant);
clearInvalidEncodedPayloads(expirationInstant);
}
@VisibleForTesting
- void clearInvalidSignals(Instant expirationInstant) {
+ void clearInvalidSignals(Instant expirationInstant, Instant now) {
sLogger.v("Clearing expired signals older than %s", expirationInstant);
- int numExpiredSignals = mProtectedSignalsDao.deleteSignalsBeforeTime(expirationInstant);
+ int numExpiredSignals =
+ mProtectedSignalsDao.deleteExpiredSignalsAndUpdateSignalsUpdateMetadata(
+ expirationInstant, now);
sLogger.v("Cleared %d expired signals", numExpiredSignals);
// Read from flags directly, since this maintenance task worker is attached to a background
@@ -138,7 +140,8 @@ public class SignalsMaintenanceTasksWorker {
sLogger.v("Clearing signals for disallowed source apps");
int numDisallowedSourceAppSignals =
- mProtectedSignalsDao.deleteAllDisallowedPackageSignals(mPackageManager, mFlags);
+ mProtectedSignalsDao.deleteAllDisallowedPackageSignalsAndUpdateSignalUpdateMetadata(
+ mPackageManager, mFlags, now);
sLogger.v("Cleared %d signals for disallowed source apps", numDisallowedSourceAppSignals);
}
diff --git a/adservices/service-core/java/com/android/adservices/service/signals/UpdateProcessingOrchestrator.java b/adservices/service-core/java/com/android/adservices/service/signals/UpdateProcessingOrchestrator.java
index 9a3c004da..476445b87 100644
--- a/adservices/service-core/java/com/android/adservices/service/signals/UpdateProcessingOrchestrator.java
+++ b/adservices/service-core/java/com/android/adservices/service/signals/UpdateProcessingOrchestrator.java
@@ -115,7 +115,7 @@ public class UpdateProcessingOrchestrator {
mSignalEvictionController.evict(adtech, updatedSignals, combinedUpdates);
- writeChanges(adtech, combinedUpdates, devContext);
+ writeChanges(adtech, creationTime, combinedUpdates, devContext);
} catch (JSONException e) {
throw new IllegalArgumentException("Couldn't unpack signal updates JSON", e);
}
@@ -195,11 +195,16 @@ public class UpdateProcessingOrchestrator {
}
private void writeChanges(
- AdTechIdentifier adTech, UpdateOutput combinedUpdates, DevContext devContext) {
+ AdTechIdentifier adTech,
+ Instant creationTime,
+ UpdateOutput combinedUpdates,
+ DevContext devContext) {
/* Modify the DB based on the output of the update processors. Might be worth skipping
* this is both signalsToAdd and signalsToDelete are empty.
*/
mProtectedSignalsDao.insertAndDelete(
+ adTech,
+ creationTime,
combinedUpdates.getToAdd().stream()
.map(DBProtectedSignal.Builder::build)
.collect(Collectors.toList()),
diff --git a/adservices/service-core/java/com/android/adservices/service/signals/UpdateSignalsOrchestrator.java b/adservices/service-core/java/com/android/adservices/service/signals/UpdateSignalsOrchestrator.java
index 24ff9be75..73ad03455 100644
--- a/adservices/service-core/java/com/android/adservices/service/signals/UpdateSignalsOrchestrator.java
+++ b/adservices/service-core/java/com/android/adservices/service/signals/UpdateSignalsOrchestrator.java
@@ -27,7 +27,7 @@ import com.google.common.util.concurrent.FluentFuture;
import org.json.JSONObject;
-import java.time.Instant;
+import java.time.Clock;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -38,20 +38,24 @@ public class UpdateSignalsOrchestrator {
@NonNull private final UpdatesDownloader mUpdatesDownloader;
@NonNull private final UpdateProcessingOrchestrator mUpdateProcessingOrchestrator;
@NonNull private final AdTechUriValidator mAdTechUriValidator;
+ @NonNull private final Clock mClock;
public UpdateSignalsOrchestrator(
@NonNull Executor backgroundExecutor,
@NonNull UpdatesDownloader updatesDownloader,
@NonNull UpdateProcessingOrchestrator updateProcessingOrchestrator,
- @NonNull AdTechUriValidator adTechUriValidator) {
+ @NonNull AdTechUriValidator adTechUriValidator,
+ @NonNull Clock clock) {
Objects.requireNonNull(backgroundExecutor);
Objects.requireNonNull(updatesDownloader);
Objects.requireNonNull(updateProcessingOrchestrator);
Objects.requireNonNull(adTechUriValidator);
+ Objects.requireNonNull(clock);
mBackgroundExecutor = backgroundExecutor;
mUpdateProcessingOrchestrator = updateProcessingOrchestrator;
mUpdatesDownloader = updatesDownloader;
mAdTechUriValidator = adTechUriValidator;
+ mClock = clock;
}
/**
@@ -70,7 +74,7 @@ public class UpdateSignalsOrchestrator {
return jsonFuture.transform(
x -> {
mUpdateProcessingOrchestrator.processUpdates(
- adtech, packageName, Instant.now(), x, devContext);
+ adtech, packageName, mClock.instant(), x, devContext);
return null;
},
mBackgroundExecutor);
diff --git a/adservices/service-core/java/com/android/adservices/service/stats/ConsentMigrationStats.java b/adservices/service-core/java/com/android/adservices/service/stats/ConsentMigrationStats.java
index b5437a8da..d877f45dd 100644
--- a/adservices/service-core/java/com/android/adservices/service/stats/ConsentMigrationStats.java
+++ b/adservices/service-core/java/com/android/adservices/service/stats/ConsentMigrationStats.java
@@ -19,6 +19,8 @@ import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICE
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_STATUS__SUCCESS_WITH_SHARED_PREF_NOT_UPDATED;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_STATUS__SUCCESS_WITH_SHARED_PREF_UPDATED;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_STATUS__UNSPECIFIED_MIGRATION_STATUS;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__ADEXT_SERVICE_TO_APPSEARCH;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__ADEXT_SERVICE_TO_SYSTEM_SERVICE;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__APPSEARCH_TO_SYSTEM_SERVICE;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__PPAPI_TO_SYSTEM_SERVICE;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__UNSPECIFIED_MIGRATION_TYPE;
@@ -75,7 +77,14 @@ public abstract class ConsentMigrationStats {
AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__PPAPI_TO_SYSTEM_SERVICE),
// Migrating consent from App Search to system service
APPSEARCH_TO_SYSTEM_SERVICE(
- AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__APPSEARCH_TO_SYSTEM_SERVICE);
+ AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__APPSEARCH_TO_SYSTEM_SERVICE),
+ // Migrating consent from AdServicesExtDataStorageService to System Server
+ ADEXT_SERVICE_TO_SYSTEM_SERVICE(
+ AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__ADEXT_SERVICE_TO_SYSTEM_SERVICE),
+ // Migrating consent from AdServicesExtDataStorageService to App Search
+ ADEXT_SERVICE_TO_APPSEARCH(
+ AD_SERVICES_CONSENT_MIGRATED__MIGRATION_TYPE__ADEXT_SERVICE_TO_APPSEARCH);
+
private final int mMigrationType;
MigrationType(int migrationType) {
diff --git a/adservices/service-core/java/com/android/adservices/service/topics/EncryptionManager.java b/adservices/service-core/java/com/android/adservices/service/topics/EncryptionManager.java
index a9a56b8aa..4f147fe67 100644
--- a/adservices/service-core/java/com/android/adservices/service/topics/EncryptionManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/topics/EncryptionManager.java
@@ -116,8 +116,9 @@ public class EncryptionManager {
* public key is missing.
*/
private Optional<String> fetchPublicKeyFor(String sdkName) {
- if (mFlags.isDisableTopicsEnrollmentCheck()) {
- return Optional.of(TEST_PUBLIC_KEY_BASE64);
+ if (!mFlags.getTopicsTestEncryptionPublicKey().isEmpty()) {
+ // Use testing key for encryption if the test key is non-empty.
+ return Optional.of(mFlags.getTopicsTestEncryptionPublicKey());
}
sLogger.v("Fetching EnrollmentData for %s", sdkName);
diff --git a/adservices/service-core/java/com/android/adservices/service/topics/TopicsServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/topics/TopicsServiceImpl.java
index 5091491c2..683a63d9f 100644
--- a/adservices/service-core/java/com/android/adservices/service/topics/TopicsServiceImpl.java
+++ b/adservices/service-core/java/com/android/adservices/service/topics/TopicsServiceImpl.java
@@ -31,6 +31,7 @@ import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICE
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__API_CALLBACK_ERROR;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PACKAGE_NAME_NOT_FOUND_EXCEPTION;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__RATE_LIMIT_CALLBACK_FAILURE;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__TOPICS_REQUEST_EMPTY_SDK_NAME;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__TOPICS;
import android.adservices.common.AdServicesStatusUtils;
@@ -147,7 +148,7 @@ public class TopicsServiceImpl extends ITopicsService.Stub {
// Check if the request is valid.
if (!validateRequest(topicsParam, callback)) {
// Return early if the request is invalid.
- sLogger.d("Invalid request %s", topicsParam);
+ sLogger.e("Invalid request %s", topicsParam);
return;
}
}
@@ -202,6 +203,9 @@ public class TopicsServiceImpl extends ITopicsService.Stub {
GetTopicsParam topicsParam, IGetTopicsCallback callback) {
// Return false if sdkName is empty or null.
if (TextUtils.isEmpty(topicsParam.getSdkName())) {
+ ErrorLogUtil.e(
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__TOPICS_REQUEST_EMPTY_SDK_NAME,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__TOPICS);
invokeCallbackWithStatus(
callback,
STATUS_INVALID_ARGUMENT,
diff --git a/adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java b/adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java
index 8e257aff4..139d2d9ba 100644
--- a/adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java
@@ -138,7 +138,7 @@ public class ClassifierInputManager {
applicationInfo.descriptionRes)));
break;
default:
- LogUtil.e("Invalid input field in config: {}", inputField);
+ LogUtil.e("Invalid input field in config: %s", inputField);
return null;
}
}
@@ -171,7 +171,7 @@ public class ClassifierInputManager {
PackageManager packageManager, ApplicationInfo applicationInfo, int resourceId) {
if (!SdkLevel.isAtLeastS()) {
LogUtil.d(
- "English app resource not available for SDK version {} - "
+ "English app resource not available for SDK version %d - "
+ "returning localized app resource",
Build.VERSION.SDK_INT);
return getLocalAppResource(packageManager, applicationInfo, resourceId);
@@ -192,7 +192,7 @@ public class ClassifierInputManager {
} catch (PackageManager.NameNotFoundException e) {
LogUtil.e("No resources returned from packageManager.");
} catch (Resources.NotFoundException e) {
- LogUtil.e("Resource not found by packageManager - resourceId: {}", resourceId);
+ LogUtil.e("Resource not found by packageManager - resourceId: %d", resourceId);
}
return EMPTY_STRING;
}
@@ -204,7 +204,7 @@ public class ClassifierInputManager {
} catch (PackageManager.NameNotFoundException e) {
LogUtil.e("No resources returned from packageManager.");
} catch (Resources.NotFoundException e) {
- LogUtil.e("Resource not found by packageManager - resourceId: {}", resourceId);
+ LogUtil.e("Resource not found by packageManager - resourceId: %d", resourceId);
}
return EMPTY_STRING;
}
diff --git a/adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java b/adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java
index 3a1f1934a..4a2fda2f4 100644
--- a/adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java
@@ -665,7 +665,7 @@ public class ModelManager {
try {
inputFields.add(ClassifierInputField.valueOf(line));
} catch (IllegalArgumentException e) {
- LogUtil.e("Invalid input field in classifier input config: {}", line);
+ LogUtil.e("Invalid input field in classifier input config: %s", line);
return ClassifierInputConfig.getEmptyConfig();
}
}
@@ -696,7 +696,7 @@ public class ModelManager {
try {
String formattedInput =
String.format(classifierInputConfig.getInputFormat(), (Object[]) inputFields);
- LogUtil.d("Validated classifier input format: {}", formattedInput);
+ LogUtil.d("Validated classifier input format: %s", formattedInput);
} catch (IllegalFormatException e) {
LogUtil.e("Classifier input config is incorrectly formatted");
return false;
diff --git a/adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java b/adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java
index ea6c8203f..9079562e3 100644
--- a/adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java
@@ -102,7 +102,7 @@ public class UxStatesManager {
/** Returns process statble UX flags. */
public boolean getFlag(String uxFlagKey) {
if (!mUxFlags.containsKey(uxFlagKey)) {
- LogUtil.e("Key not found in cached UX flags: ", uxFlagKey);
+ LogUtil.e("Key not found in cached UX flags: %s", uxFlagKey);
}
Boolean value = mUxFlags.get(uxFlagKey);
return value != null ? value : false;
diff --git a/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/AlreadyEnrolledChannel.java b/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/AlreadyEnrolledChannel.java
index caea3ca6c..bff7b772c 100644
--- a/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/AlreadyEnrolledChannel.java
+++ b/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/AlreadyEnrolledChannel.java
@@ -56,12 +56,9 @@ public class AlreadyEnrolledChannel implements PrivacySandboxEnrollmentChannel {
private static boolean isPreNotificationManualUser(
ConsentManager consentManager, UxStatesManager uxStatesManager) {
- if (uxStatesManager.getFlag(KEY_CONSENT_ALREADY_INTERACTED_FIX_ENABLE)
+ return uxStatesManager.getFlag(KEY_CONSENT_ALREADY_INTERACTED_FIX_ENABLE)
&& consentManager.getUserManualInteractionWithConsent()
- == MANUAL_INTERACTIONS_RECORDED) {
- return true;
- }
- return false;
+ == MANUAL_INTERACTIONS_RECORDED;
}
/** No-Op if the user has already enrolled. */
diff --git a/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/ConsentNotificationResetChannel.java b/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/ConsentNotificationResetChannel.java
index 126e35346..aa26433a8 100644
--- a/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/ConsentNotificationResetChannel.java
+++ b/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/ConsentNotificationResetChannel.java
@@ -16,6 +16,8 @@
package com.android.adservices.service.ui.enrollment.impl;
+import static com.android.adservices.service.consent.ConsentManager.NO_MANUAL_INTERACTIONS_RECORDED;
+
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
@@ -72,6 +74,7 @@ public class ConsentNotificationResetChannel implements PrivacySandboxEnrollment
/** Perform enrollment logic for the reset channel. */
public void enroll(Context context, ConsentManager consentManager) {
+ consentManager.recordUserManualInteractionWithConsent(NO_MANUAL_INTERACTIONS_RECORDED);
consentManager.recordNotificationDisplayed(false);
consentManager.recordGaUxNotificationDisplayed(false);
consentManager.setU18NotificationDisplayed(false);
diff --git a/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/RvcPostOTAChannel.java b/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/RvcPostOTAChannel.java
index 6d6bc18d6..6d89bd4d3 100644
--- a/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/RvcPostOTAChannel.java
+++ b/adservices/service-core/java/com/android/adservices/service/ui/enrollment/impl/RvcPostOTAChannel.java
@@ -16,7 +16,7 @@
package com.android.adservices.service.ui.enrollment.impl;
-import static com.android.adservices.service.FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED;
+import static com.android.adservices.service.FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED;
import android.content.Context;
import android.os.Build;
@@ -40,8 +40,7 @@ public class RvcPostOTAChannel implements PrivacySandboxEnrollmentChannel {
ConsentManager consentManager,
UxStatesManager uxStatesManager) {
// Rvc user should be matched to RvcPostOTAChannel on S+
- // TODO: rename flag to KEY_RVC_POST_OTA_NOTIFICATION_ENABLED
- return uxStatesManager.getFlag(KEY_RVC_NOTIFICATION_ENABLED)
+ return uxStatesManager.getFlag(KEY_RVC_POST_OTA_NOTIFICATION_ENABLED)
&& consentManager.isOtaAdultUserFromRvc();
}
diff --git a/adservices/service-core/schemas/com.android.adservices.data.signals.ProtectedSignalsDatabase/4.json b/adservices/service-core/schemas/com.android.adservices.data.signals.ProtectedSignalsDatabase/4.json
new file mode 100644
index 000000000..a060c0d03
--- /dev/null
+++ b/adservices/service-core/schemas/com.android.adservices.data.signals.ProtectedSignalsDatabase/4.json
@@ -0,0 +1,239 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 4,
+ "identityHash": "3bf5a664458869cb5cd6781484a8a229",
+ "entities": [
+ {
+ "tableName": "protected_signals",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `buyer` TEXT NOT NULL, `key` BLOB NOT NULL, `value` BLOB NOT NULL, `creationTime` INTEGER NOT NULL, `packageName` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "buyer",
+ "columnName": "buyer",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "key",
+ "columnName": "key",
+ "affinity": "BLOB",
+ "notNull": true
+ },
+ {
+ "fieldPath": "value",
+ "columnName": "value",
+ "affinity": "BLOB",
+ "notNull": true
+ },
+ {
+ "fieldPath": "creationTime",
+ "columnName": "creationTime",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "packageName",
+ "columnName": "packageName",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_protected_signals_buyer",
+ "unique": false,
+ "columnNames": [
+ "buyer"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_protected_signals_buyer` ON `${TABLE_NAME}` (`buyer`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "encoder_endpoints",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`buyer` TEXT NOT NULL, `download_uri` TEXT NOT NULL, `creation_time` INTEGER NOT NULL, PRIMARY KEY(`buyer`))",
+ "fields": [
+ {
+ "fieldPath": "buyer",
+ "columnName": "buyer",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "downloadUri",
+ "columnName": "download_uri",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "creationTime",
+ "columnName": "creation_time",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "buyer"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_encoder_endpoints_creation_time",
+ "unique": false,
+ "columnNames": [
+ "creation_time"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_encoder_endpoints_creation_time` ON `${TABLE_NAME}` (`creation_time`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "encoder_logics",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`buyer` TEXT NOT NULL, `version` INTEGER NOT NULL, `creation_time` INTEGER NOT NULL, `failed_encoding_count` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`buyer`))",
+ "fields": [
+ {
+ "fieldPath": "buyer",
+ "columnName": "buyer",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "version",
+ "columnName": "version",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "creationTime",
+ "columnName": "creation_time",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "failedEncodingCount",
+ "columnName": "failed_encoding_count",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "0"
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "buyer"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_encoder_logics_creation_time",
+ "unique": false,
+ "columnNames": [
+ "creation_time"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_encoder_logics_creation_time` ON `${TABLE_NAME}` (`creation_time`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "encoded_payload",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`buyer` TEXT NOT NULL, `version` INTEGER NOT NULL, `creation_time` INTEGER NOT NULL, `encoded_payload` BLOB NOT NULL, PRIMARY KEY(`buyer`))",
+ "fields": [
+ {
+ "fieldPath": "buyer",
+ "columnName": "buyer",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "version",
+ "columnName": "version",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "creationTime",
+ "columnName": "creation_time",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "encodedPayload",
+ "columnName": "encoded_payload",
+ "affinity": "BLOB",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "buyer"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_encoded_payload_creation_time",
+ "unique": false,
+ "columnNames": [
+ "creation_time"
+ ],
+ "orders": [],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_encoded_payload_creation_time` ON `${TABLE_NAME}` (`creation_time`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "signals_update_metadata",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`buyer` TEXT NOT NULL, `last_signals_updated_time` INTEGER, PRIMARY KEY(`buyer`))",
+ "fields": [
+ {
+ "fieldPath": "buyer",
+ "columnName": "buyer",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lastSignalsUpdatedTime",
+ "columnName": "last_signals_updated_time",
+ "affinity": "INTEGER",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "buyer"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3bf5a664458869cb5cd6781484a8a229')"
+ ]
+ }
+} \ No newline at end of file
diff --git a/adservices/service/java/com/android/server/adservices/AdServicesManagerService.java b/adservices/service/java/com/android/server/adservices/AdServicesManagerService.java
index 19ee994b0..239fabda1 100644
--- a/adservices/service/java/com/android/server/adservices/AdServicesManagerService.java
+++ b/adservices/service/java/com/android/server/adservices/AdServicesManagerService.java
@@ -767,7 +767,7 @@ public class AdServicesManagerService extends IAdServicesManager.Stub {
}
LogUtil.v("Executing shell cmd: %s", Arrays.toString(args));
- return new AdServicesShellCommand()
+ return new AdServicesShellCommand(mContext)
.exec(
this,
in.getFileDescriptor(),
diff --git a/adservices/service/java/com/android/server/adservices/AdServicesShellCommand.java b/adservices/service/java/com/android/server/adservices/AdServicesShellCommand.java
index 58f41b772..cbdf07537 100644
--- a/adservices/service/java/com/android/server/adservices/AdServicesShellCommand.java
+++ b/adservices/service/java/com/android/server/adservices/AdServicesShellCommand.java
@@ -18,9 +18,17 @@ package com.android.server.adservices;
import static android.app.adservices.AdServicesManager.AD_SERVICES_SYSTEM_SERVICE;
+import android.adservices.shell.IShellCommand;
+import android.adservices.shell.IShellCommandCallback;
+import android.adservices.shell.ShellCommandParam;
+import android.adservices.shell.ShellCommandResult;
+import android.content.Context;
import android.os.Binder;
import android.os.Process;
+import android.os.RemoteException;
+import com.android.adservices.AdServicesCommon;
+import com.android.adservices.ServiceBinder;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.BasicShellCommandHandler;
@@ -28,7 +36,11 @@ import com.google.errorprone.annotations.FormatMethod;
import com.google.errorprone.annotations.FormatString;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Implementation of {@code cmd adservices_manager}.
@@ -44,17 +56,23 @@ class AdServicesShellCommand extends BasicShellCommandHandler {
static final String WRONG_UID_TEMPLATE =
AD_SERVICES_SYSTEM_SERVICE + " shell cmd is only callable by ADB (called by %d)";
+ private static final String CMD_IS_SYSTEM_SERVICE_ENABLED = "is-system-service-enabled";
+
private final Injector mInjector;
private final Flags mFlags;
+ private final Context mContext;
+
+ private static final int DEFAULT_TIMEOUT_MILLIS = 5_000;
- AdServicesShellCommand() {
- this(new Injector(), PhFlags.getInstance());
+ AdServicesShellCommand(Context context) {
+ this(new Injector(), PhFlags.getInstance(), context);
}
@VisibleForTesting
- AdServicesShellCommand(Injector injector, Flags flags) {
+ AdServicesShellCommand(Injector injector, Flags flags, Context context) {
mInjector = Objects.requireNonNull(injector);
mFlags = Objects.requireNonNull(flags);
+ mContext = Objects.requireNonNull(context);
}
@Override
@@ -63,17 +81,74 @@ class AdServicesShellCommand extends BasicShellCommandHandler {
if (callingUid != Process.ROOT_UID && callingUid != Process.SHELL_UID) {
throw new SecurityException(String.format(WRONG_UID_TEMPLATE, callingUid));
}
-
if (cmd == null || cmd.isEmpty() || cmd.equals("-h") || cmd.equals("help")) {
onHelp();
return 0;
}
switch (cmd) {
- case "is-system-service-enabled":
+ // Below commands are handled by the System Server
+ case CMD_IS_SYSTEM_SERVICE_ENABLED:
return runIsSystemServiceEnabled();
+
+ // If there is no explicit case is there, we assume we want to run the shell command
+ // in the adservices process.
default:
- // Cannot use handleDefaultCommands() because it doesn't show help
- return showError("Unsupported commmand: %s", cmd);
+ // TODO(b/308009734): Check for --user args in the follow-up cl and change
+ // context and bind to the service accordingly.
+ return runAdServicesShellCommand(mContext, getAllArgs());
+ }
+ }
+
+ private int runAdServicesShellCommand(Context context, String[] args) {
+ IShellCommand service = mInjector.getShellCommandService(context);
+ if (service == null) {
+ getOutPrintWriter().println("Failed to connect to shell command service");
+ return -1;
+ }
+ ShellCommandParam param = new ShellCommandParam(args);
+ CountDownLatch latch = new CountDownLatch(1);
+ AtomicInteger resultCode = new AtomicInteger(-1);
+ try {
+ service.runShellCommand(
+ param,
+ new IShellCommandCallback.Stub() {
+ @Override
+ public void onResult(ShellCommandResult response) {
+ if (response.isSuccess()) {
+ getOutPrintWriter().println(response.getOut());
+ resultCode.set(response.getResultCode());
+ } else {
+ showError("%s", response.getErr());
+ }
+ latch.countDown();
+ }
+ });
+ } catch (RemoteException e) {
+ getErrPrintWriter()
+ .printf(
+ "Remote exception occurred while executing %s\n",
+ Arrays.toString(args));
+
+ latch.countDown();
+ }
+
+ // TODO(b/308009734): make the time out configurable with flags and command line argument.
+ await(latch, DEFAULT_TIMEOUT_MILLIS, getErrPrintWriter());
+
+ return resultCode.get();
+ }
+
+ private void await(CountDownLatch latch, int timeout, PrintWriter pw) {
+ try {
+ if (!latch.await(timeout, TimeUnit.MILLISECONDS)) {
+ pw.printf(
+ "Elapsed time: %d Millisecond. Timeout occurred , failed to "
+ + "complete shell command\n",
+ timeout);
+ }
+ } catch (InterruptedException e) {
+ pw.println("Thread interrupted, failed to complete shell command");
+ Thread.currentThread().interrupt();
}
}
@@ -144,5 +219,14 @@ class AdServicesShellCommand extends BasicShellCommandHandler {
int getCallingUid() {
return Binder.getCallingUid();
}
+
+ IShellCommand getShellCommandService(Context context) {
+ ServiceBinder<IShellCommand> serviceBinder =
+ ServiceBinder.getServiceBinder(
+ context,
+ AdServicesCommon.ACTION_SHELL_COMMAND_SERVICE,
+ IShellCommand.Stub::asInterface);
+ return serviceBinder.getService();
+ }
}
}
diff --git a/adservices/tests/cts/Android.bp b/adservices/tests/cts/Android.bp
index 0cc6024c3..3aec78af2 100644
--- a/adservices/tests/cts/Android.bp
+++ b/adservices/tests/cts/Android.bp
@@ -35,12 +35,12 @@ android_test {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
plugins: [
"auto_value_plugin",
"auto_annotation_plugin"
],
- test_mainline_modules: ["com.google.android.adservices.apex"],
static_libs: [
"androidx.test.rules",
"androidx.test.ext.junit",
@@ -81,12 +81,12 @@ android_test {
"cts_root",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
plugins: [
"auto_value_plugin",
"auto_annotation_plugin"
],
- test_mainline_modules: ["com.google.android.adservices.apex"],
static_libs: [
"androidx.test.rules",
"androidx.test.ext.junit",
@@ -102,8 +102,8 @@ android_test {
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
compile_multilib: "both",
- test_config: "AndroidTest.Root.xml",
manifest: "AndroidManifestRoot.xml",
+ test_config: "AndroidTest.Root.xml",
}
android_test {
@@ -126,12 +126,12 @@ android_test {
"cts",
"mts-extservices",
"general-tests",
+ "mcts-extservices",
],
plugins: [
"auto_value_plugin",
"auto_annotation_plugin"
],
- test_mainline_modules: ["com.google.android.extservices.apex"],
static_libs: [
"androidx.test.rules",
"androidx.test.ext.junit",
@@ -174,8 +174,8 @@ android_test {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
- test_mainline_modules: ["com.google.android.adservices.apex"],
static_libs: [
"androidx.room_room-runtime",
"androidx.room_room-testing",
@@ -216,6 +216,7 @@ android_test {
"cts",
"mts-extservices",
"general-tests",
+ "mcts-extservices",
],
plugins: [
"auto_value_plugin",
diff --git a/adservices/tests/cts/AndroidTest.ExtServices.xml b/adservices/tests/cts/AndroidTest.ExtServices.xml
index 1e96fba6d..182611f37 100644
--- a/adservices/tests/cts/AndroidTest.ExtServices.xml
+++ b/adservices/tests/cts/AndroidTest.ExtServices.xml
@@ -67,6 +67,12 @@
<option name="teardown-command"
value="setprop debug.adservices.consent_manager_debug_mode false"/>
+ <!-- Override MDD background job to avoid race condition. -->
+ <option name="run-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch true"/>
+ <option name="teardown-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch false"/>
+
<!-- Force enable enrollment checks for FLEDGE when testing enrollment -->
<option name="run-command"
value="setprop debug.adservices.disable_fledge_enrollment_check false"/>
diff --git a/adservices/tests/cts/AndroidTest.Root.xml b/adservices/tests/cts/AndroidTest.Root.xml
index de174602c..beeba4e1a 100644
--- a/adservices/tests/cts/AndroidTest.Root.xml
+++ b/adservices/tests/cts/AndroidTest.Root.xml
@@ -20,6 +20,11 @@
<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" />
+
+ <!-- For this test suite to get picked up in mainline presubmit -->
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.adservices.apex" />
+
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsAdServicesRootTestCases.apk" />
@@ -44,6 +49,12 @@
<option name="run-command" value="setprop debug.adservices.consent_manager_debug_mode true" />
<option name="teardown-command" value="setprop debug.adservices.consent_manager_debug_mode false"/>
+ <!-- Override MDD background job to avoid race condition. -->
+ <option name="run-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch true"/>
+ <option name="teardown-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch false"/>
+
<!-- Force enable enrollment checks for FLEDGE when testing enrollment -->
<option name="run-command" value="setprop debug.adservices.disable_fledge_enrollment_check false" />
diff --git a/adservices/tests/cts/AndroidTest.xml b/adservices/tests/cts/AndroidTest.xml
index 7fc974f98..61c51b4af 100644
--- a/adservices/tests/cts/AndroidTest.xml
+++ b/adservices/tests/cts/AndroidTest.xml
@@ -43,6 +43,12 @@
<option name="run-command" value="setprop debug.adservices.consent_manager_debug_mode true" />
<option name="teardown-command" value="setprop debug.adservices.consent_manager_debug_mode false"/>
+ <!-- Override MDD background job to avoid race condition. -->
+ <option name="run-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch true"/>
+ <option name="teardown-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch false"/>
+
<!-- Force enable enrollment checks for FLEDGE when testing enrollment -->
<option name="run-command" value="setprop debug.adservices.disable_fledge_enrollment_check false" />
diff --git a/adservices/tests/cts/AndroidTestDebuggable.ExtServices.xml b/adservices/tests/cts/AndroidTestDebuggable.ExtServices.xml
index 5dd225ba3..04b3850ff 100644
--- a/adservices/tests/cts/AndroidTestDebuggable.ExtServices.xml
+++ b/adservices/tests/cts/AndroidTestDebuggable.ExtServices.xml
@@ -68,6 +68,12 @@
<option name="teardown-command"
value="setprop debug.adservices.consent_manager_debug_mode false"/>
+ <!-- Override MDD background job to avoid race condition. -->
+ <option name="run-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch true"/>
+ <option name="teardown-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch false"/>
+
<!-- Increase the allowed API queries per second -->
<option name="run-command"
value="setprop debug.adservices.sdk_request_permits_per_second 100000"/>
diff --git a/adservices/tests/cts/AndroidTestDebuggable.xml b/adservices/tests/cts/AndroidTestDebuggable.xml
index 4945c1852..d84b3081e 100644
--- a/adservices/tests/cts/AndroidTestDebuggable.xml
+++ b/adservices/tests/cts/AndroidTestDebuggable.xml
@@ -45,6 +45,12 @@
<option name="run-command" value="setprop debug.adservices.consent_manager_debug_mode true" />
<option name="teardown-command" value="setprop debug.adservices.consent_manager_debug_mode false"/>
+ <!-- Override MDD background job to avoid race condition. -->
+ <option name="run-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch true"/>
+ <option name="teardown-command"
+ value="setprop debug.adservices.mdd_background_task_kill_switch false"/>
+
<!-- Increase the allowed API queries per second -->
<option name="run-command" value="setprop debug.adservices.sdk_request_permits_per_second 100000" />
<option name="teardown-command" value="setprop debug.adservices.sdk_request_permits_per_second 1" />
diff --git a/adservices/tests/cts/adid/Android.bp b/adservices/tests/cts/adid/Android.bp
index f06b1fc98..eeb95fe64 100644
--- a/adservices/tests/cts/adid/Android.bp
+++ b/adservices/tests/cts/adid/Android.bp
@@ -36,7 +36,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
@@ -63,11 +64,12 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-extservices"
+ "mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "30",
max_sdk_version: "32",
test_config: "AndroidTest.ExtServices.xml",
manifest: "AndroidManifestExtServices.xml",
-}
+} \ No newline at end of file
diff --git a/adservices/tests/cts/adid/src/com/android/adservices/tests/adid/AdIdManagerTest.java b/adservices/tests/cts/adid/src/com/android/adservices/tests/adid/AdIdManagerTest.java
index 034688c6e..3a5abc4c0 100644
--- a/adservices/tests/cts/adid/src/com/android/adservices/tests/adid/AdIdManagerTest.java
+++ b/adservices/tests/cts/adid/src/com/android/adservices/tests/adid/AdIdManagerTest.java
@@ -17,8 +17,6 @@ package com.android.adservices.tests.adid;
import static com.google.common.truth.Truth.assertWithMessage;
-import static org.junit.Assert.fail;
-
import android.adservices.adid.AdId;
import android.adservices.adid.AdIdManager;
import android.os.LimitExceededException;
@@ -162,19 +160,14 @@ public final class AdIdManagerTest extends CtsAdIdEndToEndTestCase {
@Test
@RequiresLowRamDevice
- public void testAdIdManager_whenDeviceNotSupported_R() {
+ public void testAdIdManager_whenDeviceNotSupported_R() throws Exception {
AdIdManager adIdManager = AdIdManager.get(sContext);
assertWithMessage("adIdManager").that(adIdManager).isNotNull();
AdServicesOutcomeReceiverForTests<AdId> receiver =
new AdServicesOutcomeReceiverForTests<>();
- // NOTE: cannot use assertThrows() as it would cause a NoSuchClassException on R (as
- // JUnit somehow scans the whole class)
- try {
- adIdManager.getAdId(sCallbackExecutor, receiver);
- fail("getAdId() should have thrown IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
+
+ adIdManager.getAdId(sCallbackExecutor, receiver);
+ receiver.assertFailure(IllegalStateException.class);
}
private static String toString(AdId adId) {
diff --git a/adservices/tests/cts/appsetid/Android.bp b/adservices/tests/cts/appsetid/Android.bp
index 628cb1e8c..65087f5f0 100644
--- a/adservices/tests/cts/appsetid/Android.bp
+++ b/adservices/tests/cts/appsetid/Android.bp
@@ -36,7 +36,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
javacflags: ["-parameters"],
sdk_version: "module_current",
@@ -64,7 +65,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-extservices"
+ "mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "31",
diff --git a/adservices/tests/cts/assets/scenarios/data/InvalidJson.json b/adservices/tests/cts/assets/scenarios/data/InvalidJson.json
new file mode 100644
index 000000000..24913e916
--- /dev/null
+++ b/adservices/tests/cts/assets/scenarios/data/InvalidJson.json
@@ -0,0 +1 @@
+this{is_not:real}json \ No newline at end of file
diff --git a/adservices/tests/cts/assets/scenarios/remarketing-cuj-034.json b/adservices/tests/cts/assets/scenarios/remarketing-cuj-034.json
new file mode 100644
index 000000000..eab9b85cd
--- /dev/null
+++ b/adservices/tests/cts/assets/scenarios/remarketing-cuj-034.json
@@ -0,0 +1,69 @@
+{
+ "mocks": [
+ {
+ "request": {
+ "path": "bidding"
+ },
+ "response": {
+ "body": "BiddingLogicV2.js"
+ }
+ },
+ {
+ "request": {
+ "path": "scoring"
+ },
+ "response": {
+ "body": "ScoringLogic.js"
+ }
+ },
+ {
+ "request": {
+ "path": "scoring/trusted"
+ },
+ "response": {
+ "body": "ScoringSignals.json"
+ }
+ },
+ {
+ "request": {
+ "path": "bidding/trusted"
+ },
+ "response": {
+ "body": "BiddingSignals.json"
+ }
+ },
+ {
+ "request": {
+ "path": "bidding/daily/shoes"
+ },
+ "response": {
+ "body": "InvalidJson.json"
+ },
+ "verify_called": true
+ },
+ {
+ "request": {
+ "path": "buyer/reportImpression"
+ },
+ "response": {
+ "body": null
+ }
+ },
+ {
+ "request": {
+ "path": "seller/reportImpression"
+ },
+ "response": {
+ "body": null
+ }
+ }
+ ],
+ "substitutions": {
+ "<daily-update-uri>": "{base_url}/bidding/daily",
+ "<ad-render-uri-1>": "{base_url}/render_ad/1",
+ "<ad-render-uri-2>": "{base_url}/render_ad/2",
+ "<buyer-trusted-bidding-uri>": "{base_url}/bidding/trusted",
+ "<buyer-reporting-uri>": "{base_url}/buyer/reportImpression",
+ "<seller-reporting-uri>": "{base_url}/buyer/reportImpression"
+ }
+} \ No newline at end of file
diff --git a/adservices/tests/cts/assets/scenarios/remarketing-cuj-053.json b/adservices/tests/cts/assets/scenarios/remarketing-cuj-053.json
new file mode 100644
index 000000000..fe53db76f
--- /dev/null
+++ b/adservices/tests/cts/assets/scenarios/remarketing-cuj-053.json
@@ -0,0 +1,71 @@
+{
+ "mocks": [
+ {
+ "request": {
+ "path": "bidding"
+ },
+ "response": {
+ "body": "BiddingLogicV2.js"
+ },
+ "verify_called": true
+ },
+ {
+ "request": {
+ "path": "scoring"
+ },
+ "response": {
+ "body": "ScoringLogic.js",
+ "delay_sec": 30
+ }
+ },
+ {
+ "request": {
+ "path": "scoring/trusted"
+ },
+ "response": {
+ "body": "ScoringSignals.json"
+ }
+ },
+ {
+ "request": {
+ "path": "bidding/trusted"
+ },
+ "response": {
+ "body": "BiddingSignals.json"
+ },
+ "verify_called": true
+ },
+ {
+ "request": {
+ "path": "bidding/daily"
+ },
+ "response": {
+ "body": "DailyUpdateResponse.json"
+ }
+ },
+ {
+ "request": {
+ "path": "buyer/reportImpression"
+ },
+ "response": {
+ "body": null
+ }
+ },
+ {
+ "request": {
+ "path": "seller/reportImpression"
+ },
+ "response": {
+ "body": null
+ }
+ }
+ ],
+ "substitutions": {
+ "<daily-update-uri>": "{base_url}/bidding/daily",
+ "<ad-render-uri-1>": "{base_url}/render_ad/1",
+ "<ad-render-uri-2>": "{base_url}/render_ad/2",
+ "<buyer-trusted-bidding-uri>": "{base_url}/bidding/trusted",
+ "<buyer-reporting-uri>": "{base_url}/buyer/reportImpression",
+ "<seller-reporting-uri>": "{base_url}/buyer/reportImpression"
+ }
+} \ No newline at end of file
diff --git a/adservices/tests/cts/cobalt/Android.bp b/adservices/tests/cts/cobalt/Android.bp
index 613eb3f36..3825b828a 100644
--- a/adservices/tests/cts/cobalt/Android.bp
+++ b/adservices/tests/cts/cobalt/Android.bp
@@ -34,7 +34,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
@@ -61,11 +62,12 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-extservices"
+ "mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "31",
max_sdk_version: "32",
test_config: "AndroidTest.ExtServices.xml",
manifest: "AndroidManifestExtServices.xml",
-}
+} \ No newline at end of file
diff --git a/adservices/tests/cts/endtoends/measurement/Android.bp b/adservices/tests/cts/endtoends/measurement/Android.bp
index 3b9d0c450..75631bcd9 100644
--- a/adservices/tests/cts/endtoends/measurement/Android.bp
+++ b/adservices/tests/cts/endtoends/measurement/Android.bp
@@ -32,7 +32,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
// To fix Pre-submit warning, suggested by farivar@
javacflags: ["-parameters"],
@@ -57,7 +58,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-extservices"
+ "mts-extservices",
+ "mcts-extservices",
],
javacflags: ["-parameters"],
sdk_version: "module_current",
diff --git a/adservices/tests/cts/endtoends/permissions/appoptout/Android.bp b/adservices/tests/cts/endtoends/permissions/appoptout/Android.bp
index 3c14e003f..6aef11243 100644
--- a/adservices/tests/cts/endtoends/permissions/appoptout/Android.bp
+++ b/adservices/tests/cts/endtoends/permissions/appoptout/Android.bp
@@ -41,7 +41,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
min_sdk_version: "33",
manifest: "AndroidManifest.xml",
@@ -73,10 +74,11 @@ android_test {
"cts",
"general-tests",
"mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "31",
max_sdk_version: "32",
test_config: "AndroidTest.ExtServices.xml",
manifest: "AndroidManifestExtServices.xml",
-}
+} \ No newline at end of file
diff --git a/adservices/tests/cts/endtoends/permissions/noperm/Android.bp b/adservices/tests/cts/endtoends/permissions/noperm/Android.bp
index 11698d01e..026ab5116 100644
--- a/adservices/tests/cts/endtoends/permissions/noperm/Android.bp
+++ b/adservices/tests/cts/endtoends/permissions/noperm/Android.bp
@@ -37,7 +37,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
min_sdk_version: "33",
manifest: "AndroidManifest.xml",
@@ -65,10 +66,11 @@ android_test {
"cts",
"general-tests",
"mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "31",
max_sdk_version: "32",
test_config: "AndroidTest.ExtServices.xml",
manifest: "AndroidManifestExtServices.xml",
-}
+} \ No newline at end of file
diff --git a/adservices/tests/cts/endtoends/permissions/notallowed/Android.bp b/adservices/tests/cts/endtoends/permissions/notallowed/Android.bp
index d6c6815db..5f3c3eb08 100644
--- a/adservices/tests/cts/endtoends/permissions/notallowed/Android.bp
+++ b/adservices/tests/cts/endtoends/permissions/notallowed/Android.bp
@@ -37,7 +37,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
min_sdk_version: "33",
manifest: "AndroidManifest.xml",
@@ -66,7 +67,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-extservices"
+ "mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "31",
diff --git a/adservices/tests/cts/endtoends/permissions/valid/Android.bp b/adservices/tests/cts/endtoends/permissions/valid/Android.bp
index e4eb9d560..6e12318e9 100644
--- a/adservices/tests/cts/endtoends/permissions/valid/Android.bp
+++ b/adservices/tests/cts/endtoends/permissions/valid/Android.bp
@@ -41,7 +41,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
min_sdk_version: "33",
manifest: "AndroidManifest.xml",
@@ -74,10 +75,11 @@ android_test {
"cts",
"general-tests",
"mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "31",
max_sdk_version: "32",
test_config: "AndroidTest.ExtServices.xml",
manifest: "AndroidManifestExtServices.xml",
-}
+} \ No newline at end of file
diff --git a/adservices/tests/cts/endtoends/topics/Android.bp b/adservices/tests/cts/endtoends/topics/Android.bp
index 1f70ae2d9..f74b78aa6 100644
--- a/adservices/tests/cts/endtoends/topics/Android.bp
+++ b/adservices/tests/cts/endtoends/topics/Android.bp
@@ -42,7 +42,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
min_sdk_version: "Tiramisu",
manifest: "CtsAdServicesEndToEndTestsManifest.xml",
@@ -56,10 +57,10 @@ android_test {
"cts",
"general-tests",
"mts-extservices",
+ "mcts-extservices",
],
min_sdk_version: "30",
max_sdk_version: "32",
manifest: "CtsAdExtServicesEndToEndTestsManifest.xml",
test_config: "CtsAdExtServicesEndToEndTests.xml",
}
-
diff --git a/adservices/tests/cts/endtoends/topics/appupdate/Android.bp b/adservices/tests/cts/endtoends/topics/appupdate/Android.bp
index 3f10fcd70..a57aac3ca 100644
--- a/adservices/tests/cts/endtoends/topics/appupdate/Android.bp
+++ b/adservices/tests/cts/endtoends/topics/appupdate/Android.bp
@@ -36,7 +36,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
data: [
// Sample App will be installed and uninstalled in the test.
@@ -68,6 +69,7 @@ android_test {
"cts",
"general-tests",
"mts-extservices",
+ "mcts-extservices",
],
data: [
// Sample App will be installed and uninstalled in the test.
@@ -78,4 +80,4 @@ android_test {
max_sdk_version: "32",
test_config: "AndroidTest.ExtServices.xml",
manifest: "AndroidManifestExtServices.xml",
-}
+} \ No newline at end of file
diff --git a/adservices/tests/cts/endtoends/topics/connection/Android.bp b/adservices/tests/cts/endtoends/topics/connection/Android.bp
index 17f20d501..ec896ecd2 100644
--- a/adservices/tests/cts/endtoends/topics/connection/Android.bp
+++ b/adservices/tests/cts/endtoends/topics/connection/Android.bp
@@ -36,7 +36,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
@@ -64,10 +65,11 @@ android_test {
"cts",
"general-tests",
"mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "31",
max_sdk_version: "32",
test_config: "AndroidTest.ExtServices.xml",
manifest: "AndroidManifestExtServices.xml",
-}
+} \ No newline at end of file
diff --git a/adservices/tests/cts/endtoends/topics/mdd/Android.bp b/adservices/tests/cts/endtoends/topics/mdd/Android.bp
index fde9c1592..c67c58948 100644
--- a/adservices/tests/cts/endtoends/topics/mdd/Android.bp
+++ b/adservices/tests/cts/endtoends/topics/mdd/Android.bp
@@ -36,7 +36,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
@@ -64,10 +65,11 @@ android_test {
"cts",
"general-tests",
"mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "31",
max_sdk_version: "32",
test_config: "AndroidTest.ExtServices.xml",
manifest: "AndroidManifestExtServices.xml",
-}
+} \ No newline at end of file
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 ab4b43272..9848c49a5 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
@@ -51,7 +51,7 @@ import java.util.concurrent.Executors;
public final class TopicsManagerTest extends CtsTopicsEndToEndTestCase {
// Test constants for testing encryption
- static final String PUBLIC_KEY_BASE64 = "rSJBSUYG0ebvfW1AXCWO0CMGMJhDzpfQm3eLyw1uxX8=";
+ static final String TEST_PUBLIC_KEY_BASE64 = "rSJBSUYG0ebvfW1AXCWO0CMGMJhDzpfQm3eLyw1uxX8=";
// The JobId of the Epoch Computation.
private static final int EPOCH_JOB_ID = 2;
@@ -470,6 +470,8 @@ public final class TopicsManagerTest extends CtsTopicsEndToEndTestCase {
// Set flags for encryption test
flags.setFlag(FlagsConstants.KEY_TOPICS_ENCRYPTION_ENABLED, true);
flags.setFlag(FlagsConstants.KEY_ENABLE_DATABASE_SCHEMA_VERSION_9, true);
+ // Override encryption key for testing
+ flags.setFlag(FlagsConstants.KEY_TOPICS_TEST_ENCRYPTION_PUBLIC_KEY, TEST_PUBLIC_KEY_BASE64);
// The Test App has 1 SDK: sdk6
// sdk6 calls the Topics API.
@@ -519,7 +521,7 @@ public final class TopicsManagerTest extends CtsTopicsEndToEndTestCase {
assertThat(sdk6Result.getEncryptedTopics()).hasSize(1);
assertThat(sdk6Result.getEncryptedTopics().get(0).getEncryptedTopic()).isNotNull();
assertThat(sdk6Result.getEncryptedTopics().get(0).getKeyIdentifier())
- .isEqualTo(PUBLIC_KEY_BASE64);
+ .isEqualTo(TEST_PUBLIC_KEY_BASE64);
assertThat(sdk6Result.getEncryptedTopics().get(0).getEncapsulatedKey()).isNotNull();
}
diff --git a/adservices/tests/cts/extdata/Android.bp b/adservices/tests/cts/extdata/Android.bp
index 13a5b3f90..0e68e1491 100644
--- a/adservices/tests/cts/extdata/Android.bp
+++ b/adservices/tests/cts/extdata/Android.bp
@@ -36,7 +36,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-adservices"
+ "mts-adservices",
+ "mcts-adservices",
],
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
@@ -63,7 +64,8 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-extservices"
+ "mts-extservices",
+ "mcts-extservices",
],
sdk_version: "module_current",
min_sdk_version: "30",
diff --git a/adservices/tests/cts/hosttests/Android.bp b/adservices/tests/cts/hosttests/Android.bp
index 4d9168f7e..b81adbf3f 100644
--- a/adservices/tests/cts/hosttests/Android.bp
+++ b/adservices/tests/cts/hosttests/Android.bp
@@ -25,6 +25,7 @@ java_test_host {
"cts",
"general-tests",
"mts-adservices",
+ "mcts-adservices",
],
libs: [
"cts-tradefed",
@@ -50,6 +51,7 @@ java_test_host {
"cts",
"general-tests",
"mts-extservices",
+ "mcts-extservices",
],
libs: [
"cts-tradefed",
diff --git a/adservices/tests/cts/hosttests/app/Android.bp b/adservices/tests/cts/hosttests/app/Android.bp
index 488adf978..486a7072c 100644
--- a/adservices/tests/cts/hosttests/app/Android.bp
+++ b/adservices/tests/cts/hosttests/app/Android.bp
@@ -42,5 +42,6 @@ android_test_helper_app {
"cts",
"general-tests",
"mts-adservices",
+ "mcts-adservices",
],
}
diff --git a/adservices/tests/cts/sandbox/adid/Android.bp b/adservices/tests/cts/sandbox/adid/Android.bp
index 8f9d9c0cb..fadb81f05 100644
--- a/adservices/tests/cts/sandbox/adid/Android.bp
+++ b/adservices/tests/cts/sandbox/adid/Android.bp
@@ -42,5 +42,6 @@ android_test {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
}
diff --git a/adservices/tests/cts/sandbox/appsetid/Android.bp b/adservices/tests/cts/sandbox/appsetid/Android.bp
index 78bf40f23..1bafab376 100644
--- a/adservices/tests/cts/sandbox/appsetid/Android.bp
+++ b/adservices/tests/cts/sandbox/appsetid/Android.bp
@@ -42,5 +42,6 @@ android_test {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
}
diff --git a/adservices/tests/cts/sandbox/fledge/Android.bp b/adservices/tests/cts/sandbox/fledge/Android.bp
index c4a64f29f..4df33f5b0 100644
--- a/adservices/tests/cts/sandbox/fledge/Android.bp
+++ b/adservices/tests/cts/sandbox/fledge/Android.bp
@@ -45,5 +45,6 @@ android_test {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
}
diff --git a/adservices/tests/cts/sandbox/measurement/Android.bp b/adservices/tests/cts/sandbox/measurement/Android.bp
index f2b7969be..2bc189122 100644
--- a/adservices/tests/cts/sandbox/measurement/Android.bp
+++ b/adservices/tests/cts/sandbox/measurement/Android.bp
@@ -43,5 +43,6 @@ android_test {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
}
diff --git a/adservices/tests/cts/sandbox/topics/Android.bp b/adservices/tests/cts/sandbox/topics/Android.bp
index 15cf9d41c..b4602dda8 100644
--- a/adservices/tests/cts/sandbox/topics/Android.bp
+++ b/adservices/tests/cts/sandbox/topics/Android.bp
@@ -43,5 +43,6 @@ android_test {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
}
diff --git a/adservices/tests/cts/src/android/adservices/cts/CustomAudienceApiCtsTest.java b/adservices/tests/cts/src/android/adservices/cts/CustomAudienceApiCtsTest.java
index e458b0d50..99b4e4ba7 100644
--- a/adservices/tests/cts/src/android/adservices/cts/CustomAudienceApiCtsTest.java
+++ b/adservices/tests/cts/src/android/adservices/cts/CustomAudienceApiCtsTest.java
@@ -26,8 +26,14 @@ import static android.adservices.customaudience.CustomAudienceFixture.VALID_NAME
import static android.adservices.customaudience.CustomAudienceFixture.VALID_USER_BIDDING_SIGNALS;
import static android.adservices.customaudience.CustomAudienceFixture.getValidFetchUriByBuyer;
-import static com.android.adservices.service.Flags.FLEDGE_CUSTOM_AUDIENCE_MAX_NAME_SIZE_B;
-import static com.android.adservices.service.Flags.FLEDGE_FETCH_CUSTOM_AUDIENCE_MAX_USER_BIDDING_SIGNALS_SIZE_B;
+import static com.android.adservices.service.FlagsConstants.KEY_ENABLE_ENROLLMENT_TEST_SEED;
+import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_COUNT;
+import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_NAME_SIZE_B;
+import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_NUM_ADS;
+import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_OWNER_COUNT;
+import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_PER_APP_MAX_COUNT;
+import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED;
+import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_MAX_USER_BIDDING_SIGNALS_SIZE_B;
import static com.google.common.truth.Truth.assertThat;
@@ -52,16 +58,15 @@ import android.net.Uri;
import android.os.Process;
import android.util.Pair;
+import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.adservices.common.AdServicesDeviceSupportedRule;
-import com.android.adservices.common.AdServicesFlagsSetterRule;
import com.android.adservices.common.AdservicesTestHelper;
-import com.android.adservices.common.SdkLevelSupportRule;
-import com.android.adservices.service.PhFlagsFixture;
+import com.android.adservices.common.RequiresSdkLevelAtLeastS;
+import com.android.adservices.common.annotations.SetFlagEnabled;
+import com.android.adservices.common.annotations.SetIntegerFlag;
import com.android.adservices.service.devapi.DevContext;
import com.android.adservices.service.devapi.DevContextFilter;
-import com.android.modules.utils.build.SdkLevel;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
@@ -70,7 +75,6 @@ import com.google.common.util.concurrent.MoreExecutors;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import java.util.ArrayList;
@@ -78,7 +82,10 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-public class CustomAudienceApiCtsTest extends ForegroundCtsTest {
+@RequiresSdkLevelAtLeastS // TODO(b/291488819) - Remove SDK Level check if Fledge is enabled on R.
+@SetFlagEnabled(KEY_ENABLE_ENROLLMENT_TEST_SEED)
+public final class CustomAudienceApiCtsTest extends ForegroundCtsTestCase {
+
private AdvertisingCustomAudienceClient mClient;
private TestAdvertisingCustomAudienceClient mTestClient;
@@ -93,24 +100,9 @@ public class CustomAudienceApiCtsTest extends ForegroundCtsTest {
private final ArrayList<Pair<AdTechIdentifier, String>> mCustomAudiencesToCleanUp =
new ArrayList<>();
- // TODO(b/291488819) - Remove SDK Level check if Fledge is enabled on R.
- @Rule(order = 0)
- public final SdkLevelSupportRule sdkLevel = SdkLevelSupportRule.forAtLeastS();
-
- // Skip the test if it runs on unsupported platforms.
- @Rule(order = 1)
- public final AdServicesDeviceSupportedRule adServicesDeviceSupportedRule =
- new AdServicesDeviceSupportedRule();
-
- @Rule(order = 2)
- public final AdServicesFlagsSetterRule flags =
- AdServicesFlagsSetterRule.forGlobalKillSwitchDisabledTests()
- .setCompatModeFlags()
- .setPpapiAppAllowList(sContext.getPackageName());
-
@Before
- public void setup() throws InterruptedException {
- if (SdkLevel.isAtLeastT()) {
+ public void setup() throws Exception {
+ if (sdkLevel.isAtLeastT()) {
assertForegroundActivityStarted();
}
@@ -131,16 +123,14 @@ public class CustomAudienceApiCtsTest extends ForegroundCtsTest {
InstrumentationRegistry.getInstrumentation()
.getUiAutomation()
.adoptShellPermissionIdentity(Manifest.permission.WRITE_DEVICE_CONFIG);
- PhFlagsFixture.overrideEnableEnrollmentSeed(true);
// Kill AdServices process
AdservicesTestHelper.killAdservicesProcess(sContext);
}
@After
- public void tearDown() throws ExecutionException, InterruptedException, TimeoutException {
+ public void tearDown() throws Exception {
leaveJoinedCustomAudiences();
- PhFlagsFixture.overrideEnableEnrollmentSeed(false);
}
@Test
@@ -274,27 +264,23 @@ public class CustomAudienceApiCtsTest extends ForegroundCtsTest {
}
@Test
+ @SetIntegerFlag(name = KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_NUM_ADS, value = 2)
public void testJoinCustomAudience_invalidNumberOfAds_fail() {
- PhFlagsFixture.overrideFledgeCustomAudienceMaxNumAds(2);
- try {
- CustomAudience customAudienceWithInvalidNumberOfAds =
- CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1)
- .setAds(
- ImmutableList.of(
- AdDataFixture.getValidAdDataByBuyer(VALID_BUYER_1, 1),
- AdDataFixture.getValidAdDataByBuyer(VALID_BUYER_1, 2),
- AdDataFixture.getValidAdDataByBuyer(VALID_BUYER_1, 3)))
- .build();
-
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> joinCustomAudience(customAudienceWithInvalidNumberOfAds));
- assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
- assertThat(exception).hasCauseThat().hasMessageThat().isEqualTo(null);
- } finally {
- PhFlagsFixture.overrideFledgeCustomAudienceMaxNumAds(100);
- }
+ CustomAudience customAudienceWithInvalidNumberOfAds =
+ CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1)
+ .setAds(
+ ImmutableList.of(
+ AdDataFixture.getValidAdDataByBuyer(VALID_BUYER_1, 1),
+ AdDataFixture.getValidAdDataByBuyer(VALID_BUYER_1, 2),
+ AdDataFixture.getValidAdDataByBuyer(VALID_BUYER_1, 3)))
+ .build();
+
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> joinCustomAudience(customAudienceWithInvalidNumberOfAds));
+ assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
+ assertThat(exception).hasCauseThat().hasMessageThat().isNull();
}
@Test
@@ -327,384 +313,347 @@ public class CustomAudienceApiCtsTest extends ForegroundCtsTest {
}
@Test
+ @SetIntegerFlag(name = KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_COUNT, value = 2)
+ @SetIntegerFlag(name = KEY_FLEDGE_CUSTOM_AUDIENCE_PER_APP_MAX_COUNT, value = 1000)
+ @SetIntegerFlag(name = KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_OWNER_COUNT, value = 1000)
public void testJoinCustomAudience_maxTotalCustomAudiences_fail() {
- PhFlagsFixture.overrideFledgeCustomAudienceMaxCount(2);
- PhFlagsFixture.overrideFledgeCustomAudiencePerAppMaxCount(1000);
- PhFlagsFixture.overrideFledgeCustomAudienceMaxOwnerCount(1000);
- try {
- CustomAudience customAudience1 =
- CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1)
- .setName("CA1")
- .build();
- CustomAudience customAudience2 =
- CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1)
- .setName("CA2")
- .build();
- CustomAudience customAudience3 =
- CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1)
- .setName("CA3")
- .build();
-
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> {
- joinCustomAudience(customAudience1);
- joinCustomAudience(customAudience2);
- joinCustomAudience(customAudience3);
- });
- assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
- assertThat(exception).hasCauseThat().hasMessageThat().isEqualTo(null);
- } finally {
- PhFlagsFixture.overrideFledgeCustomAudienceMaxCount(4000);
- }
+ CustomAudience customAudience1 =
+ CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1).setName("CA1").build();
+ CustomAudience customAudience2 =
+ CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1).setName("CA2").build();
+ CustomAudience customAudience3 =
+ CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1).setName("CA3").build();
+
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> {
+ joinCustomAudience(customAudience1);
+ joinCustomAudience(customAudience2);
+ joinCustomAudience(customAudience3);
+ });
+ assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
+ assertThat(exception).hasCauseThat().hasMessageThat().isNull();
}
@Test
+ @SetIntegerFlag(name = KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_COUNT, value = 4000)
+ @SetIntegerFlag(name = KEY_FLEDGE_CUSTOM_AUDIENCE_PER_APP_MAX_COUNT, value = 2)
+ @SetIntegerFlag(name = KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_OWNER_COUNT, value = 1000)
public void testJoinCustomAudience_maxCustomAudiencesPerApp_fail() {
- PhFlagsFixture.overrideFledgeCustomAudienceMaxCount(4000);
- PhFlagsFixture.overrideFledgeCustomAudiencePerAppMaxCount(2);
- PhFlagsFixture.overrideFledgeCustomAudienceMaxOwnerCount(1000);
- try {
- CustomAudience customAudience1 =
- CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1)
- .setName("CA1")
- .build();
- CustomAudience customAudience2 =
- CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1)
- .setName("CA2")
- .build();
- CustomAudience customAudience3 =
- CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1)
- .setName("CA3")
- .build();
-
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> {
- joinCustomAudience(customAudience1);
- joinCustomAudience(customAudience2);
- joinCustomAudience(customAudience3);
- });
- assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
- assertThat(exception).hasCauseThat().hasMessageThat().isEqualTo(null);
- } finally {
- PhFlagsFixture.overrideFledgeCustomAudiencePerAppMaxCount(1000);
- }
+ CustomAudience customAudience1 =
+ CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1).setName("CA1").build();
+ CustomAudience customAudience2 =
+ CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1).setName("CA2").build();
+ CustomAudience customAudience3 =
+ CustomAudienceFixture.getValidBuilderForBuyer(VALID_BUYER_1).setName("CA3").build();
+
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> {
+ joinCustomAudience(customAudience1);
+ joinCustomAudience(customAudience2);
+ joinCustomAudience(customAudience3);
+ });
+ assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
+ assertThat(exception).hasCauseThat().hasMessageThat().isNull();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validFetchUri_validRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(
- getValidFetchUriByBuyer(VALID_BUYER_1))
- .build();
-
- // Without an actual server to respond to this request, the service will fail while
- // executing the HTTP request and throw an IllegalStateException. If a request field was
- // invalid, the service will fail before executing the HTTP request and throw an
- // IllegalArgumentException.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(
+ getValidFetchUriByBuyer(VALID_BUYER_1))
+ .build();
+
+ // Without an actual server to respond to this request, the service will fail while
+ // executing the HTTP request and throw an IllegalStateException. If a request field was
+ // invalid, the service will fail before executing the HTTP request and throw an
+ // IllegalArgumentException.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validFetchUri_validRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_validFetchUri_validRequest();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_unenrolledFetchUri_invalidRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
-
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(Uri.parse("invalid-uri.com"))
- .build();
-
- // Without an actual server to respond to this request, the service will fail while
- // executing the HTTP request and throw an IllegalStateException. If a request field was
- // invalid, the service will fail before executing the HTTP request and throw an
- // IllegalArgumentException.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- // A valid buyer will not be extracted from an invalid uri, thus failing due to lack of
- // authorization.
- assertThat(exception).hasCauseThat().isInstanceOf(SecurityException.class);
- assertThat(exception)
- .hasCauseThat()
- .hasMessageThat()
- .isEqualTo(SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(Uri.parse("invalid-uri.com")).build();
+
+ // Without an actual server to respond to this request, the service will fail while
+ // executing the HTTP request and throw an IllegalStateException. If a request field was
+ // invalid, the service will fail before executing the HTTP request and throw an
+ // IllegalArgumentException.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ // A valid buyer will not be extracted from an invalid uri, thus failing due to lack of
+ // authorization.
+ assertThat(exception).hasCauseThat().isInstanceOf(SecurityException.class);
+ assertThat(exception)
+ .hasCauseThat()
+ .hasMessageThat()
+ .isEqualTo(SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_unenrolledFetchUri_invalidRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_unenrolledFetchUri_invalidRequest();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validName_validRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
-
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(
- getValidFetchUriByBuyer(VALID_BUYER_1))
- .setName(VALID_NAME)
- .build();
-
- // Without an actual server to respond to this request, the service will fail while
- // executing the HTTP request and throw an IllegalStateException. If a request field was
- // invalid, the service will fail before executing the HTTP request and throw an
- // IllegalArgumentException.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(
+ getValidFetchUriByBuyer(VALID_BUYER_1))
+ .setName(VALID_NAME)
+ .build();
+
+ // Without an actual server to respond to this request, the service will fail while
+ // executing the HTTP request and throw an IllegalStateException. If a request field was
+ // invalid, the service will fail before executing the HTTP request and throw an
+ // IllegalArgumentException.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validName_validRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_validName_validRequest();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_tooLongName_invalidRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
- // Use a clearly small size limit.
- PhFlagsFixture.overrideFledgeCustomAudienceMaxNameSizeB(1);
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(
- getValidFetchUriByBuyer(VALID_BUYER_1))
- .setName(VALID_NAME)
- .build();
-
- // Without an actual server to respond to this request, the service will fail while
- // executing the HTTP request and throw an IllegalStateException. If a request field was
- // invalid, the service will fail before executing the HTTP request and throw an
- // IllegalArgumentException.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- // The name exceeds size limit.
- assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- PhFlagsFixture.overrideFledgeCustomAudienceMaxNameSizeB(
- FLEDGE_CUSTOM_AUDIENCE_MAX_NAME_SIZE_B);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+ // Use a clearly small size limit.
+ flags.setFlag(KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_NAME_SIZE_B, 1);
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(
+ getValidFetchUriByBuyer(VALID_BUYER_1))
+ .setName(VALID_NAME)
+ .build();
+
+ // Without an actual server to respond to this request, the service will fail while
+ // executing the HTTP request and throw an IllegalStateException. If a request field was
+ // invalid, the service will fail before executing the HTTP request and throw an
+ // IllegalArgumentException.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ // The name exceeds size limit.
+ assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_tooLongName_invalidRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_tooLongName_invalidRequest();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validActivationTime_validRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(
- getValidFetchUriByBuyer(VALID_BUYER_1))
- .setActivationTime(VALID_ACTIVATION_TIME)
- .build();
-
- // Without an actual server to respond to this request, the service will fail while
- // executing the HTTP request and throw an IllegalStateException. If a request field was
- // invalid, the service will fail before executing the HTTP request and throw an
- // IllegalArgumentException.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(
+ getValidFetchUriByBuyer(VALID_BUYER_1))
+ .setActivationTime(VALID_ACTIVATION_TIME)
+ .build();
+
+ // Without an actual server to respond to this request, the service will fail while
+ // executing the HTTP request and throw an IllegalStateException. If a request field was
+ // invalid, the service will fail before executing the HTTP request and throw an
+ // IllegalArgumentException.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validActivationTime_validRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_validActivationTime_validRequest();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_activationExceedsDelay_invalidRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(
- getValidFetchUriByBuyer(VALID_BUYER_1))
- .setActivationTime(INVALID_DELAYED_ACTIVATION_TIME)
- .build();
-
- // Without an actual server to respond to this request, the service will fail while
- // executing the HTTP request and throw an IllegalStateException. If a request field was
- // invalid, the service will fail before executing the HTTP request and throw an
- // IllegalArgumentException.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- // The activation time exceeds delay limit.
- assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(
+ getValidFetchUriByBuyer(VALID_BUYER_1))
+ .setActivationTime(INVALID_DELAYED_ACTIVATION_TIME)
+ .build();
+
+ // Without an actual server to respond to this request, the service will fail while
+ // executing the HTTP request and throw an IllegalStateException. If a request field was
+ // invalid, the service will fail before executing the HTTP request and throw an
+ // IllegalArgumentException.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ // The activation time exceeds delay limit.
+ assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_activationExceedsDelay_invalidRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_activationExceedsDelay_invalidRequest();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validExpirationTime_validRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(
- getValidFetchUriByBuyer(VALID_BUYER_1))
- .setExpirationTime(VALID_EXPIRATION_TIME)
- .build();
-
- // Without an actual server to respond to this request, the service will fail while
- // executing the HTTP request and throw an IllegalStateException. If a request field was
- // invalid, the service will fail before executing the HTTP request and throw an
- // IllegalArgumentException.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(
+ getValidFetchUriByBuyer(VALID_BUYER_1))
+ .setExpirationTime(VALID_EXPIRATION_TIME)
+ .build();
+
+ // Without an actual server to respond to this request, the service will fail while
+ // executing the HTTP request and throw an IllegalStateException. If a request field was
+ // invalid, the service will fail before executing the HTTP request and throw an
+ // IllegalArgumentException.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validExpirationTime_validRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_validExpirationTime_validRequest();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_beyondMaxExpiration_invalidRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
-
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(
- getValidFetchUriByBuyer(VALID_BUYER_1))
- .setExpirationTime(INVALID_BEYOND_MAX_EXPIRATION_TIME)
- .build();
-
- // Without an actual server to respond to this request, the service will fail while
- // executing the HTTP request and throw an IllegalStateException. If a request field was
- // invalid, the service will fail before executing the HTTP request and throw an
- // IllegalArgumentException.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- // The expiration time exceeds max limit.
- assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(
+ getValidFetchUriByBuyer(VALID_BUYER_1))
+ .setExpirationTime(INVALID_BEYOND_MAX_EXPIRATION_TIME)
+ .build();
+
+ // Without an actual server to respond to this request, the service will fail while
+ // executing the HTTP request and throw an IllegalStateException. If a request field was
+ // invalid, the service will fail before executing the HTTP request and throw an
+ // IllegalArgumentException.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ // The expiration time exceeds max limit.
+ assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_beyondMaxExpiration_invalidRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_beyondMaxExpiration_invalidRequest();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validUserBiddingSignals_validRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(
- getValidFetchUriByBuyer(VALID_BUYER_1))
- .setUserBiddingSignals(VALID_USER_BIDDING_SIGNALS)
- .build();
-
- // Without an actual server to respond to this request, the service will fail while
- // executing the HTTP request and throw an IllegalStateException. If a request field was
- // invalid, the service will fail before executing the HTTP request and throw an
- // IllegalArgumentException.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(
+ getValidFetchUriByBuyer(VALID_BUYER_1))
+ .setUserBiddingSignals(VALID_USER_BIDDING_SIGNALS)
+ .build();
+
+ // Without an actual server to respond to this request, the service will fail while
+ // executing the HTTP request and throw an IllegalStateException. If a request field was
+ // invalid, the service will fail before executing the HTTP request and throw an
+ // IllegalArgumentException.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ assertThat(exception.getCause()).isInstanceOf(IllegalStateException.class);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_validUserBiddingSignals_validRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_validUserBiddingSignals_validRequest();
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_tooBigUserBiddingSignals_invalidRequest() {
- try {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(true);
- // Use a clearly small size limit.
- PhFlagsFixture.overrideFledgeFetchCustomAudienceMaxUserBiddingSignalsSizeB(1);
- FetchAndJoinCustomAudienceRequest request =
- new FetchAndJoinCustomAudienceRequest.Builder(
- getValidFetchUriByBuyer(VALID_BUYER_1))
- .setUserBiddingSignals(VALID_USER_BIDDING_SIGNALS)
- .build();
-
- // Without an actual server response, we expect an IllegalStateException if the request
- // was well-formed and valid.
- Exception exception =
- assertThrows(
- ExecutionException.class,
- () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
- // The user bidding signals exceeds size limit.
- assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
- } finally {
- PhFlagsFixture.overrideFledgeFetchCustomAudienceEnabled(false);
- PhFlagsFixture.overrideFledgeFetchCustomAudienceMaxUserBiddingSignalsSizeB(
- FLEDGE_FETCH_CUSTOM_AUDIENCE_MAX_USER_BIDDING_SIGNALS_SIZE_B);
- }
+ // NOTE: not using flag annotations because it's called by other test
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED, true);
+ // Use a clearly small size limit.
+ flags.setFlag(KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_MAX_USER_BIDDING_SIGNALS_SIZE_B, 1);
+ FetchAndJoinCustomAudienceRequest request =
+ new FetchAndJoinCustomAudienceRequest.Builder(
+ getValidFetchUriByBuyer(VALID_BUYER_1))
+ .setUserBiddingSignals(VALID_USER_BIDDING_SIGNALS)
+ .build();
+
+ // Without an actual server response, we expect an IllegalStateException if the request
+ // was well-formed and valid.
+ Exception exception =
+ assertThrows(
+ ExecutionException.class,
+ () -> fetchAndJoinCustomAudience(request, VALID_BUYER_1, VALID_NAME));
+ // The user bidding signals exceeds size limit.
+ assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
}
@Test
+ @FlakyTest(bugId = 319330548)
public void testFetchAndJoinCustomAudience_tooBigUserBiddingSignals_invalidRequest_getMethod() {
createClientUsingGetMethod();
testFetchAndJoinCustomAudience_tooBigUserBiddingSignals_invalidRequest();
diff --git a/adservices/tests/cts/src/android/adservices/cts/ForegroundCtsTest.java b/adservices/tests/cts/src/android/adservices/cts/ForegroundCtsTestCase.java
index 6aeb4be79..7fd36268c 100644
--- a/adservices/tests/cts/src/android/adservices/cts/ForegroundCtsTest.java
+++ b/adservices/tests/cts/src/android/adservices/cts/ForegroundCtsTestCase.java
@@ -16,11 +16,10 @@
package android.adservices.cts;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertWithMessage;
-import android.content.Context;
-
-import androidx.test.core.app.ApplicationProvider;
+import android.os.Build;
+import android.util.Log;
import com.android.modules.utils.build.SdkLevel;
@@ -30,13 +29,17 @@ import org.junit.BeforeClass;
import java.time.Duration;
import java.util.concurrent.TimeoutException;
-public class ForegroundCtsTest {
- // If the context is initialized in the setup method the importance of our foreground
- // service will be IMPORTANCE_FOREGROUND_SERVICE (125) instead of
+abstract class ForegroundCtsTestCase extends CtsAdServicesDeviceTestCase {
+
+ private static final String TAG = ForegroundCtsTestCase.class.getSimpleName();
+
+ // NOTICE: if the context used by tests is initialized in the setup method the importance of our
+ // foreground service will be IMPORTANCE_FOREGROUND_SERVICE (125) instead of
// IMPORTANCE_FOREGROUND (100) on some platforms only.
- // See http://ag/c/platform/packages/modules/AdServices/+/19607471/comments/e6767fdc_971415d0
- protected static final Context sContext = ApplicationProvider.getApplicationContext();
- private static boolean sSimpleActivityStarted = false;
+ // This class is indirectly extending AdServicesCtsTestCase - which sets sContext outside any
+ // JUnit @Before / @BeforeClass method - so the process has the proper importance.
+
+ private static boolean sSimpleActivityStarted;
/**
* Starts a foreground activity to make the test process a foreground one to pass PPAPI and SDK
@@ -45,15 +48,22 @@ public class ForegroundCtsTest {
protected static void makeTestProcessForeground() throws TimeoutException {
// PPAPI foreground checks are not done on S-, so no need for the SimpleActivity
if (SdkLevel.isAtLeastT()) {
+ Log.d(TAG, "Starting activity on T+ (and waiting for 2s)");
SimpleActivity.startAndWait(sContext, Duration.ofSeconds(2));
+ Log.d(TAG, "Activity started");
sSimpleActivityStarted = true;
+ } else {
+ Log.d(TAG, "Not starting activity on device running " + Build.VERSION.SDK_INT);
}
}
/** Terminates the SimpleActivity */
protected static void shutdownForegroundActivity() {
if (SdkLevel.isAtLeastT()) {
+ Log.d(TAG, "Stopping activity on T+");
SimpleActivity.stop(sContext);
+ } else {
+ Log.d(TAG, "Not stopping activity on device running " + Build.VERSION.SDK_INT);
}
}
@@ -67,7 +77,9 @@ public class ForegroundCtsTest {
shutdownForegroundActivity();
}
- protected void assertForegroundActivityStarted() {
- assertTrue("Foreground activity didn't start successfully", sSimpleActivityStarted);
+ protected static void assertForegroundActivityStarted() {
+ assertWithMessage("Foreground activity started successfully")
+ .that(sSimpleActivityStarted)
+ .isTrue();
}
}
diff --git a/adservices/tests/cts/src/android/adservices/cts/TestAdSelectionManagerTest.java b/adservices/tests/cts/src/android/adservices/cts/TestAdSelectionManagerTest.java
index 380665aa9..4fe1ffa77 100644
--- a/adservices/tests/cts/src/android/adservices/cts/TestAdSelectionManagerTest.java
+++ b/adservices/tests/cts/src/android/adservices/cts/TestAdSelectionManagerTest.java
@@ -46,19 +46,17 @@ import android.os.Process;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.adservices.LoggerFactory;
-import com.android.adservices.common.AdServicesDeviceSupportedRule;
-import com.android.adservices.common.AdServicesFlagsSetterRule;
import com.android.adservices.common.AdservicesTestHelper;
-import com.android.adservices.common.SdkLevelSupportRule;
+import com.android.adservices.common.RequiresSdkLevelAtLeastS;
+import com.android.adservices.common.annotations.SetFlagDisabled;
+import com.android.adservices.common.annotations.SetFlagEnabled;
import com.android.adservices.service.devapi.DevContext;
import com.android.adservices.service.devapi.DevContextFilter;
-import com.android.modules.utils.build.SdkLevel;
import com.google.common.util.concurrent.ListenableFuture;
import org.junit.Assume;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import java.util.ArrayList;
@@ -67,7 +65,12 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
-public class TestAdSelectionManagerTest extends ForegroundCtsTest {
+@RequiresSdkLevelAtLeastS // TODO(b/291488819) - Remove SDK Level check if Fledge is enabled on R.
+@SetFlagEnabled(KEY_ENABLE_ENROLLMENT_TEST_SEED)
+@SetFlagDisabled(KEY_ENFORCE_ISOLATE_MAX_HEAP_SIZE)
+@SetFlagDisabled(KEY_ISOLATE_MAX_HEAP_SIZE_BYTES)
+public final class TestAdSelectionManagerTest extends ForegroundCtsTestCase {
+
private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger();
private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();
@@ -100,27 +103,10 @@ public class TestAdSelectionManagerTest extends ForegroundCtsTest {
private TestAdSelectionClient mTestAdSelectionClient;
private boolean mIsDebugMode;
- // TODO(b/291488819) - Remove SDK Level check if Fledge is enabled on R.
- @Rule(order = 0)
- public final SdkLevelSupportRule sdkLevel = SdkLevelSupportRule.forAtLeastS();
-
- // Skip the test if it runs on unsupported platforms.
- @Rule(order = 1)
- public final AdServicesDeviceSupportedRule adServicesDeviceSupportedRule =
- new AdServicesDeviceSupportedRule();
-
- @Rule(order = 2)
- public final AdServicesFlagsSetterRule flags =
- AdServicesFlagsSetterRule.forGlobalKillSwitchDisabledTests()
- .setCompatModeFlags()
- .setPpapiAppAllowList(sContext.getPackageName())
- .setFlag(KEY_ENFORCE_ISOLATE_MAX_HEAP_SIZE, false)
- .setFlag(KEY_ISOLATE_MAX_HEAP_SIZE_BYTES, false)
- .setFlag(KEY_ENABLE_ENROLLMENT_TEST_SEED, true);
-
@Before
public void setup() {
- if (SdkLevel.isAtLeastT()) {
+
+ if (sdkLevel.isAtLeastT()) {
assertForegroundActivityStarted();
}
diff --git a/adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java b/adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java
index 686882ee3..1fb43a294 100644
--- a/adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java
+++ b/adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java
@@ -49,6 +49,7 @@ import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class AdSelectionTest extends FledgeScenarioTest {
@@ -228,17 +229,17 @@ public class AdSelectionTest extends FledgeScenarioTest {
ScenarioDispatcher.fromScenario(
"scenarios/remarketing-cuj-default.json", getCacheBusterPrefix());
setupDefaultMockWebServer(dispatcher);
+ AdSelectionConfig config = makeAdSelectionConfig();
CustomAudience customAudience =
makeCustomAudience(SHOES_CA)
- .setExpirationTime(Instant.now().plus(1, ChronoUnit.SECONDS))
+ .setExpirationTime(Instant.now().plus(5, ChronoUnit.SECONDS))
.build();
- AdSelectionConfig config = makeAdSelectionConfig();
- mCustomAudienceClient.joinCustomAudience(customAudience).get(1, TimeUnit.SECONDS);
+ mCustomAudienceClient.joinCustomAudience(customAudience).get(5, TimeUnit.SECONDS);
Log.d(TAG, "Joined custom audience");
// Make a call to verify ad selection succeeds before timing out.
mAdSelectionClient.selectAds(config).get(TIMEOUT, TimeUnit.SECONDS);
- Thread.sleep(4000);
+ Thread.sleep(7000);
Exception selectAdsException =
assertThrows(
@@ -361,6 +362,32 @@ public class AdSelectionTest extends FledgeScenarioTest {
.containsAtLeastElementsIn(dispatcher.getVerifyCalledPaths());
}
+ @Test
+ public void testAdSelection_withHighLatencyBackend_doesNotWinAuction() throws Exception {
+ ScenarioDispatcher dispatcher =
+ ScenarioDispatcher.fromScenario(
+ "scenarios/remarketing-cuj-053.json", getCacheBusterPrefix());
+ setupDefaultMockWebServer(dispatcher);
+ AdSelectionConfig config = makeAdSelectionConfig();
+
+ try {
+ joinCustomAudience(SHIRTS_CA);
+ Exception selectAdsException =
+ assertThrows(
+ ExecutionException.class,
+ () ->
+ mAdSelectionClient
+ .selectAds(config)
+ .get(TIMEOUT, TimeUnit.SECONDS));
+ assertThat(selectAdsException.getCause()).isInstanceOf(TimeoutException.class);
+ } finally {
+ leaveCustomAudience(SHIRTS_CA);
+ }
+
+ assertThat(dispatcher.getCalledPaths())
+ .containsAtLeastElementsIn(dispatcher.getVerifyCalledPaths());
+ }
+
private boolean isAdIdSupported() {
AdIdCompatibleManager adIdCompatibleManager;
AdServicesOutcomeReceiverForTests<AdId> callback =
diff --git a/adservices/tests/cts/src/android/adservices/debuggablects/FledgeCtsDebuggableTest.java b/adservices/tests/cts/src/android/adservices/debuggablects/FledgeCtsDebuggableTest.java
index 7813cf309..48dddaa92 100644
--- a/adservices/tests/cts/src/android/adservices/debuggablects/FledgeCtsDebuggableTest.java
+++ b/adservices/tests/cts/src/android/adservices/debuggablects/FledgeCtsDebuggableTest.java
@@ -41,18 +41,23 @@ import android.adservices.adselection.AdSelectionFromOutcomesConfigFixture;
import android.adservices.adselection.AdSelectionOutcome;
import android.adservices.adselection.AddAdSelectionFromOutcomesOverrideRequest;
import android.adservices.adselection.AddAdSelectionOverrideRequest;
+import android.adservices.adselection.BuyersDecisionLogic;
+import android.adservices.adselection.DecisionLogic;
import android.adservices.adselection.GetAdSelectionDataOutcome;
import android.adservices.adselection.GetAdSelectionDataRequest;
import android.adservices.adselection.PersistAdSelectionResultRequest;
import android.adservices.adselection.ReportEventRequest;
import android.adservices.adselection.ReportImpressionRequest;
import android.adservices.adselection.SetAppInstallAdvertisersRequest;
+import android.adservices.adselection.SignedContextualAds;
+import android.adservices.adselection.SignedContextualAdsFixture;
import android.adservices.adselection.UpdateAdCounterHistogramRequest;
import android.adservices.clients.adselection.AdSelectionClient;
import android.adservices.clients.adselection.TestAdSelectionClient;
import android.adservices.clients.customaudience.AdvertisingCustomAudienceClient;
import android.adservices.clients.customaudience.TestAdvertisingCustomAudienceClient;
import android.adservices.common.AdData;
+import android.adservices.common.AdDataFixture;
import android.adservices.common.AdFilters;
import android.adservices.common.AdSelectionSignals;
import android.adservices.common.AdTechIdentifier;
@@ -85,6 +90,7 @@ import com.android.adservices.service.devapi.DevContextFilter;
import com.android.modules.utils.build.SdkLevel;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.BaseEncoding;
import com.google.common.util.concurrent.ListenableFuture;
@@ -104,8 +110,10 @@ import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -907,21 +915,21 @@ public class FledgeCtsDebuggableTest extends ForegroundDebuggableCtsTest {
.get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
- /*
- // TODO(b/267712947) Unhide Contextual Ad flow with App Install API changes
@Test
public void testFledgeSelectionFlow_WithContextualAds_Success() throws Exception {
Assume.assumeTrue(mAccessStatus, mHasAccessToDevOverrides);
+ PhFlagsFixture.overrideFledgeAdSelectionFilteringEnabled(true);
+ PhFlagsFixture.overrideFledgeEnrollmentCheck(false);
+
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
CustomAudience customAudience1 = createCustomAudience(BUYER_1, bidsForBuyer1);
-
CustomAudience customAudience2 = createCustomAudience(BUYER_2, bidsForBuyer2);
// Joining custom audiences, no result to do assertion on. Failures will generate an
- // exception."
+ // exception.
joinCustomAudience(customAudience1);
joinCustomAudience(customAudience2);
@@ -938,10 +946,12 @@ public class FledgeCtsDebuggableTest extends ForegroundDebuggableCtsTest {
);
// Adding AdSelection override, no result to do assertion on. Failures will generate an
- // exception."
+ // exception.
AddAdSelectionOverrideRequest addAdSelectionOverrideRequest =
new AddAdSelectionOverrideRequest(
- AD_SELECTION_CONFIG, DEFAULT_DECISION_LOGIC_JS, TRUSTED_SCORING_SIGNALS,
+ AD_SELECTION_CONFIG,
+ DEFAULT_DECISION_LOGIC_JS,
+ TRUSTED_SCORING_SIGNALS,
buyersDecisionLogic);
mTestAdSelectionClient
@@ -964,7 +974,7 @@ public class FledgeCtsDebuggableTest extends ForegroundDebuggableCtsTest {
.build();
// Adding Custom audience override, no result to do assertion on. Failures will generate an
- // exception."
+ // exception.
mTestCustomAudienceClient
.overrideCustomAudienceRemoteInfo(addCustomAudienceOverrideRequest1)
.get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@@ -995,7 +1005,7 @@ public class FledgeCtsDebuggableTest extends ForegroundDebuggableCtsTest {
"https://%s%s",
AdSelectionConfigFixture.SELLER,
SELLER_TRUSTED_SIGNAL_URI_PATH)))
- .setBuyerContextualAds(createContextualAds())
+ .setBuyerSignedContextualAds(createAuthenticatedContextualAds())
.build();
// Running ad selection and asserting that the outcome is returned in < 10 seconds
AdSelectionOutcome outcome =
@@ -1022,6 +1032,9 @@ public class FledgeCtsDebuggableTest extends ForegroundDebuggableCtsTest {
public void testFledgeSelectionFlow_OnlyContextualAds_Success() throws Exception {
Assume.assumeTrue(mAccessStatus, mHasAccessToDevOverrides);
+ PhFlagsFixture.overrideFledgeAdSelectionFilteringEnabled(true);
+ PhFlagsFixture.overrideFledgeEnrollmentCheck(false);
+
AdSelectionConfig adSelectionConfigOnlyContextualAds =
AdSelectionConfigFixture.anAdSelectionConfigBuilder()
// Adding no buyers in config
@@ -1038,7 +1051,7 @@ public class FledgeCtsDebuggableTest extends ForegroundDebuggableCtsTest {
"https://%s%s",
AdSelectionConfigFixture.SELLER,
SELLER_TRUSTED_SIGNAL_URI_PATH)))
- .setBuyerContextualAds(createContextualAds())
+ .setBuyerSignedContextualAds(createAuthenticatedContextualAds())
.build();
BuyersDecisionLogic buyersDecisionLogic =
@@ -1054,7 +1067,7 @@ public class FledgeCtsDebuggableTest extends ForegroundDebuggableCtsTest {
);
// Adding AdSelection override, no result to do assertion on. Failures will generate an
- // exception."
+ // exception.
AddAdSelectionOverrideRequest addAdSelectionOverrideRequest =
new AddAdSelectionOverrideRequest(
adSelectionConfigOnlyContextualAds, DEFAULT_DECISION_LOGIC_JS,
@@ -1093,7 +1106,6 @@ public class FledgeCtsDebuggableTest extends ForegroundDebuggableCtsTest {
.reportImpression(reportImpressionRequest)
.get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
- */
@Test
public void testFledgeAuctionSelectionFlow_overall_register_ad_beacon_Success()
@@ -4400,28 +4412,24 @@ public class FledgeCtsDebuggableTest extends ForegroundDebuggableCtsTest {
.build();
}
- /*
- // TODO(b/267712947) Unhisde Contextual Ad flow with App Install API changes
- private Map<AdTechIdentifier, ContextualAds> createContextualAds() {
- Map<AdTechIdentifier, ContextualAds> buyerContextualAds = new HashMap<>();
+ private Map<AdTechIdentifier, SignedContextualAds> createAuthenticatedContextualAds() {
+ Map<AdTechIdentifier, SignedContextualAds> buyerContextualAds = new HashMap<>();
AdTechIdentifier buyer1 = CommonFixture.VALID_BUYER_1;
- ContextualAds contextualAds1 =
- ContextualAdsFixture.generateContextualAds(
- buyer1, ImmutableList.of(100.0, 200.0, 300.0))
- .build();
+ SignedContextualAds contextualAds1 =
+ SignedContextualAdsFixture.aSignedContextualAds(
+ buyer1, ImmutableList.of(100.0, 200.0, 300.0));
AdTechIdentifier buyer2 = CommonFixture.VALID_BUYER_2;
- ContextualAds contextualAds2 =
- ContextualAdsFixture.generateContextualAds(buyer2, ImmutableList.of(400.0, 500.0))
- .build();
+ SignedContextualAds contextualAds2 =
+ SignedContextualAdsFixture.aSignedContextualAds(
+ buyer2, ImmutableList.of(400.0, 500.0));
buyerContextualAds.put(buyer1, contextualAds1);
buyerContextualAds.put(buyer2, contextualAds2);
return buyerContextualAds;
}
- */
private void joinCustomAudience(CustomAudience customAudience)
throws ExecutionException, InterruptedException, TimeoutException {
diff --git a/adservices/tests/cts/src/android/adservices/debuggablects/MeasurementCtsDebuggableTest.java b/adservices/tests/cts/src/android/adservices/debuggablects/MeasurementCtsDebuggableTest.java
index 5f893c176..0e9e8934f 100644
--- a/adservices/tests/cts/src/android/adservices/debuggablects/MeasurementCtsDebuggableTest.java
+++ b/adservices/tests/cts/src/android/adservices/debuggablects/MeasurementCtsDebuggableTest.java
@@ -659,10 +659,6 @@ public class MeasurementCtsDebuggableTest {
// Assume trigger registration can happen within 8 seconds of source registration.
getUiDevice().executeShellCommand(
"device_config put adservices "
- + "measurement_enable_configurable_event_reporting_windows true");
-
- getUiDevice().executeShellCommand(
- "device_config put adservices "
+ "measurement_event_reports_vtc_early_reporting_windows 8,15");
getUiDevice().executeShellCommand(
@@ -729,11 +725,6 @@ public class MeasurementCtsDebuggableTest {
+ "measurement_aggregation_coordinator_path null");
// Reset reporting windows
- // Assume trigger registration can happen within 8 seconds of source registration.
- getUiDevice().executeShellCommand(
- "device_config put adservices "
- + "measurement_enable_configurable_event_reporting_windows null");
-
getUiDevice().executeShellCommand(
"device_config put adservices "
+ "measurement_event_reports_vtc_early_reporting_windows null");
diff --git a/adservices/tests/cts/src/android/adservices/rootcts/CustomAudienceBackgroundFetchTest.java b/adservices/tests/cts/src/android/adservices/rootcts/CustomAudienceBackgroundFetchTest.java
index 829132176..4edcc0259 100644
--- a/adservices/tests/cts/src/android/adservices/rootcts/CustomAudienceBackgroundFetchTest.java
+++ b/adservices/tests/cts/src/android/adservices/rootcts/CustomAudienceBackgroundFetchTest.java
@@ -73,6 +73,32 @@ public class CustomAudienceBackgroundFetchTest extends FledgeScenarioTest {
}
/**
+ * Test to ensure that trusted signals are not updated during the daily update if the ads are
+ * not syntactically valid.
+ */
+ @Test
+ public void testAdSelection_withInvalidAds_backgroundJobUpdateFails() throws Exception {
+ ScenarioDispatcher dispatcher =
+ ScenarioDispatcher.fromScenario(
+ "scenarios/remarketing-cuj-034.json", getCacheBusterPrefix());
+ setupDefaultMockWebServer(dispatcher);
+ AdSelectionConfig adSelectionConfig = makeAdSelectionConfig();
+
+ try {
+ joinCustomAudience(makeCustomAudience(CA_NAME).setAds(List.of()).build());
+ assertThrows(ExecutionException.class, () -> doSelectAds(adSelectionConfig));
+ assertThat(mBackgroundJobHelper.runJob(FLEDGE_BACKGROUND_FETCH_JOB.getJobId()))
+ .isTrue();
+ assertThrows(ExecutionException.class, () -> doSelectAds(adSelectionConfig));
+ } finally {
+ leaveCustomAudience(CA_NAME);
+ }
+
+ assertThat(dispatcher.getCalledPaths())
+ .containsAtLeastElementsIn(dispatcher.getVerifyCalledPaths());
+ }
+
+ /**
* Test to ensure that trusted signals are not updated if a daily update server response exceeds
* the 30-second timeout.
*/
diff --git a/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/Android.bp b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/Android.bp
index 62a762d8b..bbb0c9294 100644
--- a/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/Android.bp
+++ b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/Android.bp
@@ -19,7 +19,7 @@ package {
android_test {
name: "AdServicesGaUxAlreadyEnrolledChannelTest",
srcs: [
- "src/**/*.java",
+ "src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/GaUxAlreadyEnrolledChannelTest.java",
],
static_libs: [
"adservices-assets",
@@ -41,3 +41,61 @@ android_test {
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
}
+
+android_test {
+ name: "AdExtServicesGaUxAlreadyEnrolledChannelRowTest",
+ srcs: [
+ "src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelRowTest.java",
+ ],
+ static_libs: [
+ "adservices-assets",
+ "adservices-service-core",
+ "compatibility-device-util-axt",
+ "truth",
+ "adservices-test-utility",
+ "adservices-ui-cts-root-test-lib",
+ "platform-test-rules",
+ ],
+ libs: [
+ "android.test.base",
+ "framework-adservices-lib",
+ ],
+ test_suites: [
+ "cts_root",
+ "general-tests",
+ ],
+ sdk_version: "module_current",
+ max_sdk_version: "32",
+ min_sdk_version: "31",
+ test_config: "AndroidTest.ExtServices.Row.xml",
+ manifest: "AndroidManifestExtServices.xml",
+}
+
+android_test {
+ name: "AdExtServicesGaUxAlreadyEnrolledChannelEuTest",
+ srcs: [
+ "src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelEuTest.java",
+ ],
+ static_libs: [
+ "adservices-assets",
+ "adservices-service-core",
+ "compatibility-device-util-axt",
+ "truth",
+ "adservices-test-utility",
+ "adservices-ui-cts-root-test-lib",
+ "platform-test-rules",
+ ],
+ libs: [
+ "android.test.base",
+ "framework-adservices-lib",
+ ],
+ test_suites: [
+ "cts_root",
+ "general-tests",
+ ],
+ sdk_version: "module_current",
+ max_sdk_version: "32",
+ min_sdk_version: "31",
+ test_config: "AndroidTest.ExtServices.Eu.xml",
+ manifest: "AndroidManifestExtServices.xml",
+}
diff --git a/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidManifestExtServices.xml b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidManifestExtServices.xml
new file mode 100644
index 000000000..16ebe068d
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidManifestExtServices.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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.ui.gaux.alredyenrolledchannel">
+
+
+ <application>
+ <!-- Used and present only on S- -->
+ <uses-library android:name="com.google.android.ext.services" android:required="false"/>
+
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.google.android.ext.services">
+ </instrumentation>
+</manifest>
diff --git a/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidTest.ExtServices.Eu.xml b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidTest.ExtServices.Eu.xml
new file mode 100644
index 000000000..9526af3ed
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidTest.ExtServices.Eu.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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="TF Config for AdServices Ui Cts test">
+
+ <!-- For this test suite to get picked up in presubmit -->
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.extservices.apex" />
+
+ <!-- Prevent test from running on Android T+ -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MaxSdkModuleController">
+ <option name="max-sdk-level" value="32"/>
+ </object>
+
+ <!-- Prevent tests from running on Android R- -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="device_config set_sync_disabled_for_tests persistent"/>
+ <option name="teardown-command" value="device_config set_sync_disabled_for_tests none"/>
+
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE" />
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_activity_debug_mode false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ui_ota_strings_feature_enabled false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device_feature_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_already_interacted_fix_enable false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ga_ux_enabled true"/>
+ <option name="run-command" value="device_config put adservices enable_back_compat true"/>
+ <option name="run-command" value="device_config put adservices global_kill_switch false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enable_status true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put ui_ota_strings_feature_enabled false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices enable_ad_services_system_api true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices eu_notif_flow_change_enabled false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_debug_mode false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_activity_debug_mode false"/>
+ <!-- override scheduling params so the test is unaffected by time of the day -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_begin_ms 0"/>
+ <!-- end of day (24 hours) -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_end_ms 86400000"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_minimal_delay_before_interval_ends 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="AdExtServicesGaUxAlreadyEnrolledChannelEuTest.apk"/>
+ </target_preparer>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/sdcard/Documents/adservices-tests" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/system/files" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.adservices.tests.ui.gaux.alredyenrolledchannel"/>
+ </test>
+</configuration>
diff --git a/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidTest.ExtServices.Row.xml b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidTest.ExtServices.Row.xml
new file mode 100644
index 000000000..4cf2eca01
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/AndroidTest.ExtServices.Row.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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="TF Config for AdServices Ui Cts test">
+
+ <!-- For this test suite to get picked up in presubmit -->
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.extservices.apex" />
+
+ <!-- Prevent test from running on Android T+ -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MaxSdkModuleController">
+ <option name="max-sdk-level" value="32"/>
+ </object>
+
+ <!-- Prevent tests from running on Android R- -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="device_config set_sync_disabled_for_tests persistent"/>
+ <option name="teardown-command" value="device_config set_sync_disabled_for_tests none"/>
+
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE" />
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_activity_debug_mode false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ui_ota_strings_feature_enabled false"/>
+ <option name="run-command" value="device_config put adservices global_kill_switch false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enable_status true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put ui_ota_strings_feature_enabled false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices enable_ad_services_system_api true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices eu_notif_flow_change_enabled false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_debug_mode false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device_feature_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_already_interacted_fix_enable false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ga_ux_enabled true"/>
+ <option name="run-command" value="device_config put adservices enable_back_compat true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_activity_debug_mode false"/>
+ <!-- override scheduling params so the test is unaffected by time of the day -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_begin_ms 0"/>
+ <!-- end of day (24 hours) -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_end_ms 86400000"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_minimal_delay_before_interval_ends 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="AdExtServicesGaUxAlreadyEnrolledChannelRowTest.apk"/>
+ </target_preparer>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/sdcard/Documents/adservices-tests" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/system/files" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.adservices.tests.ui.gaux.alredyenrolledchannel"/>
+ </test>
+</configuration>
diff --git a/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelEuTest.java b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelEuTest.java
new file mode 100644
index 000000000..0aa6ad2cd
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelEuTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2023 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.ui.gaux.alreadyenrolledchannel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.adservices.common.AdServicesCommonManager;
+import android.adservices.common.AdServicesStates;
+import android.content.Context;
+import android.os.OutcomeReceiver;
+import android.platform.test.rule.ScreenRecordRule;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.adservices.common.AdservicesTestHelper;
+import com.android.adservices.tests.ui.libs.AdservicesWorkflows;
+import com.android.adservices.tests.ui.libs.UiConstants.UX;
+import com.android.adservices.tests.ui.libs.UiUtils;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executors;
+
+/** Test for verifying user consent notification trigger behaviors. */
+@RunWith(AndroidJUnit4.class)
+@ScreenRecordRule.ScreenRecord
+public class ExtGaUxAlreadyEnrolledChannelEuTest {
+
+ private AdServicesCommonManager mCommonManager;
+
+ private UiDevice mDevice;
+
+ private String mTestName;
+
+ private OutcomeReceiver<Boolean, Exception> mCallback;
+
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getContext();
+
+ @Rule public final ScreenRecordRule sScreenRecordRule = new ScreenRecordRule();
+
+ @Before
+ public void setUp() throws Exception {
+ Assume.assumeTrue(AdservicesTestHelper.isDeviceSupported());
+
+ UiUtils.resetAdServicesConsentData(sContext);
+
+ UiUtils.enableNotificationPermission();
+ UiUtils.enableGa();
+ UiUtils.disableNotificationFlowV2();
+ UiUtils.disableOtaStrings();
+
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ mCommonManager = AdServicesCommonManager.get(sContext);
+
+ // General purpose callback used for expected success calls.
+ mCallback =
+ new OutcomeReceiver<Boolean, Exception>() {
+ @Override
+ public void onResult(Boolean result) {
+ assertThat(result).isTrue();
+ }
+
+ @Override
+ public void onError(Exception exception) {
+ Assert.fail();
+ }
+ };
+
+ // Reset consent and thereby AdServices data before each test.
+ UiUtils.refreshConsentResetToken();
+
+ SettableFuture<Boolean> responseFuture = SettableFuture.create();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ new OutcomeReceiver<Boolean, Exception>() {
+ @Override
+ public void onResult(Boolean result) {
+ responseFuture.set(result);
+ }
+
+ @Override
+ public void onError(Exception exception) {
+ responseFuture.setException(exception);
+ }
+ });
+
+ Boolean response = responseFuture.get();
+ assertThat(response).isTrue();
+
+ mDevice.pressHome();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (!AdservicesTestHelper.isDeviceSupported()) return;
+
+ UiUtils.takeScreenshot(mDevice, getClass().getSimpleName() + "_" + mTestName + "_");
+ }
+
+ /**
+ * Verify that for GA, EU devices with non zeroed-out AdId, the GA EU notification is displayed.
+ */
+ @Test
+ public void testGaEuAdIdEnabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ AdServicesStates adServicesStates =
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build();
+
+ mCommonManager.enableAdServices(
+ adServicesStates, Executors.newCachedThreadPool(), mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext, mDevice, /* isDisplayed */ true, /* isEuTest */ true, UX.GA_UX, true);
+
+ // Notifications should not be shown twice.
+ mCommonManager.enableAdServices(
+ adServicesStates, Executors.newCachedThreadPool(), mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext, mDevice, /* isDisplayed */ false, /* isEuTest */ true, UX.GA_UX, true);
+ }
+
+ /** Verify that for GA, EU devices with zeroed-out AdId, the EU notification is displayed. */
+ @Test
+ public void testGaEuAdIdDisabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ UiUtils.setAsEuDevice();
+
+ AdServicesStates adServicesStates =
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(false)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build();
+
+ mCommonManager.enableAdServices(
+ adServicesStates, Executors.newCachedThreadPool(), mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext, mDevice, /* isDisplayed */ true, /* isEuTest */ true, UX.GA_UX, true);
+
+ // Notifications should not be shown twice.
+ mCommonManager.enableAdServices(
+ adServicesStates, Executors.newCachedThreadPool(), mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext, mDevice, /* isDisplayed */ false, /* isEuTest */ true, UX.GA_UX, true);
+ }
+}
diff --git a/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelRowTest.java b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelRowTest.java
new file mode 100644
index 000000000..9688ac720
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/alreadyenrolledchannel/src/com/android/adservices/tests/ui/gaux/alreadyenrolledchannel/ExtGaUxAlreadyEnrolledChannelRowTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2023 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.ui.gaux.alreadyenrolledchannel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.adservices.common.AdServicesCommonManager;
+import android.adservices.common.AdServicesStates;
+import android.content.Context;
+import android.os.OutcomeReceiver;
+import android.platform.test.rule.ScreenRecordRule;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.adservices.common.AdservicesTestHelper;
+import com.android.adservices.tests.ui.libs.AdservicesWorkflows;
+import com.android.adservices.tests.ui.libs.UiConstants.UX;
+import com.android.adservices.tests.ui.libs.UiUtils;
+
+import com.google.common.util.concurrent.SettableFuture;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executors;
+
+/** Test for verifying user consent notification trigger behaviors. */
+@RunWith(AndroidJUnit4.class)
+@ScreenRecordRule.ScreenRecord
+public class ExtGaUxAlreadyEnrolledChannelRowTest {
+
+ private AdServicesCommonManager mCommonManager;
+
+ private UiDevice mDevice;
+
+ private String mTestName;
+
+ private OutcomeReceiver<Boolean, Exception> mCallback;
+
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getContext();
+
+ @Rule public final ScreenRecordRule sScreenRecordRule = new ScreenRecordRule();
+
+ @Before
+ public void setUp() throws Exception {
+ Assume.assumeTrue(AdservicesTestHelper.isDeviceSupported());
+
+ UiUtils.resetAdServicesConsentData(sContext);
+
+ UiUtils.enableNotificationPermission();
+ UiUtils.enableGa();
+ UiUtils.disableNotificationFlowV2();
+ UiUtils.disableOtaStrings();
+
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ mCommonManager = AdServicesCommonManager.get(sContext);
+
+ // General purpose callback used for expected success calls.
+ mCallback =
+ new OutcomeReceiver<Boolean, Exception>() {
+ @Override
+ public void onResult(Boolean result) {
+ assertThat(result).isTrue();
+ }
+
+ @Override
+ public void onError(Exception exception) {
+ Assert.fail();
+ }
+ };
+
+ // Reset consent and thereby AdServices data before each test.
+ UiUtils.refreshConsentResetToken();
+
+ SettableFuture<Boolean> responseFuture = SettableFuture.create();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ new OutcomeReceiver<Boolean, Exception>() {
+ @Override
+ public void onResult(Boolean result) {
+ responseFuture.set(result);
+ }
+
+ @Override
+ public void onError(Exception exception) {
+ responseFuture.setException(exception);
+ }
+ });
+
+ Boolean response = responseFuture.get();
+ assertThat(response).isTrue();
+
+ mDevice.pressHome();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (!AdservicesTestHelper.isDeviceSupported()) return;
+
+ UiUtils.takeScreenshot(mDevice, getClass().getSimpleName() + "_" + mTestName + "_");
+ }
+
+ /**
+ * Verify that for GA, ROW devices with non zeroed-out AdId, the GA ROW notification is
+ * displayed.
+ */
+ @Test
+ public void testGaRowAdIdEnabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ AdServicesStates adServicesStates =
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build();
+
+ mCommonManager.enableAdServices(
+ adServicesStates, Executors.newCachedThreadPool(), mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext, mDevice, /* isDisplayed */ true, /* isEuTest */ false, UX.GA_UX, true);
+
+ // Notifications should not be shown twice.
+ mCommonManager.enableAdServices(
+ adServicesStates, Executors.newCachedThreadPool(), mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext, mDevice, /* isDisplayed */ false, /* isEuTest */ false, UX.GA_UX, true);
+ }
+
+ /**
+ * Verify that for GA, ROW devices with zeroed-out AdId, the GA EU notification is displayed.
+ */
+ @Test
+ public void testGaRowAdIdDisabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ UiUtils.setAsRowDevice();
+
+ AdServicesStates adServicesStates =
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(false)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build();
+
+ mCommonManager.enableAdServices(
+ adServicesStates, Executors.newCachedThreadPool(), mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext, mDevice, /* isDisplayed */ true, /* isEuTest */ true, UX.GA_UX, true);
+
+ // Notifications should not be shown twice.
+ mCommonManager.enableAdServices(
+ adServicesStates, Executors.newCachedThreadPool(), mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext, mDevice, /* isDisplayed */ false, /* isEuTest */ true, UX.GA_UX, true);
+ }
+}
diff --git a/adservices/tests/cts/ui/gaux/debugchannel/Android.bp b/adservices/tests/cts/ui/gaux/debugchannel/Android.bp
index 08b4ac67c..0162c03b3 100644
--- a/adservices/tests/cts/ui/gaux/debugchannel/Android.bp
+++ b/adservices/tests/cts/ui/gaux/debugchannel/Android.bp
@@ -19,7 +19,7 @@ package {
android_test {
name: "AdServicesGaUxDebugChannelCtsRootTest",
srcs: [
- "src/**/*.java",
+ "src/com/android/adservices/tests/ui/gaux/debugchannel/GaUxDebugChannelTest.java",
],
static_libs: [
"adservices-assets",
@@ -41,3 +41,90 @@ android_test {
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
}
+
+android_test {
+ name: "AdExtServicesGaUxDebugChannelCtsRootEuTest",
+ srcs: [
+ "src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelEuTest.java",
+ ],
+ static_libs: [
+ "adservices-assets",
+ "adservices-service-core",
+ "compatibility-device-util-axt",
+ "truth",
+ "adservices-test-utility",
+ "adservices-ui-cts-root-test-lib",
+ "platform-test-rules",
+ ],
+ libs: [
+ "android.test.base",
+ "framework-adservices-lib",
+ ],
+ test_suites: [
+ "cts_root",
+ "general-tests",
+ ],
+ sdk_version: "module_current",
+ max_sdk_version: "32",
+ min_sdk_version: "31",
+ test_config: "AndroidTest.ExtServices.Eu.xml",
+ manifest: "AndroidManifestExtServices.xml",
+}
+
+android_test {
+ name: "AdExtServicesGaUxDebugChannelCtsRootRowTest",
+ srcs: [
+ "src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelRowTest.java",
+ ],
+ static_libs: [
+ "adservices-assets",
+ "adservices-service-core",
+ "compatibility-device-util-axt",
+ "truth",
+ "adservices-test-utility",
+ "adservices-ui-cts-root-test-lib",
+ "platform-test-rules",
+ ],
+ libs: [
+ "android.test.base",
+ "framework-adservices-lib",
+ ],
+ test_suites: [
+ "cts_root",
+ "general-tests",
+ ],
+ sdk_version: "module_current",
+ max_sdk_version: "32",
+ min_sdk_version: "31",
+ test_config: "AndroidTest.ExtServices.Row.xml",
+ manifest: "AndroidManifestExtServices.xml",
+}
+
+android_test {
+ name: "AdExtServicesGaUxDebugChannelCtsRootApiOffTest",
+ srcs: [
+ "src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelApiOffTest.java",
+ ],
+ static_libs: [
+ "adservices-assets",
+ "adservices-service-core",
+ "compatibility-device-util-axt",
+ "truth",
+ "adservices-test-utility",
+ "adservices-ui-cts-root-test-lib",
+ "platform-test-rules",
+ ],
+ libs: [
+ "android.test.base",
+ "framework-adservices-lib",
+ ],
+ test_suites: [
+ "cts_root",
+ "general-tests",
+ ],
+ sdk_version: "module_current",
+ max_sdk_version: "32",
+ min_sdk_version: "31",
+ test_config: "AndroidTest.ExtServices.ApiOff.xml",
+ manifest: "AndroidManifestExtServices.xml",
+} \ No newline at end of file
diff --git a/adservices/tests/cts/ui/gaux/debugchannel/AndroidManifestExtServices.xml b/adservices/tests/cts/ui/gaux/debugchannel/AndroidManifestExtServices.xml
new file mode 100644
index 000000000..2c7347586
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/debugchannel/AndroidManifestExtServices.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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.ui.gaux.debugchannel">
+
+ <application>
+ <!-- Used and present only on S- -->
+ <uses-library android:name="com.google.android.ext.services" android:required="false"/>
+ </application>
+
+ <!-- instrument into the system server for permission -->
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.google.android.ext.services">
+ </instrumentation>
+</manifest>
diff --git a/adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.ApiOff.xml b/adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.ApiOff.xml
new file mode 100644
index 000000000..b2975c00b
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.ApiOff.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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="TF Config for AdServices Ui Cts test">
+ <!-- For this test suite to get picked up in presubmit -->
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.extservices.apex" />
+
+ <!-- Prevent test from running on Android T+ -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MaxSdkModuleController">
+ <option name="max-sdk-level" value="32"/>
+ </object>
+
+ <!-- Prevent tests from running on Android R- -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="device_config set_sync_disabled_for_tests persistent"/>
+ <option name="teardown-command" value="device_config set_sync_disabled_for_tests none"/>
+
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE" />
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_activity_debug_mode false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ui_ota_strings_feature_enabled false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device_feature_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ga_ux_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_debug_mode true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_already_interacted_fix_enable false"/>
+ <option name="run-command" value="device_config put adservices global_kill_switch false"/>
+ <option name="run-command" value="device_config put adservices enable_back_compat true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enable_status true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices enable_ad_services_system_api false"/>
+ <!-- override scheduling params so the test is unaffected by time of the day -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_begin_ms 0"/>
+ <!-- end of day (24 hours) -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_end_ms 86400000"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_minimal_delay_before_interval_ends 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="AdExtServicesGaUxDebugChannelCtsRootApiOffTest.apk"/>
+ </target_preparer>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/sdcard/Documents/adservices-tests" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/system/files" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.adservices.tests.ui.gaux.debugchannel"/>
+ </test>
+</configuration>
diff --git a/adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.Eu.xml b/adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.Eu.xml
new file mode 100644
index 000000000..d8d94c2ce
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.Eu.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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="TF Config for AdServices Ui Cts test">
+ <!-- For this test suite to get picked up in presubmit -->
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.extservices.apex" />
+
+ <!-- Prevent test from running on Android T+ -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MaxSdkModuleController">
+ <option name="max-sdk-level" value="32"/>
+ </object>
+
+ <!-- Prevent tests from running on Android R- -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="device_config set_sync_disabled_for_tests persistent"/>
+ <option name="teardown-command" value="device_config set_sync_disabled_for_tests none"/>
+
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE" />
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_activity_debug_mode false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ui_ota_strings_feature_enabled false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device_feature_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ga_ux_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_debug_mode true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_already_interacted_fix_enable false"/>
+ <option name="run-command" value="device_config put adservices global_kill_switch false"/>
+ <option name="run-command" value="device_config put adservices enable_back_compat true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enable_status true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices enable_ad_services_system_api true"/>
+ <!-- override scheduling params so the test is unaffected by time of the day -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_begin_ms 0"/>
+ <!-- end of day (24 hours) -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_end_ms 86400000"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_minimal_delay_before_interval_ends 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="AdExtServicesGaUxDebugChannelCtsRootEuTest.apk"/>
+ </target_preparer>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/sdcard/Documents/adservices-tests" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/system/files" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.adservices.tests.ui.gaux.debugchannel"/>
+ </test>
+</configuration>
diff --git a/adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.Row.xml b/adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.Row.xml
new file mode 100644
index 000000000..a1364c112
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/debugchannel/AndroidTest.ExtServices.Row.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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="TF Config for AdServices Ui Cts test">
+ <!-- For this test suite to get picked up in presubmit -->
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.extservices.apex" />
+
+ <!-- Prevent test from running on Android T+ -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MaxSdkModuleController">
+ <option name="max-sdk-level" value="32"/>
+ </object>
+
+ <!-- Prevent tests from running on Android R- -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="device_config set_sync_disabled_for_tests persistent"/>
+ <option name="teardown-command" value="device_config set_sync_disabled_for_tests none"/>
+
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE" />
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_activity_debug_mode false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ui_ota_strings_feature_enabled false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device_feature_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices is_eea_device false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices ga_ux_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_debug_mode true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_already_interacted_fix_enable false"/>
+ <option
+ name="run-command"
+ value="device_config put adservices eu_notif_flow_change_enabled false"/>
+ <option name="run-command" value="device_config put adservices global_kill_switch false"/>
+ <option name="run-command" value="device_config put adservices enable_back_compat true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enable_status true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices adservice_enabled true"/>
+ <option
+ name="run-command"
+ value="device_config put adservices enable_ad_services_system_api true"/>
+ <!-- override scheduling params so the test is unaffected by time of the day -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_begin_ms 0"/>
+ <!-- end of day (24 hours) -->
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_interval_end_ms 86400000"/>
+ <option
+ name="run-command"
+ value="device_config put adservices consent_notification_minimal_delay_before_interval_ends 0"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="AdExtServicesGaUxDebugChannelCtsRootRowTest.apk"/>
+ </target_preparer>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/sdcard/Documents/adservices-tests" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/system/files" />
+ <option name="clean-up" value="false" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.adservices.tests.ui.gaux.debugchannel"/>
+ </test>
+</configuration>
diff --git a/adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelApiOffTest.java b/adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelApiOffTest.java
new file mode 100644
index 000000000..ec396ba8b
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelApiOffTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2023 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.ui.gaux.debugchannel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.adservices.common.AdServicesCommonManager;
+import android.adservices.common.AdServicesStates;
+import android.content.Context;
+import android.os.OutcomeReceiver;
+import android.platform.test.rule.ScreenRecordRule;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.adservices.common.AdservicesTestHelper;
+import com.android.adservices.tests.ui.libs.AdservicesWorkflows;
+import com.android.adservices.tests.ui.libs.UiConstants;
+import com.android.adservices.tests.ui.libs.UiUtils;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executors;
+
+/** Test for verifying user consent notification trigger behaviors. */
+@RunWith(AndroidJUnit4.class)
+@ScreenRecordRule.ScreenRecord
+public class ExtGaUxDebugChannelApiOffTest {
+
+ private AdServicesCommonManager mCommonManager;
+
+ private UiDevice mDevice;
+
+ private String mTestName;
+
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getContext();
+
+ @Rule public final ScreenRecordRule sScreenRecordRule = new ScreenRecordRule();
+
+ @Before
+ public void setUp() throws Exception {
+ // Skip the test if it runs on unsupported platforms.
+ Assume.assumeTrue(AdservicesTestHelper.isDeviceSupported());
+
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ UiUtils.enableNotificationPermission();
+
+ mCommonManager = AdServicesCommonManager.get(sContext);
+
+ // consent debug mode is turned on for this test class as we only care about the
+ // first trigger (API call).
+ UiUtils.enableConsentDebugMode();
+ UiUtils.disableNotificationFlowV2();
+ UiUtils.disableOtaStrings();
+
+ mDevice.pressHome();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (!AdservicesTestHelper.isDeviceSupported()) return;
+
+ UiUtils.takeScreenshot(mDevice, getClass().getSimpleName() + "_" + mTestName + "_");
+
+ mDevice.pressHome();
+ }
+
+ /** Verify that the API returns false when API is disabled. */
+ @Test
+ public void testApiDisabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ assertThat(result).isFalse();
+ }
+
+ @Override
+ public void onError(Exception exception) {
+ Assert.fail();
+ }
+ });
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ false, /* isEuTest */
+ false,
+ UiConstants.UX.GA_UX,
+ true);
+ }
+}
diff --git a/adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelEuTest.java b/adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelEuTest.java
new file mode 100644
index 000000000..72ec7d26a
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelEuTest.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2023 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.ui.gaux.debugchannel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.adservices.common.AdServicesCommonManager;
+import android.adservices.common.AdServicesStates;
+import android.content.Context;
+import android.os.OutcomeReceiver;
+import android.platform.test.rule.ScreenRecordRule;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.adservices.common.AdservicesTestHelper;
+import com.android.adservices.tests.ui.libs.AdservicesWorkflows;
+import com.android.adservices.tests.ui.libs.UiConstants;
+import com.android.adservices.tests.ui.libs.UiUtils;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executors;
+
+/** Test for verifying user consent notification trigger behaviors. */
+@RunWith(AndroidJUnit4.class)
+@ScreenRecordRule.ScreenRecord
+public class ExtGaUxDebugChannelEuTest {
+
+ private AdServicesCommonManager mCommonManager;
+
+ private UiDevice mDevice;
+
+ private String mTestName;
+
+ private OutcomeReceiver<Boolean, Exception> mCallback;
+
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getContext();
+
+ @Rule public final ScreenRecordRule sScreenRecordRule = new ScreenRecordRule();
+
+ @Before
+ public void setUp() throws Exception {
+ // Skip the test if it runs on unsupported platforms.
+ Assume.assumeTrue(AdservicesTestHelper.isDeviceSupported());
+
+ UiUtils.resetAdServicesConsentData(sContext);
+
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ UiUtils.enableNotificationPermission();
+
+ mCommonManager = AdServicesCommonManager.get(sContext);
+
+ // consent debug mode is turned on for this test class as we only care about the
+ // first trigger (API call).
+ UiUtils.enableConsentDebugMode();
+ UiUtils.disableNotificationFlowV2();
+ UiUtils.disableOtaStrings();
+
+ mCallback =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ assertThat(result).isTrue();
+ }
+
+ @Override
+ public void onError(Exception exception) {
+ Assert.fail();
+ }
+ };
+
+ mDevice.pressHome();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (!AdservicesTestHelper.isDeviceSupported()) return;
+
+ UiUtils.takeScreenshot(mDevice, getClass().getSimpleName() + "_" + mTestName + "_");
+
+ mDevice.pressHome();
+ }
+
+ /** Verify that entry point disabled can not trigger consent notification. */
+ @Test
+ public void testEntryPointDisabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(false)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ false, /* isEuTest */
+ false, /* isGa */
+ UiConstants.UX.GA_UX,
+ true);
+ }
+
+ /** Verify that when request sent from entry point, we won't trigger notification. */
+ @Test
+ public void testFromEntryPointRequest() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(false)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .setPrivacySandboxUiRequest(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ false, /* isEuTest */
+ true,
+ UiConstants.UX.GA_UX,
+ true);
+ }
+
+ /** Verify that non-adult account can not trigger consent notification. */
+ @Test
+ public void testNonAdultAccount() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(false)
+ .setPrivacySandboxUiEnabled(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ false, /* isEuTest */
+ false,
+ UiConstants.UX.GA_UX,
+ true);
+ }
+
+ /**
+ * Verify that for GA, EU devices with non zeroed-out AdId, the GA EU notification is displayed.
+ */
+ @Test
+ public void testGaEuAdIdEnabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ true, /* isEuTest */
+ true,
+ UiConstants.UX.GA_UX,
+ true);
+ }
+
+ /** Verify that for GA, EU devices with zeroed-out AdId, the EU notification is displayed. */
+ @Test
+ public void testGaEuAdIdDisabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(false)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ true, /* isEuTest */
+ true,
+ UiConstants.UX.GA_UX,
+ true);
+ }
+}
diff --git a/adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelRowTest.java b/adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelRowTest.java
new file mode 100644
index 000000000..782773fbd
--- /dev/null
+++ b/adservices/tests/cts/ui/gaux/debugchannel/src/com/android/adservices/tests/ui/gaux/debugchannel/ExtGaUxDebugChannelRowTest.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2023 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.ui.gaux.debugchannel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.adservices.common.AdServicesCommonManager;
+import android.adservices.common.AdServicesStates;
+import android.content.Context;
+import android.os.OutcomeReceiver;
+import android.platform.test.rule.ScreenRecordRule;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.adservices.common.AdservicesTestHelper;
+import com.android.adservices.tests.ui.libs.AdservicesWorkflows;
+import com.android.adservices.tests.ui.libs.UiConstants;
+import com.android.adservices.tests.ui.libs.UiUtils;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executors;
+
+/** Test for verifying user consent notification trigger behaviors. */
+@RunWith(AndroidJUnit4.class)
+@ScreenRecordRule.ScreenRecord
+public class ExtGaUxDebugChannelRowTest {
+
+ private AdServicesCommonManager mCommonManager;
+
+ private UiDevice mDevice;
+
+ private String mTestName;
+
+ private OutcomeReceiver<Boolean, Exception> mCallback;
+
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getContext();
+
+ @Rule public final ScreenRecordRule sScreenRecordRule = new ScreenRecordRule();
+
+ @Before
+ public void setUp() throws Exception {
+ // Skip the test if it runs on unsupported platforms.
+ Assume.assumeTrue(AdservicesTestHelper.isDeviceSupported());
+
+ UiUtils.resetAdServicesConsentData(sContext);
+
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ UiUtils.enableNotificationPermission();
+
+ mCommonManager = AdServicesCommonManager.get(sContext);
+
+ // consent debug mode is turned on for this test class as we only care about the
+ // first trigger (API call).
+ UiUtils.enableConsentDebugMode();
+ UiUtils.disableNotificationFlowV2();
+ UiUtils.disableOtaStrings();
+
+ mCallback =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ assertThat(result).isTrue();
+ }
+
+ @Override
+ public void onError(Exception exception) {
+ Assert.fail();
+ }
+ };
+
+ mDevice.pressHome();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (!AdservicesTestHelper.isDeviceSupported()) return;
+
+ UiUtils.takeScreenshot(mDevice, getClass().getSimpleName() + "_" + mTestName + "_");
+
+ mDevice.pressHome();
+ }
+
+ /** Verify that entry point disabled can not trigger consent notification. */
+ @Test
+ public void testEntryPointDisabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(false)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ false, /* isEuTest */
+ false, /* isGa */
+ UiConstants.UX.GA_UX,
+ true);
+ }
+
+ /** Verify that when request sent from entry point, we won't trigger notification. */
+ @Test
+ public void testFromEntryPointRequest() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(false)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .setPrivacySandboxUiRequest(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ false, /* isEuTest */
+ false,
+ UiConstants.UX.GA_UX,
+ true);
+ }
+
+ /** Verify that non-adult account can not trigger consent notification. */
+ @Test
+ public void testNonAdultAccount() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(false)
+ .setPrivacySandboxUiEnabled(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ false, /* isEuTest */
+ false,
+ UiConstants.UX.GA_UX,
+ true);
+ }
+
+ /**
+ * Verify that for GA, ROW devices with non zeroed-out AdId, the GA ROW notification is
+ * displayed.
+ */
+ @Test
+ public void testGaRowAdIdEnabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(true)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ true, /* isEuTest */
+ false,
+ UiConstants.UX.GA_UX,
+ true);
+ }
+
+ /**
+ * Verify that for GA, ROW devices with zeroed-out AdId, the GA EU notification is displayed.
+ */
+ @Test
+ public void testGaRowAdIdDisabled() throws Exception {
+ mTestName = new Object() {}.getClass().getEnclosingMethod().getName();
+
+ mCommonManager.enableAdServices(
+ new AdServicesStates.Builder()
+ .setAdIdEnabled(false)
+ .setAdultAccount(true)
+ .setPrivacySandboxUiEnabled(true)
+ .build(),
+ Executors.newCachedThreadPool(),
+ mCallback);
+
+ AdservicesWorkflows.verifyNotification(
+ sContext,
+ mDevice, /* isDisplayed */
+ true, /* isEuTest */
+ true,
+ UiConstants.UX.GA_UX,
+ true);
+ }
+}
diff --git a/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/AdservicesWorkflows.java b/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/AdservicesWorkflows.java
index c36dde21b..4f2125672 100644
--- a/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/AdservicesWorkflows.java
+++ b/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/AdservicesWorkflows.java
@@ -135,6 +135,10 @@ public class AdservicesWorkflows {
UiUtils.enableGa();
UiUtils.enableU18();
break;
+ case RVC_UX:
+ UiUtils.enableGa();
+ UiUtils.enableRvc();
+ break;
}
UiUtils.setFlipFlow(isV2);
@@ -192,7 +196,7 @@ public class AdservicesWorkflows {
boolean isEuDevice,
UiConstants.UX ux)
throws Exception {
- NotificationPages.verifyNotification(context, device, isDisplayed, isEuDevice, ux, false);
+ NotificationPages.verifyNotification(context, device, isDisplayed, isEuDevice, ux, true);
}
public static void verifyNotification(
diff --git a/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java b/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java
index e917a5182..6b3d7bb57 100644
--- a/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java
+++ b/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java
@@ -171,9 +171,9 @@ public class UiUtils {
forceSetFlag("rvc_ux_enabled", true);
}
- /** Override flag rvc_notification_enabled in tests to true */
+ /** Override flag rvc_post_ota_notification_enabled in tests to true */
public static void enableRvcNotification() throws Exception {
- forceSetFlag("rvc_notification_enabled", true);
+ forceSetFlag("rvc_post_ota_notification_enabled", true);
}
/** Override flag rvc_ux_enabled in tests to false */
@@ -280,14 +280,17 @@ public class UiUtils {
int notificationHeader = -1;
switch (ux) {
case GA_UX:
+ // Should match the contentTitle string in ConsentNotificationTrigger.java.
notificationTitle =
isEuTest
- ? R.string.notificationUI_notification_ga_title_eu
- : R.string.notificationUI_notification_ga_title;
+ ? R.string.notificationUI_notification_ga_title_eu_v2
+ : R.string.notificationUI_notification_ga_title_v2;
+ // Should match the text in consent_notification_screen_1_ga_v2_eu.xml and
+ // consent_notification_screen_1_ga_v2_row.xml, respectively.
notificationHeader =
isEuTest
- ? R.string.notificationUI_header_ga_title_eu
- : R.string.notificationUI_header_ga_title;
+ ? R.string.notificationUI_fledge_measurement_title_v2
+ : R.string.notificationUI_header_ga_title_v2;
break;
case BETA_UX:
notificationTitle =
@@ -625,23 +628,6 @@ public class UiUtils {
scrollView.swipe(Direction.DOWN, 0.7f, 500);
}
- public static UiObject2 getConsentSwitch(UiDevice device) {
- UiObject2 consentSwitch =
- device.wait(
- Until.findObject(By.clazz("android.widget.Switch")),
- PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
- // Swipe the screen by the width of the toggle so it's not blocked by the nav bar on AOSP
- // devices.
- device.swipe(
- consentSwitch.getVisibleBounds().centerX(),
- 500,
- consentSwitch.getVisibleBounds().centerX(),
- 0,
- 100);
-
- return consentSwitch;
- }
-
public static void performSwitchClick(
UiDevice device, Context context, boolean dialogsOn, UiObject2 mainSwitch) {
if (dialogsOn && mainSwitch.isChecked()) {
@@ -667,7 +653,10 @@ public class UiUtils {
public static void gentleSwipe(UiDevice device) {
UiObject2 scrollView =
device.findObject(By.scrollable(true).clazz(ANDROID_WIDGET_SCROLLVIEW));
- scrollView.scroll(Direction.DOWN, /* percent */ 0.25F);
+ // Some devices on R is not scrollable
+ if (scrollView != null) {
+ scrollView.scroll(Direction.DOWN, /* percent */ 0.25F);
+ }
}
public static void setFlipFlow(boolean isFlip) {
@@ -700,10 +689,13 @@ public class UiUtils {
public static UiObject2 scrollTo(Context context, UiDevice device, int resId) {
UiObject2 scrollView =
device.findObject(By.scrollable(true).clazz(ANDROID_WIDGET_SCROLLVIEW));
- String targetStr = getString(context, resId);
- scrollView.scrollUntil(
- Direction.DOWN,
- Until.findObject(By.text(Pattern.compile(targetStr, Pattern.CASE_INSENSITIVE))));
+ if (scrollView != null) {
+ String targetStr = getString(context, resId);
+ scrollView.scrollUntil(
+ Direction.DOWN,
+ Until.findObject(
+ By.text(Pattern.compile(targetStr, Pattern.CASE_INSENSITIVE))));
+ }
return getElement(context, device, resId);
}
diff --git a/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/pages/NotificationPages.java b/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/pages/NotificationPages.java
index 6a5051d04..0c6b88564 100644
--- a/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/pages/NotificationPages.java
+++ b/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/pages/NotificationPages.java
@@ -53,16 +53,17 @@ public class NotificationPages {
int notificationHeader = -1;
switch (ux) {
case GA_UX:
+ // Should match the contentTitle string in ConsentNotificationTrigger.java.
notificationTitle =
isEuTest
- ? R.string.notificationUI_notification_ga_title_eu
- : isV2
- ? R.string.notificationUI_notification_ga_title_v2
- : R.string.notificationUI_notification_ga_title;
+ ? R.string.notificationUI_notification_ga_title_eu_v2
+ : R.string.notificationUI_notification_ga_title_v2;
+ // Should match the text in consent_notification_screen_1_ga_v2_eu.xml and
+ // consent_notification_screen_1_ga_v2_row.xml, respectively.
notificationHeader =
isEuTest
- ? R.string.notificationUI_header_ga_title_eu
- : R.string.notificationUI_header_ga_title;
+ ? R.string.notificationUI_fledge_measurement_title_v2
+ : R.string.notificationUI_header_ga_title_v2;
break;
case BETA_UX:
notificationTitle =
diff --git a/adservices/tests/host/room/Android.bp b/adservices/tests/host/room/Android.bp
index b6f2bdb98..04b066d8c 100644
--- a/adservices/tests/host/room/Android.bp
+++ b/adservices/tests/host/room/Android.bp
@@ -26,5 +26,4 @@ java_test_host {
"cts-install-lib-host",
],
test_suites: ["general-tests"],
- test_mainline_modules: ["com.google.android.adservices.apex"],
}
diff --git a/adservices/tests/host/room/AndroidTest.xml b/adservices/tests/host/room/AndroidTest.xml
index 3b520b53c..d70c792cd 100644
--- a/adservices/tests/host/room/AndroidTest.xml
+++ b/adservices/tests/host/room/AndroidTest.xml
@@ -19,6 +19,10 @@
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app"/>
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi"/>
+ <!-- For this test suite to get picked up in mainline presubmit -->
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.adservices.apex" />
+
<test class="com.android.tradefed.testtype.HostTest">
<option name="class"
value="com.android.adservices.room.test.RoomDatabaseVersionBumpGuardrailTest"/>
diff --git a/adservices/tests/host/room/src/com/android/adservices/room/test/RoomDatabaseVersionBumpGuardrailTest.java b/adservices/tests/host/room/src/com/android/adservices/room/test/RoomDatabaseVersionBumpGuardrailTest.java
index 8c3db3124..de345b50f 100644
--- a/adservices/tests/host/room/src/com/android/adservices/room/test/RoomDatabaseVersionBumpGuardrailTest.java
+++ b/adservices/tests/host/room/src/com/android/adservices/room/test/RoomDatabaseVersionBumpGuardrailTest.java
@@ -21,6 +21,7 @@ import android.cts.install.lib.host.InstallUtilsHost;
import com.android.tradefed.config.Option;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.FileUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -70,6 +71,9 @@ public class RoomDatabaseVersionBumpGuardrailTest extends BaseHostJUnit4Test {
@Option(name = "new-schema-lib")
protected String mNewSchemaLib;
+ @Option(name = "schema-apk-name")
+ protected String mSchemaApkName = AD_SERVICES_SERVICE_CORE_UNIT_TESTS_APK_FILE_NAME;
+
@Test
public void roomDatabaseVersionBumpGuardrailTest() throws Exception {
@@ -79,15 +83,14 @@ public class RoomDatabaseVersionBumpGuardrailTest extends BaseHostJUnit4Test {
Map<String, ZipEntry> baseVersions = extractVersionMap(baseSchemas);
Map<String, ZipEntry> newVersions = extractVersionMap(newSchemas);
- StringBuilder stringBuilder = new StringBuilder();
+ StringBuilder errors = new StringBuilder();
for (Map.Entry<String, ZipEntry> e : baseVersions.entrySet()) {
String name = e.getKey();
ZipEntry baseFile = e.getValue();
ZipEntry newFile = newVersions.get(name);
if (newFile == null) {
- stringBuilder.append(
- String.format("Database file '%s' missing in new version!\n", name));
+ errors.append(String.format("Database file '%s' missing in new version!\n", name));
continue;
}
@@ -98,7 +101,7 @@ public class RoomDatabaseVersionBumpGuardrailTest extends BaseHostJUnit4Test {
if (!Arrays.equals(
baseSchemas.getInputStream(baseFile).readAllBytes(),
newSchemas.getInputStream(newFile).readAllBytes())) {
- stringBuilder.append(
+ errors.append(
String.format(
"Database file '%s' changed between major build. Please bump up"
+ " DB version.\n",
@@ -107,29 +110,33 @@ public class RoomDatabaseVersionBumpGuardrailTest extends BaseHostJUnit4Test {
}
if (getVersionFromFile(baseFile) > getVersionFromFile(newFile)) {
- stringBuilder.append(
+ errors.append(
String.format(
"Database %s version was turned down from %d to %d\n",
name, baseFileVersion, newFileVersion));
}
}
- if (stringBuilder.length() != 0) {
- throw new IllegalStateException(stringBuilder.toString());
+ if (errors.length() != 0) {
+ throw new IllegalStateException(errors.toString());
}
}
private ZipFile getTestPackageFromFile(String lib) throws IOException {
byte[] bytes;
- try (ZipFile zipFile = new ZipFile(mHostUtils.getTestFile(lib))) {
- ZipEntry entry =
- getZipEntry(zipFile, AD_SERVICES_SERVICE_CORE_UNIT_TESTS_APK_FILE_NAME);
- bytes = zipFile.getInputStream(entry).readAllBytes();
+ File testPackage = mHostUtils.getTestFile(lib);
+ if (testPackage.isFile()) {
+ try (ZipFile zipFile = new ZipFile(testPackage)) {
+ ZipEntry entry = getZipEntry(zipFile, mSchemaApkName);
+ bytes = zipFile.getInputStream(entry).readAllBytes();
+ }
+ File tempFile = File.createTempFile("schemaFiles", ".zip");
+ tempFile.setWritable(true);
+ new FileOutputStream(tempFile).write(bytes);
+ return new ZipFile(tempFile);
+ } else {
+ return new ZipFile(FileUtil.findFile(testPackage, mSchemaApkName));
}
- File tempFile = File.createTempFile("schemaFiles", ".zip");
- tempFile.setWritable(true);
- new FileOutputStream(tempFile).write(bytes);
- return new ZipFile(tempFile);
}
private static ZipEntry getZipEntry(ZipFile zipFile, String fileName) {
diff --git a/adservices/tests/jetpack/Android.bp b/adservices/tests/jetpack/Android.bp
index 9a6a91221..f506a0013 100644
--- a/adservices/tests/jetpack/Android.bp
+++ b/adservices/tests/jetpack/Android.bp
@@ -437,7 +437,8 @@ android_test {
],
libs: [
"android.test.base",
- ],
+ "framework-sdkextensions",
+ ],
test_suites: [
"general-tests",
],
@@ -468,7 +469,8 @@ android_test {
],
libs: [
"android.test.base",
- ],
+ "framework-sdkextensions",
+ ],
test_suites: [
"general-tests",
],
@@ -499,7 +501,8 @@ android_test {
],
libs: [
"android.test.base",
- ],
+ "framework-sdkextensions",
+ ],
test_suites: [
"general-tests",
],
@@ -530,7 +533,8 @@ android_test {
],
libs: [
"android.test.base",
- ],
+ "framework-sdkextensions",
+ ],
test_suites: [
"general-tests",
],
@@ -561,7 +565,8 @@ android_test {
],
libs: [
"android.test.base",
- ],
+ "framework-sdkextensions",
+ ],
test_suites: [
"general-tests",
],
diff --git a/adservices/tests/jetpack/src/com/android/adservices/TestUtil.java b/adservices/tests/jetpack/src/com/android/adservices/TestUtil.java
index fa2f7dbb0..46722078d 100644
--- a/adservices/tests/jetpack/src/com/android/adservices/TestUtil.java
+++ b/adservices/tests/jetpack/src/com/android/adservices/TestUtil.java
@@ -93,6 +93,7 @@ public class TestUtil {
public void overrideAllowlists(boolean override) {
String overrideStr = override ? "*" : "null";
runShellCommand("device_config put adservices ppapi_app_allow_list " + overrideStr);
+ runShellCommand("device_config put adservices msmt_api_app_allow_list " + overrideStr);
runShellCommand(
"device_config put adservices ppapi_app_signature_allow_list " + overrideStr);
runShellCommand(
diff --git a/adservices/tests/jetpack/src/com/android/adservices/adid/AdIdManagerJetpackTest.java b/adservices/tests/jetpack/src/com/android/adservices/adid/AdIdManagerJetpackTest.java
index f5e9d7459..1fbab9bd8 100644
--- a/adservices/tests/jetpack/src/com/android/adservices/adid/AdIdManagerJetpackTest.java
+++ b/adservices/tests/jetpack/src/com/android/adservices/adid/AdIdManagerJetpackTest.java
@@ -18,6 +18,8 @@ package com.android.adservices.adid;
import static com.google.common.truth.Truth.assertThat;
+import android.os.ext.SdkExtensions;
+
import androidx.privacysandbox.ads.adservices.adid.AdId;
import androidx.privacysandbox.ads.adservices.java.adid.AdIdManagerFutures;
import androidx.test.core.app.ApplicationProvider;
@@ -26,6 +28,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.android.adservices.TestUtil;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@@ -35,6 +38,8 @@ public class AdIdManagerJetpackTest {
@Before
public void setup() throws Exception {
+ Assume.assumeTrue(SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) >= 4);
+
mTestUtil.overrideAdIdKillSwitch(true);
mTestUtil.overrideKillSwitches(true);
mTestUtil.overrideConsentManagerDebugMode(true);
diff --git a/adservices/tests/jetpack/src/com/android/adservices/appsetid/AppSetIdManagerJetpackTest.java b/adservices/tests/jetpack/src/com/android/adservices/appsetid/AppSetIdManagerJetpackTest.java
index c8169f0c1..ed7c06e91 100644
--- a/adservices/tests/jetpack/src/com/android/adservices/appsetid/AppSetIdManagerJetpackTest.java
+++ b/adservices/tests/jetpack/src/com/android/adservices/appsetid/AppSetIdManagerJetpackTest.java
@@ -18,6 +18,8 @@ package com.android.adservices.appsetid;
import static com.google.common.truth.Truth.assertThat;
+import android.os.ext.SdkExtensions;
+
import androidx.privacysandbox.ads.adservices.appsetid.AppSetId;
import androidx.privacysandbox.ads.adservices.java.appsetid.AppSetIdManagerFutures;
import androidx.test.core.app.ApplicationProvider;
@@ -26,6 +28,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.android.adservices.TestUtil;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@@ -35,6 +38,8 @@ public class AppSetIdManagerJetpackTest {
@Before
public void setup() throws Exception {
+ Assume.assumeTrue(SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) >= 4);
+
mTestUtil.overrideAppSetIdKillSwitch(true);
mTestUtil.overrideKillSwitches(true);
mTestUtil.overrideAllowlists(true);
diff --git a/adservices/tests/jetpack/src/com/android/adservices/measurement/MeasurementManagerJetpackTest.java b/adservices/tests/jetpack/src/com/android/adservices/measurement/MeasurementManagerJetpackTest.java
index b0a589b0e..0154d334c 100644
--- a/adservices/tests/jetpack/src/com/android/adservices/measurement/MeasurementManagerJetpackTest.java
+++ b/adservices/tests/jetpack/src/com/android/adservices/measurement/MeasurementManagerJetpackTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import android.net.Uri;
+import android.os.ext.SdkExtensions;
import androidx.privacysandbox.ads.adservices.java.measurement.MeasurementManagerFutures;
import androidx.privacysandbox.ads.adservices.measurement.DeletionRequest;
@@ -33,6 +34,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.android.adservices.TestUtil;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@@ -56,6 +58,7 @@ public class MeasurementManagerJetpackTest {
@Before
public void setup() throws Exception {
+ Assume.assumeTrue(SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) >= 5);
// To grant access to all pp api app
mTestUtil.overrideAllowlists(true);
// We need to turn the Consent Manager into debug mode
diff --git a/adservices/tests/jetpack/src/com/android/adservices/protectedaudience/FledgeCtsDebuggableJetpackTest.java b/adservices/tests/jetpack/src/com/android/adservices/protectedaudience/FledgeCtsDebuggableJetpackTest.java
index 20ad27236..30ff2e2de 100644
--- a/adservices/tests/jetpack/src/com/android/adservices/protectedaudience/FledgeCtsDebuggableJetpackTest.java
+++ b/adservices/tests/jetpack/src/com/android/adservices/protectedaudience/FledgeCtsDebuggableJetpackTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertThrows;
import android.content.Context;
import android.net.Uri;
+import android.os.ext.SdkExtensions;
import android.util.Log;
import androidx.privacysandbox.ads.adservices.adselection.AdSelectionConfig;
@@ -35,7 +36,6 @@ import androidx.privacysandbox.ads.adservices.customaudience.CustomAudience;
import androidx.privacysandbox.ads.adservices.customaudience.JoinCustomAudienceRequest;
import androidx.privacysandbox.ads.adservices.customaudience.LeaveCustomAudienceRequest;
import androidx.privacysandbox.ads.adservices.customaudience.TrustedBiddingData;
-import androidx.privacysandbox.ads.adservices.internal.AdServicesInfo;
import androidx.privacysandbox.ads.adservices.java.adselection.AdSelectionManagerFutures;
import androidx.privacysandbox.ads.adservices.java.customaudience.CustomAudienceManagerFutures;
import androidx.test.core.app.ApplicationProvider;
@@ -195,6 +195,8 @@ public class FledgeCtsDebuggableJetpackTest {
@Before
public void setup() throws Exception {
+ Assume.assumeTrue(SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) >= 4);
+
mAdSelectionClient = new AdSelectionClient(sContext);
mCustomAudienceClient = new CustomAudienceClient(sContext);
@@ -209,9 +211,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testFledgeAuctionSelectionFlow_overall_Success() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -248,9 +247,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testAdSelection_etldViolation_failure() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -297,9 +293,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testReportImpression_etldViolation_failure() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -359,9 +352,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testAdSelection_skipAdsMalformedBiddingLogic_success() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -407,9 +397,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testAdSelection_malformedScoringLogic_failure() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -454,9 +441,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testAdSelection_skipAdsFailedGettingBiddingLogic_success() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -502,9 +486,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testAdSelection_errorGettingScoringLogic_failure() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -555,9 +536,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testAdSelectionFlow_skipNonActivatedCA_Success() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -604,9 +582,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testAdSelectionFlow_skipExpiredCA_Success() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -659,9 +634,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testAdSelectionFlow_skipCAsThatTimeoutDuringBidding_Success() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -706,9 +678,6 @@ public class FledgeCtsDebuggableJetpackTest {
@Test
public void testAdSelection_overallTimeout_Failure() throws Exception {
- // Skip the test if SDK extension 4 is not present.
- Assume.assumeTrue(AdServicesInfo.INSTANCE.version() >= 4);
-
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
diff --git a/adservices/tests/jetpack/src/com/android/adservices/topics/TopicsManagerJetpackTest.java b/adservices/tests/jetpack/src/com/android/adservices/topics/TopicsManagerJetpackTest.java
index cfb4ad406..4233a8890 100644
--- a/adservices/tests/jetpack/src/com/android/adservices/topics/TopicsManagerJetpackTest.java
+++ b/adservices/tests/jetpack/src/com/android/adservices/topics/TopicsManagerJetpackTest.java
@@ -18,6 +18,8 @@ package com.android.adservices.topics;
import static com.google.common.truth.Truth.assertThat;
+import android.os.ext.SdkExtensions;
+
import androidx.privacysandbox.ads.adservices.java.topics.TopicsManagerFutures;
import androidx.privacysandbox.ads.adservices.topics.GetTopicsRequest;
import androidx.privacysandbox.ads.adservices.topics.GetTopicsResponse;
@@ -28,6 +30,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.android.adservices.TestUtil;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -50,6 +53,8 @@ public class TopicsManagerJetpackTest {
@Before
public void setup() throws Exception {
+ Assume.assumeTrue(SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) >= 4);
+
mTestUtil.overrideKillSwitches(true);
// 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.
diff --git a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/AdSelectionDataE2ETest.java b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/AdSelectionDataE2ETest.java
index 3fb572f9a..8cee1b4b1 100644
--- a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/AdSelectionDataE2ETest.java
+++ b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/AdSelectionDataE2ETest.java
@@ -73,7 +73,7 @@ public class AdSelectionDataE2ETest {
"CustomAudienceServerAuctionFiveBuyersMultipleCa.json";
private static final String CUSTOM_AUDIENCE_NO_AD_RENDER_ID = "CustomAudienceNoAdRenderId.json";
private static final String SELLER = "ba-seller-5jyy5ulagq-uc.a.run.app";
- private static final String SFE_ADDRESS = "https://seller1-nmb.sfe-gcp.com/v1/selectAd";
+ private static final String SFE_ADDRESS = "https://seller1-patest.sfe.bas-gcp.pstest.dev/v1/selectAd";
private static final boolean SERVER_RESPONSE_LOGGING_ENABLED = true;
private static final String AD_WINNER_DOMAIN = "https://ba-buyer-5jyy5ulagq-uc.a.run.app/";
diff --git a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/GetAdSelectionDataLatency.java b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/GetAdSelectionDataLatency.java
new file mode 100644
index 000000000..5c7308321
--- /dev/null
+++ b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/GetAdSelectionDataLatency.java
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2023 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 android.adservices.test.scenario.adservices.fledge;
+
+import android.Manifest;
+import android.adservices.adselection.GetAdSelectionDataOutcome;
+import android.adservices.adselection.GetAdSelectionDataRequest;
+import android.adservices.clients.adselection.AdSelectionClient;
+import android.adservices.common.AdTechIdentifier;
+import android.adservices.customaudience.CustomAudience;
+import android.adservices.customaudience.CustomAudienceFixture;
+import android.adservices.test.scenario.adservices.fledge.utils.CustomAudienceTestFixture;
+import android.adservices.test.scenario.adservices.utils.SelectAdsFlagRule;
+import android.content.Context;
+import android.platform.test.microbenchmark.Microbenchmark;
+import android.platform.test.rule.CleanPackageRule;
+import android.platform.test.rule.KillAppsRule;
+import android.platform.test.scenario.annotation.Scenario;
+import android.util.Log;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.adservices.common.AdservicesTestHelper;
+import com.android.compatibility.common.util.ShellUtils;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+@Scenario
+@RunWith(Microbenchmark.class)
+public class GetAdSelectionDataLatency {
+ private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool();
+ private static final Context CONTEXT = ApplicationProvider.getApplicationContext();
+ private static final String CUSTOM_AUDIENCE_ONE_BUYER_ONE_CA_ONE_AD =
+ "CustomAudienceOneBuyerOneCaOneAd.json";
+ private static final String SELLER = "ba-seller-5jyy5ulagq-uc.a.run.app";
+
+ private static final int API_RESPONSE_TIMEOUT_SECONDS = 100;
+ private static final AdSelectionClient AD_SELECTION_CLIENT =
+ new AdSelectionClient.Builder()
+ .setContext(CONTEXT)
+ .setExecutor(CALLBACK_EXECUTOR)
+ .build();
+
+ @Rule
+ public RuleChain rules =
+ RuleChain.outerRule(
+ new KillAppsRule(
+ AdservicesTestHelper.getAdServicesPackageName(CONTEXT)))
+ .around(
+ // CleanPackageRule should not execute after each test method because
+ // there's a chance it interferes with ShowmapSnapshotListener snapshot
+ // at the end of the test, impacting collection of memory metrics for
+ // AdServices process.
+ new CleanPackageRule(
+ AdservicesTestHelper.getAdServicesPackageName(CONTEXT),
+ /* clearOnStarting = */ true,
+ /* clearOnFinished = */ false))
+ .around(new SelectAdsFlagRule());
+
+ @BeforeClass
+ public static void setupBeforeClass() {
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity(Manifest.permission.WRITE_DEVICE_CONFIG);
+ }
+
+ private static final String TAG = "SelectAds";
+
+ private String generateLogLabel(String classSimpleName, String testName, long elapsedMs) {
+ return "("
+ + "SELECT_ADS_LATENCY_"
+ + classSimpleName
+ + "#"
+ + testName
+ + ": "
+ + elapsedMs
+ + " ms)";
+ }
+
+ private static final long NANO_TO_MILLISECONDS = 1000000;
+
+ @Before
+ public void warmup() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceTestFixture.readCustomAudiences(
+ CUSTOM_AUDIENCE_ONE_BUYER_ONE_CA_ONE_AD);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingBuyers_1() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 1, /* nCAsPerBuyer= */ 1, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingBuyers_1",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingBuyers_10() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 10, /* nCAsPerBuyer= */ 1, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingBuyers_10",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingBuyers_100() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 100, /* nCAsPerBuyer= */ 1, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingBuyers_100",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingBuyers_500() throws Exception {
+ increasePayloadBucketSize();
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 500, /* nCAsPerBuyer= */ 1, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingBuyers_500",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ resetPayloadBucketSize();
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingBuyers_1000() throws Exception {
+ increasePayloadBucketSize();
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 1000, /* nCAsPerBuyer= */ 1, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingBuyers_1000",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ resetPayloadBucketSize();
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingCAs_1() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 1, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingCAs_1",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingCAs_10() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 10, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingCAs_10",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingCAs_100() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 100, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingBuyers_100",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingCAs_500() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 500, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingCAs_500",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingCAs_1000() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 1000, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingCAs_1000",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingAds_5() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 10, /* nAdsPerCA= */ 5);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingAds_5",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingAds_25() throws Exception {
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 10, /* nAdsPerCA= */ 25);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingAds_25",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingAds_125() throws Exception {
+ increaseMaximumAds();
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 10, /* nAdsPerCA= */ 125);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingAds_125",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ resetMaximumAds();
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingAds_500() throws Exception {
+ increaseMaximumAds();
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 10, /* nAdsPerCA= */ 500);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingAds_500",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ resetMaximumAds();
+ }
+
+ @Test
+ public void test_withoutFiltering_varyingAds_1000() throws Exception {
+ increaseMaximumAds();
+ List<CustomAudience> customAudiences =
+ CustomAudienceFixture.getNValidCustomAudiences(
+ /* nBuyers= */ 4, /* nCAsPerBuyer= */ 10, /* nAdsPerCA= */ 1000);
+ CustomAudienceTestFixture.joinCustomAudiences(customAudiences);
+
+ long startTime = System.nanoTime();
+ GetAdSelectionDataRequest request =
+ new GetAdSelectionDataRequest.Builder()
+ .setSeller(AdTechIdentifier.fromString(SELLER))
+ .build();
+ GetAdSelectionDataOutcome outcome =
+ AD_SELECTION_CLIENT
+ .getAdSelectionData(request)
+ .get(API_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ long endTime = System.nanoTime();
+ Log.i(
+ TAG,
+ generateLogLabel(
+ getClass().getSimpleName(),
+ "test_withoutFiltering_varyingAds_1000",
+ (endTime - startTime) / NANO_TO_MILLISECONDS));
+
+ CustomAudienceTestFixture.leaveCustomAudience(customAudiences);
+ resetMaximumAds();
+ }
+
+ void increaseMaximumAds() {
+ ShellUtils.runShellCommand(
+ "device_config put adservices fledge_custom_audience_max_num_ads 1000");
+ ShellUtils.runShellCommand(
+ "device_config put adservices fledge_custom_audience_max_ads_size_b 1048576");
+ }
+
+ void resetMaximumAds() {
+ ShellUtils.runShellCommand(
+ "device_config put adservices fledge_custom_audience_max_num_ads 100");
+ ShellUtils.runShellCommand(
+ "device_config put adservices fledge_custom_audience_max_ads_size_b 10240");
+ }
+
+ void increasePayloadBucketSize() {
+ ShellUtils.runShellCommand(
+ "device_config put adservices fledge_auction_server_payload_bucket_sizes"
+ + " 0,1024,2048,4096,8192,16384,32768,65536,131072,262174,524288,1048576");
+ }
+
+ void resetPayloadBucketSize() {
+ ShellUtils.runShellCommand(
+ "device_config put adservices fledge_auction_server_payload_bucket_sizes"
+ + " 0,1024,2048,4096,8192,16384,32768,65536");
+ }
+}
diff --git a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/ServerAuctionOneBuyerLargeCaLatency.java b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/ServerAuctionOneBuyerLargeCaLatency.java
index 62299f741..a4953faed 100644
--- a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/ServerAuctionOneBuyerLargeCaLatency.java
+++ b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/fledge/ServerAuctionOneBuyerLargeCaLatency.java
@@ -66,7 +66,7 @@ public class ServerAuctionOneBuyerLargeCaLatency {
private static final String AD_WINNER_DOMAIN = "https://ba-buyer-5jyy5ulagq-uc.a.run.app/";
private static final String SELLER = "ba-seller-5jyy5ulagq-uc.a.run.app";
- private static final String SFE_ADDRESS = "https://seller1-paprod.sfe-gcp.com/v1/selectAd";
+ private static final String SFE_ADDRESS = "https://seller1-paprod.sfe.bas-gcp.pstest.dev/v1/selectAd";
private static final String CUSTOM_AUDIENCE_ONE_BUYER_ONE_CA_ONE_AD =
"CustomAudienceOneBuyerOneCaOneAd.json";
diff --git a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java
index 79b8bf311..77b20f7ea 100644
--- a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java
+++ b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java
@@ -19,7 +19,6 @@ package android.adservices.test.scenario.adservices.ui;
import android.content.Context;
import android.os.Trace;
import android.platform.test.scenario.annotation.Scenario;
-import android.util.Log;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -27,9 +26,11 @@ import androidx.test.uiautomator.UiDevice;
import com.android.adservices.common.AdServicesFlagsSetterRule;
import com.android.adservices.common.AdservicesTestHelper;
+import com.android.adservices.service.FlagsConstants;
import com.android.adservices.tests.ui.libs.AdservicesWorkflows;
import com.android.adservices.tests.ui.libs.UiConstants;
import com.android.adservices.tests.ui.libs.UiUtils;
+import com.android.modules.utils.build.SdkLevel;
import org.junit.After;
import org.junit.Before;
@@ -38,7 +39,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-/** Crystalball test for Topics API to collect System Heath metrics. */
@Scenario
@RunWith(JUnit4.class)
public class NotificationLandingPage {
@@ -50,7 +50,10 @@ public class NotificationLandingPage {
@Rule
public final AdServicesFlagsSetterRule flags =
- AdServicesFlagsSetterRule.forGlobalKillSwitchDisabledTests().setCompatModeFlags();
+ AdServicesFlagsSetterRule.forGlobalKillSwitchDisabledTests()
+ .setCompatModeFlags()
+ .setDebugUxFlagsForRvcUx()
+ .setFlag(FlagsConstants.KEY_ENABLE_ADEXT_DATA_SERVICE_DEBUG_PROXY, "false");
@Before
public void setup() throws Exception {
@@ -70,15 +73,15 @@ public class NotificationLandingPage {
@Test
public void testNotificationLandingPage() throws Exception {
- final long start = System.currentTimeMillis();
+ UiConstants.UX ux = UiConstants.UX.GA_UX;
+ if( SdkLevel.isAtLeastR() && !SdkLevel.isAtLeastS() ) {
+ ux = UiConstants.UX.RVC_UX;
+ }
Trace.beginSection("NotificationTriggerEvent");
AdservicesWorkflows.testNotificationActivityFlow(
- sContext, sDevice, true, UiConstants.UX.GA_UX, false, false, true);
+ sContext, sDevice, true, ux, true, false, true);
Trace.endSection();
-
- final long duration = System.currentTimeMillis() - start;
- Log.i(TAG, "(" + UI_NOTIFICATION_LATENCY_METRIC + ": " + duration + ")");
}
}
diff --git a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java
index 0c20f376e..a080c42a6 100644
--- a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java
+++ b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java
@@ -18,7 +18,7 @@ package android.adservices.test.scenario.adservices.ui;
import android.content.Context;
import android.platform.test.scenario.annotation.Scenario;
-import android.util.Log;
+import android.os.Trace;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -26,9 +26,11 @@ import androidx.test.uiautomator.UiDevice;
import com.android.adservices.common.AdServicesFlagsSetterRule;
import com.android.adservices.common.AdservicesTestHelper;
+import com.android.adservices.service.FlagsConstants;
import com.android.adservices.tests.ui.libs.AdservicesWorkflows;
import com.android.adservices.tests.ui.libs.UiConstants;
import com.android.adservices.tests.ui.libs.UiUtils;
+import com.android.modules.utils.build.SdkLevel;
import org.junit.After;
import org.junit.Before;
@@ -37,7 +39,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-/** Crystalball test for Topics API to collect System Heath metrics. */
@Scenario
@RunWith(JUnit4.class)
public class UiSettingsMainPage {
@@ -49,7 +50,10 @@ public class UiSettingsMainPage {
@Rule
public final AdServicesFlagsSetterRule flags =
- AdServicesFlagsSetterRule.forGlobalKillSwitchDisabledTests().setCompatModeFlags();
+ AdServicesFlagsSetterRule.forGlobalKillSwitchDisabledTests()
+ .setCompatModeFlags()
+ .setDebugUxFlagsForRvcUx()
+ .setFlag(FlagsConstants.KEY_ENABLE_ADEXT_DATA_SERVICE_DEBUG_PROXY, "false");
@Before
public void setup() throws Exception {
@@ -69,15 +73,19 @@ public class UiSettingsMainPage {
@Test
public void testSettingsPage() throws Exception {
- final long start = System.currentTimeMillis();
+ UiConstants.UX ux = UiConstants.UX.GA_UX;
+ if( SdkLevel.isAtLeastR() && !SdkLevel.isAtLeastS() ) {
+ ux = UiConstants.UX.RVC_UX;
+ }
+
+ Trace.beginSection("NotificationTriggerEvent");
AdservicesWorkflows.testSettingsPageFlow(
sContext,
sDevice,
- UiConstants.UX.GA_UX,
+ ux,
/* isOptIn= */ true,
/* isFlipConsent= */ true,
/* assertOptIn= */ false);
- final long duration = System.currentTimeMillis() - start;
- Log.i(TAG, "(" + UI_SETTINGS_LATENCY_METRIC + ": " + duration + ")");
+ Trace.endSection();
}
}
diff --git a/adservices/tests/perf/tests/src/android/adservices/test/scenario/adservices/fledge/GetAdSelectionDataLatencyMicroBenchmark.java b/adservices/tests/perf/tests/src/android/adservices/test/scenario/adservices/fledge/GetAdSelectionDataLatencyMicroBenchmark.java
new file mode 100644
index 000000000..298fed502
--- /dev/null
+++ b/adservices/tests/perf/tests/src/android/adservices/test/scenario/adservices/fledge/GetAdSelectionDataLatencyMicroBenchmark.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 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 android.adservices.test.scenario.adservices.fledge;
+
+public class GetAdSelectionDataLatencyMicroBenchmark extends GetAdSelectionDataLatency {}
diff --git a/adservices/tests/test-util/Android.bp b/adservices/tests/test-util/Android.bp
index 3c06879e5..24f94cb3d 100644
--- a/adservices/tests/test-util/Android.bp
+++ b/adservices/tests/test-util/Android.bp
@@ -64,6 +64,7 @@ android_library {
"androidx.test.runner",
"compatibility-device-util-axt",
"modules-utils-preconditions",
+ "adservices-shared-util", // For checkState method uses varargs.
// TODO(b/281577492): should use modules-utils-extended-mockito-rule instead
"modules-utils-testable-device-config",
],
diff --git a/adservices/tests/test-util/host-side/com/android/adservices/common/TestDeviceHelper.java b/adservices/tests/test-util/host-side/com/android/adservices/common/TestDeviceHelper.java
index 0ef8ff9c8..18c3d4562 100644
--- a/adservices/tests/test-util/host-side/com/android/adservices/common/TestDeviceHelper.java
+++ b/adservices/tests/test-util/host-side/com/android/adservices/common/TestDeviceHelper.java
@@ -97,8 +97,17 @@ public final class TestDeviceHelper {
.doesNotContain("Error: Activity not started, unable to resolve Intent");
}
- public static void enableComponent(String packageName, String className) {
- runShellCommand("pm enable %s/%s", packageName, className);
+ /** Enable the given component and return the result of the shell command */
+ public static String enableComponent(String packageName, String className) {
+ return runShellCommand("pm enable %s/%s", packageName, className);
+ }
+
+ /**
+ * Enable the given component for the given userId only and return the result of the shell
+ * command
+ */
+ public static String enableComponent(String packageName, String className, int userId) {
+ return runShellCommand("pm enable --user %d %s/%s", userId, packageName, className);
}
/**
diff --git a/adservices/tests/test-util/java/com/android/adservices/common/ExceptionFailureSyncCallback.java b/adservices/tests/test-util/java/com/android/adservices/common/ExceptionFailureSyncCallback.java
index a9d50b690..e41d9aa89 100644
--- a/adservices/tests/test-util/java/com/android/adservices/common/ExceptionFailureSyncCallback.java
+++ b/adservices/tests/test-util/java/com/android/adservices/common/ExceptionFailureSyncCallback.java
@@ -15,13 +15,12 @@
*/
package com.android.adservices.common;
+import static com.android.adservices.shared.util.Preconditions.checkState;
+import static com.android.internal.util.Preconditions.checkArgument;
+
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
-
-import com.google.errorprone.annotations.FormatMethod;
-import com.google.errorprone.annotations.FormatString;
// TODO(b/302757068): add unit tests (and/or convert tests from OutcomeReceiverForTestsTest)
/**
@@ -103,7 +102,7 @@ public abstract class ExceptionFailureSyncCallback<T> extends SyncCallback<T, Ex
*/
public <E extends Exception> E assertFailure(Class<E> expectedClass)
throws InterruptedException {
- Preconditions.checkArgument(expectedClass != null, "expectedClass cannot be null");
+ checkArgument(expectedClass != null, "expectedClass cannot be null");
Exception error = assertErrorReceived();
checkState(
expectedClass.isInstance(error),
@@ -130,15 +129,4 @@ public abstract class ExceptionFailureSyncCallback<T> extends SyncCallback<T, Ex
public T getResult() {
return getResultReceived();
}
-
- // TODO(b/303886367): move to common helper
- @FormatMethod
- private static void checkState(
- boolean expression,
- @FormatString String messageTemplate,
- @Nullable Object... messageArgs) {
- if (!expression) {
- throw new IllegalStateException(String.format(messageTemplate, messageArgs));
- }
- }
}
diff --git a/adservices/tests/test-util/java/com/android/adservices/mockito/ExtendedMockitoExpectations.java b/adservices/tests/test-util/java/com/android/adservices/mockito/ExtendedMockitoExpectations.java
index 98fdfdbbb..3efe757a9 100644
--- a/adservices/tests/test-util/java/com/android/adservices/mockito/ExtendedMockitoExpectations.java
+++ b/adservices/tests/test-util/java/com/android/adservices/mockito/ExtendedMockitoExpectations.java
@@ -206,7 +206,20 @@ public final class ExtendedMockitoExpectations {
* int)}.
*/
public static void verifyErrorLogUtilErrorWithAnyException(int errorCode, int ppapiName) {
- verify(() -> ErrorLogUtil.e(any(), eq(errorCode), eq(ppapiName)));
+ verifyErrorLogUtilErrorWithAnyException(errorCode, ppapiName, times(1));
+ }
+
+ /**
+ * Verifies {@link ErrorLogUtil#e()} was called with the expected values, using Mockito's {@link
+ * VerificationMode} to set the number of times (like {@code times(2)} or {@code never}).
+ *
+ * <p><b>Note: </b>you must call either {@link #doNothingOnErrorLogUtilError()} or {@link
+ * #mockErrorLogUtilWithThrowable()} before the test calls {@link ErrorLogUtil#e(Throwable, int,
+ * int)}.
+ */
+ public static void verifyErrorLogUtilErrorWithAnyException(
+ int errorCode, int ppapiName, VerificationMode mode) {
+ verify(() -> ErrorLogUtil.e(any(), eq(errorCode), eq(ppapiName)), mode);
}
/**
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractAdServicesFlagsSetterRule.java b/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractAdServicesFlagsSetterRule.java
index 655702791..c0c704da1 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractAdServicesFlagsSetterRule.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractAdServicesFlagsSetterRule.java
@@ -267,6 +267,18 @@ abstract class AbstractAdServicesFlagsSetterRule<T extends AbstractAdServicesFla
});
}
+ public T setDebugUxFlagsForRvcUx() {
+ return runOrCache(
+ "setDebugUxFlagsForRvcUx()",
+ () -> {
+ if (!isAtLeastS() && isAtLeastR()) {
+ setFlag(FlagsConstants.KEY_CONSENT_NOTIFICATION_ACTIVITY_DEBUG_MODE, true);
+ setFlag(FlagsConstants.KEY_DEBUG_UX, "RVC_UX");
+ return;
+ }
+ });
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE: DO NOT add new setXyz() methods, unless they need non-trivial logic. Instead, let //
// your test call setFlags(flagName) (statically import FlagsConstant.flagName), which will //
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java b/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java
index 9d9fa631c..8400a12ee 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java
@@ -369,8 +369,12 @@ abstract class AbstractFlagsSetterRule<T extends AbstractFlagsSetterRule<T>> imp
/** Gets the device's SDK level. */
protected abstract int getDeviceSdk();
+ protected boolean isAtLeastR() {
+ return getDeviceSdk() >= 30;
+ }
+
protected boolean isAtLeastS() {
- return getDeviceSdk() > 31;
+ return getDeviceSdk() >= 31;
}
protected boolean isAtLeastT() {
@@ -385,7 +389,13 @@ abstract class AbstractFlagsSetterRule<T extends AbstractFlagsSetterRule<T>> imp
// Set the annotated flags with the specified value for a particular test method.
protected void setAnnotatedFlags(Description description) {
- for (Annotation annotation : description.getAnnotations()) {
+ List<Annotation> annotations = getAllFlagAnnotations(description);
+
+ // Apply the annotations in the reverse order. First apply from the super classes, test
+ // class and then test method. If same annotated flag is present in class and test
+ // method, test method takes higher priority.
+ for (int i = annotations.size() - 1; i >= 0; i--) {
+ Annotation annotation = annotations.get(i);
if (annotation instanceof SetFlagEnabled) {
setAnnotatedFlag((SetFlagEnabled) annotation);
} else if (annotation instanceof SetFlagsEnabled) {
@@ -416,7 +426,6 @@ abstract class AbstractFlagsSetterRule<T extends AbstractFlagsSetterRule<T>> imp
setAnnotatedFlag((SetStringFlags) annotation);
}
}
- // TODO(b/300146214) Add code to scan class / superclasses flag annotations.
}
private T setOrCacheFlag(String name, String value) {
@@ -542,6 +551,50 @@ abstract class AbstractFlagsSetterRule<T extends AbstractFlagsSetterRule<T>> imp
}
}
+ private boolean isFlagAnnotationPresent(Annotation annotation) {
+ return (annotation instanceof SetFlagEnabled)
+ || (annotation instanceof SetFlagsEnabled)
+ || (annotation instanceof SetFlagDisabled)
+ || (annotation instanceof SetFlagsDisabled)
+ || (annotation instanceof SetIntegerFlag)
+ || (annotation instanceof SetIntegerFlags)
+ || (annotation instanceof SetLongFlag)
+ || (annotation instanceof SetLongFlags)
+ || (annotation instanceof SetFloatFlag)
+ || (annotation instanceof SetFloatFlags)
+ || (annotation instanceof SetDoubleFlag)
+ || (annotation instanceof SetDoubleFlags)
+ || (annotation instanceof SetStringFlag)
+ || (annotation instanceof SetStringFlags);
+ }
+
+ private List<Annotation> getAllFlagAnnotations(Description description) {
+ // TODO(b/318893752): Move this to a helper function to scan test method, class and
+ // superclasses for annotations.
+ List<Annotation> result = new ArrayList<>();
+ for (Annotation testMethodAnnotation : description.getAnnotations()) {
+ if (isFlagAnnotationPresent(testMethodAnnotation)) {
+ result.add(testMethodAnnotation);
+ }
+ }
+
+ // Get all the flag based annotations from test class and super classes
+ Class<?> clazz = description.getTestClass();
+ do {
+ Annotation[] classAnnotations = clazz.getAnnotations();
+ if (classAnnotations != null) {
+ for (Annotation annotation : classAnnotations) {
+ if (isFlagAnnotationPresent(annotation)) {
+ result.add(annotation);
+ }
+ }
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != null);
+
+ return result;
+ }
+
// Single SetFlagEnabled annotations present
private void setAnnotatedFlag(SetFlagEnabled annotation) {
setFlag(annotation.value(), true);
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java
index 4b24b8443..93988e09f 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetDoubleFlags.class)
public @interface SetDoubleFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java
index f15239680..7415bb105 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetDoubleFlags {
SetDoubleFlag[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java
index a62d8b076..a8d3bddce 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
* in the test to false.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetFlagsDisabled.class)
public @interface SetFlagDisabled {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java
index bdc0ae77d..ae041a7d0 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
* in the test to true.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetFlagsEnabled.class)
public @interface SetFlagEnabled {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java
index 2f470e2a3..361950b09 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetFlagsDisabled {
SetFlagDisabled[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java
index bb67d1182..7e197c8de 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetFlagsEnabled {
SetFlagEnabled[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java
index 4f404404d..421f79cbb 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetFloatFlags.class)
public @interface SetFloatFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java
index 0e839c2ab..a15f4a578 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetFloatFlags {
SetFloatFlag[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java
index e02b72f79..c5895be1d 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetIntegerFlags.class)
public @interface SetIntegerFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java
index b8386707f..cc76a947e 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetIntegerFlags {
SetIntegerFlag[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java
index 473758cd2..bee66b142 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetLongFlags.class)
public @interface SetLongFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java
index 46303a573..38309e88d 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetLongFlags {
SetLongFlag[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java
index 1b46d431b..bb3685892 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetStringFlags.class)
public @interface SetStringFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java
index bf39a4d60..f4bac410b 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetStringFlags {
SetStringFlag[] value();
}
diff --git a/adservices/tests/unittest/adservices-test-utility/AndroidTest.xml b/adservices/tests/unittest/adservices-test-utility/AndroidTest.xml
index 61f6fadac..4893bd4eb 100644
--- a/adservices/tests/unittest/adservices-test-utility/AndroidTest.xml
+++ b/adservices/tests/unittest/adservices-test-utility/AndroidTest.xml
@@ -28,4 +28,13 @@
<object type="module_controller"
class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
+ <!-- Entries below are neceessary so atest can run specific test classes without specifying the
+ module name (for example: atest AndroidSdkRangeTest) -->
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="AdServicesTestUtilityTests.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.adservices.testutil.tests" />
+ </test>
</configuration>
diff --git a/adservices/tests/unittest/fixtures/java/android/adservices/adselection/AdSelectionConfigFixture.java b/adservices/tests/unittest/fixtures/java/android/adservices/adselection/AdSelectionConfigFixture.java
index 0f1b38537..cfc066974 100644
--- a/adservices/tests/unittest/fixtures/java/android/adservices/adselection/AdSelectionConfigFixture.java
+++ b/adservices/tests/unittest/fixtures/java/android/adservices/adselection/AdSelectionConfigFixture.java
@@ -125,8 +125,9 @@ public class AdSelectionConfigFixture {
* for the unit tests, this version of Ad Selection builder includes contextual Ads as well
* @hide
*/
- public static AdSelectionConfig.Builder anAdSelectionConfigWithContextualAdsBuilder() {
+ public static AdSelectionConfig.Builder anAdSelectionConfigWithSignedContextualAdsBuilder() {
return anAdSelectionConfigBuilder()
- .setBuyerSignedContextualAds(SignedContextualAdsFixture.getBuyerContextualAdsMap());
+ .setBuyerSignedContextualAds(
+ SignedContextualAdsFixture.getBuyerSignedContextualAdsMap());
}
}
diff --git a/adservices/tests/unittest/fixtures/java/android/adservices/adselection/SignedContextualAdsFixture.java b/adservices/tests/unittest/fixtures/java/android/adservices/adselection/SignedContextualAdsFixture.java
index d1a9a4f55..2988a2aea 100644
--- a/adservices/tests/unittest/fixtures/java/android/adservices/adselection/SignedContextualAdsFixture.java
+++ b/adservices/tests/unittest/fixtures/java/android/adservices/adselection/SignedContextualAdsFixture.java
@@ -16,15 +16,25 @@
package android.adservices.adselection;
+import static com.android.adservices.service.adselection.signature.ProtectedAudienceSignatureManager.PRIVATE_TEST_KEY_STRING;
+
import android.adservices.common.AdData;
import android.adservices.common.AdDataFixture;
import android.adservices.common.AdTechIdentifier;
import android.adservices.common.CommonFixture;
import android.net.Uri;
+import com.android.adservices.LoggerFactory;
+import com.android.adservices.service.adselection.signature.SignedContextualAdsHashUtil;
+
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
@@ -33,7 +43,8 @@ import java.util.stream.Collectors;
* SignedContextualAds}.
*/
public class SignedContextualAdsFixture {
- public static final byte[] PLACEHOLDER_SIGNATURE = new byte[] {0, 0};
+ private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger();
+ private static final byte[] PLACEHOLDER_EMPTY_SIGNATURE = new byte[] {};
public static final AdTechIdentifier BUYER = CommonFixture.VALID_BUYER_1;
public static final AdTechIdentifier BUYER_2 = CommonFixture.VALID_BUYER_2;
@@ -51,44 +62,128 @@ public class SignedContextualAdsFixture {
public static final List<AdWithBid> ADS_WITH_BID =
ImmutableList.of(AD_WITH_BID_1, AD_WITH_BID_2);
- public static SignedContextualAds.Builder aSignedContextualAdBuilder() {
+ /**
+ * Returns a {@link SignedContextualAds} object with a placeholder signature
+ *
+ * <p>This object's signature will not pass the verification
+ */
+ public static SignedContextualAds.Builder aContextualAdsWithEmptySignatureBuilder() {
return new SignedContextualAds.Builder()
.setBuyer(BUYER)
.setDecisionLogicUri(DECISION_LOGIC_URI)
.setAdsWithBid(ADS_WITH_BID)
- .setSignature(PLACEHOLDER_SIGNATURE);
+ .setSignature(PLACEHOLDER_EMPTY_SIGNATURE);
}
- public static SignedContextualAds.Builder generateSignedContextualAds(
- AdTechIdentifier buyer, List<Double> bids) {
- return new SignedContextualAds.Builder()
+ /**
+ * Returns a {@link SignedContextualAds} object with a placeholder signature and the given
+ * buyer.
+ *
+ * <p>This object's signature will not pass the verification
+ */
+ public static SignedContextualAds.Builder aContextualAdsWithEmptySignatureBuilder(
+ AdTechIdentifier buyer) {
+ return aContextualAdsWithEmptySignatureBuilder()
.setBuyer(buyer)
- .setDecisionLogicUri(CommonFixture.getUri(buyer, DECISION_LOGIC_FRAGMENT))
- .setAdsWithBid(
- bids.stream()
- .map(
- bid ->
- new AdWithBid(
- AdDataFixture.getValidFilterAdDataByBuyer(
- buyer, bid.intValue()),
- bid))
- .collect(Collectors.toList()))
- .setSignature(PLACEHOLDER_SIGNATURE);
+ .setDecisionLogicUri(CommonFixture.getUri(buyer, DECISION_LOGIC_FRAGMENT));
+ }
+
+ /**
+ * Returns a {@link SignedContextualAds} object with a placeholder signature with given buyer
+ * and bids.
+ *
+ * <p>This object's signature will not pass the verification
+ */
+ public static SignedContextualAds.Builder aContextualAdsWithEmptySignatureBuilder(
+ AdTechIdentifier buyer, List<Double> bids) {
+ List<AdWithBid> adsWithBid =
+ bids.stream()
+ .map(
+ bid ->
+ new AdWithBid(
+ AdDataFixture.getValidFilterAdDataByBuyer(
+ buyer, bid.intValue()),
+ bid))
+ .collect(Collectors.toList());
+ return aContextualAdsWithEmptySignatureBuilder(buyer).setAdsWithBid(adsWithBid);
}
- public static SignedContextualAds aSignedContextualAd() {
- return aSignedContextualAdBuilder().build();
+ /**
+ * Returns a {@link SignedContextualAds} object that is signed.
+ *
+ * <p>This object's signature can be verified using {@link SignedContextualAdsFixture
+ * #PUBLIC_KEY_STRING}.
+ */
+ public static SignedContextualAds aSignedContextualAds() {
+ return signContextualAds(aContextualAdsWithEmptySignatureBuilder());
}
- public static SignedContextualAds aSignedContextualAd(AdTechIdentifier buyer) {
- return aSignedContextualAdBuilder().setBuyer(buyer).build();
+ /**
+ * Returns a {@link SignedContextualAds} object that is signed with given buyer.
+ *
+ * <p>This object's signature can be verified using {@link SignedContextualAdsFixture
+ * #PUBLIC_KEY_STRING}.
+ */
+ public static SignedContextualAds aSignedContextualAds(AdTechIdentifier buyer) {
+ return signContextualAds(aContextualAdsWithEmptySignatureBuilder(buyer));
}
- public static ImmutableMap<AdTechIdentifier, SignedContextualAds> getBuyerContextualAdsMap() {
+ /**
+ * Returns a {@link SignedContextualAds} object that is signed with given buyer.
+ *
+ * <p>This object's signature can be verified using {@link SignedContextualAdsFixture
+ * #PUBLIC_KEY_STRING}.
+ */
+ public static SignedContextualAds aSignedContextualAds(
+ AdTechIdentifier buyer, List<Double> bids) {
+ return signContextualAds(aContextualAdsWithEmptySignatureBuilder(buyer, bids));
+ }
+
+ public static ImmutableMap<AdTechIdentifier, SignedContextualAds>
+ getBuyerSignedContextualAdsMap() {
return ImmutableMap.of(
CommonFixture.VALID_BUYER_1,
- aSignedContextualAd(CommonFixture.VALID_BUYER_1),
+ aSignedContextualAds(CommonFixture.VALID_BUYER_1),
CommonFixture.VALID_BUYER_2,
- aSignedContextualAd(CommonFixture.VALID_BUYER_2));
+ aSignedContextualAds(CommonFixture.VALID_BUYER_2));
+ }
+
+ /**
+ * Signs contextual ads using {@link
+ * com.android.adservices.service.adselection.signature.ProtectedAudienceSignatureManager
+ * #PRIVATE_KEY_STRING}.
+ *
+ * <p>Bundle can be verified using {@link
+ * com.android.adservices.service.adselection.signature.ProtectedAudienceSignatureManager
+ * #PUBLIC_KEY_STRING}
+ */
+ public static SignedContextualAds signContextualAds(
+ SignedContextualAds.Builder notSignedContextualAdsBuilder) {
+ SignedContextualAds signedContextualAds;
+ try {
+ Signature ecdsaSigner = getECDSASignatureInstance();
+ ecdsaSigner.update(
+ new SignedContextualAdsHashUtil()
+ .serialize(notSignedContextualAdsBuilder.build()));
+ signedContextualAds =
+ notSignedContextualAdsBuilder.setSignature(ecdsaSigner.sign()).build();
+ } catch (Exception e) {
+ String errMsg =
+ String.format(
+ "Something went wrong during signing a contextual ad bundle: %s", e);
+ sLogger.v(errMsg);
+ throw new RuntimeException(errMsg, e);
+ }
+ return signedContextualAds;
+ }
+
+ private static Signature getECDSASignatureInstance() throws Exception {
+ byte[] privateKeyBytes = Base64.getDecoder().decode(PRIVATE_TEST_KEY_STRING);
+ PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKeyBytes);
+ KeyFactory keyFactory = KeyFactory.getInstance("EC");
+ PrivateKey privateKey = keyFactory.generatePrivate(spec);
+ Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
+ ecdsaSign.initSign(privateKey);
+ return ecdsaSign;
}
}
diff --git a/adservices/tests/unittest/fixtures/java/android/adservices/customaudience/CustomAudienceFixture.java b/adservices/tests/unittest/fixtures/java/android/adservices/customaudience/CustomAudienceFixture.java
index bc5425a1c..daaf142e6 100644
--- a/adservices/tests/unittest/fixtures/java/android/adservices/customaudience/CustomAudienceFixture.java
+++ b/adservices/tests/unittest/fixtures/java/android/adservices/customaudience/CustomAudienceFixture.java
@@ -16,6 +16,10 @@
package android.adservices.customaudience;
+import static android.adservices.common.AdDataFixture.getValidFilterAdDataWithAdRenderIdByBuyer;
+import static android.adservices.customaudience.TrustedBiddingDataFixture.getValidTrustedBiddingDataByBuyer;
+
+import android.adservices.common.AdData;
import android.adservices.common.AdDataFixture;
import android.adservices.common.AdSelectionSignals;
import android.adservices.common.AdTechIdentifier;
@@ -24,7 +28,9 @@ import android.net.Uri;
import java.time.Duration;
import java.time.Instant;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/** Utility class supporting custom audience API unit tests */
public final class CustomAudienceFixture {
@@ -96,8 +102,7 @@ public final class CustomAudienceFixture {
.setExpirationTime(CustomAudienceFixture.VALID_EXPIRATION_TIME)
.setDailyUpdateUri(CustomAudienceFixture.getValidDailyUpdateUriByBuyer(buyer))
.setUserBiddingSignals(CustomAudienceFixture.VALID_USER_BIDDING_SIGNALS)
- .setTrustedBiddingData(
- TrustedBiddingDataFixture.getValidTrustedBiddingDataByBuyer(buyer))
+ .setTrustedBiddingData(getValidTrustedBiddingDataByBuyer(buyer))
.setBiddingLogicUri(CustomAudienceFixture.getValidBiddingLogicUriByBuyer(buyer))
.setAds(AdDataFixture.getValidAdsByBuyer(buyer));
}
@@ -134,9 +139,54 @@ public final class CustomAudienceFixture {
.setExpirationTime(CustomAudienceFixture.VALID_EXPIRATION_TIME)
.setDailyUpdateUri(CustomAudienceFixture.getValidDailyUpdateUriByBuyer(buyer))
.setUserBiddingSignals(CustomAudienceFixture.VALID_USER_BIDDING_SIGNALS)
- .setTrustedBiddingData(
- TrustedBiddingDataFixture.getValidTrustedBiddingDataByBuyer(buyer))
+ .setTrustedBiddingData(getValidTrustedBiddingDataByBuyer(buyer))
.setBiddingLogicUri(CustomAudienceFixture.getValidBiddingLogicUriByBuyer(buyer))
.setAds(AdDataFixture.getValidFilterAdsByBuyer(buyer));
}
+
+ /** Build valid CA with filters and render id */
+ public static CustomAudience.Builder getValidBuilderForBuyerFiltersWithAdRenderId(
+ AdTechIdentifier buyer) {
+ return new CustomAudience.Builder()
+ .setBuyer(buyer)
+ .setName(CustomAudienceFixture.VALID_NAME)
+ .setActivationTime(CustomAudienceFixture.VALID_ACTIVATION_TIME)
+ .setExpirationTime(CustomAudienceFixture.VALID_EXPIRATION_TIME)
+ .setDailyUpdateUri(CustomAudienceFixture.getValidDailyUpdateUriByBuyer(buyer))
+ .setUserBiddingSignals(CustomAudienceFixture.VALID_USER_BIDDING_SIGNALS)
+ .setTrustedBiddingData(getValidTrustedBiddingDataByBuyer(buyer))
+ .setBiddingLogicUri(CustomAudienceFixture.getValidBiddingLogicUriByBuyer(buyer))
+ .setAds(AdDataFixture.getValidFilterAdsWithAdRenderIdByBuyer(buyer));
+ }
+
+ /** Build N valid CAs with filters and render id */
+ public static List<CustomAudience> getNValidCustomAudiences(
+ int nBuyers, int nCAsPerBuyer, int nAdsPerCA) {
+ List<CustomAudience> customAudiences = new ArrayList<>();
+ for (int b = 0; b < nBuyers; b++) {
+ AdTechIdentifier buyer = AdTechIdentifier.fromString("buyer%d.com".formatted(b));
+ for (int c = 0; c < nCAsPerBuyer; c++) {
+ List<AdData> ads = new ArrayList<>();
+ for (int a = 0; a < nAdsPerCA; a++) {
+ ads.add(
+ getValidFilterAdDataWithAdRenderIdByBuyer(
+ buyer, /* sequenceNumber= */ a));
+ }
+ CustomAudience customAudience =
+ new CustomAudience.Builder()
+ .setBuyer(buyer)
+ .setName(VALID_NAME)
+ .setActivationTime(VALID_ACTIVATION_TIME)
+ .setExpirationTime(VALID_EXPIRATION_TIME)
+ .setDailyUpdateUri(getValidDailyUpdateUriByBuyer(buyer))
+ .setBiddingLogicUri(getValidBiddingLogicUriByBuyer(buyer))
+ .setUserBiddingSignals(VALID_USER_BIDDING_SIGNALS)
+ .setTrustedBiddingData(getValidTrustedBiddingDataByBuyer(buyer))
+ .setAds(ads)
+ .build();
+ customAudiences.add(customAudience);
+ }
+ }
+ return customAudiences;
+ }
}
diff --git a/adservices/tests/unittest/fixtures/java/com/android/adservices/service/PhFlagsFixture.java b/adservices/tests/unittest/fixtures/java/com/android/adservices/service/PhFlagsFixture.java
index a1ddecae4..d9be9de3f 100644
--- a/adservices/tests/unittest/fixtures/java/com/android/adservices/service/PhFlagsFixture.java
+++ b/adservices/tests/unittest/fixtures/java/com/android/adservices/service/PhFlagsFixture.java
@@ -28,6 +28,7 @@ import static com.android.adservices.service.Flags.FLEDGE_BACKGROUND_FETCH_NETWO
import static com.android.adservices.service.Flags.FLEDGE_REPORT_IMPRESSION_OVERALL_TIMEOUT_MS;
import static com.android.adservices.service.Flags.SDK_REQUEST_PERMITS_PER_SECOND;
import static com.android.adservices.service.FlagsConstants.KEY_AD_ID_FETCHER_TIMEOUT_MS;
+import static com.android.adservices.service.FlagsConstants.KEY_DISABLE_FLEDGE_ENROLLMENT_CHECK;
import static com.android.adservices.service.FlagsConstants.KEY_ENFORCE_FOREGROUND_STATUS_FLEDGE_OVERRIDE;
import static com.android.adservices.service.FlagsConstants.KEY_ENFORCE_FOREGROUND_STATUS_FLEDGE_REPORT_IMPRESSION;
import static com.android.adservices.service.FlagsConstants.KEY_ENFORCE_FOREGROUND_STATUS_FLEDGE_REPORT_INTERACTION;
@@ -35,22 +36,12 @@ import static com.android.adservices.service.FlagsConstants.KEY_ENFORCE_FOREGROU
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_AD_SELECTION_FILTERING_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_AD_SELECTION_PREBUILT_URI_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_AUCTION_SERVER_KILL_SWITCH;
-import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_BACKGROUND_FETCH_ELIGIBLE_UPDATE_BASE_INTERVAL_S;
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CPC_BILLING_ENABLED;
-import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_COUNT;
-import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_NAME_SIZE_B;
-import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_NUM_ADS;
-import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_OWNER_COUNT;
-import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_PER_APP_MAX_COUNT;
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_DATA_VERSION_HEADER_ENABLED;
-import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED;
-import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_MAX_USER_BIDDING_SIGNALS_SIZE_B;
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_REGISTER_AD_BEACON_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_PROTECTED_SIGNALS_CLEANUP_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_SDK_REQUEST_PERMITS_PER_SECOND;
-import static org.junit.Assert.assertEquals;
-
import android.provider.DeviceConfig;
/**
@@ -97,21 +88,6 @@ public final class PhFlagsFixture {
FLEDGE_AUCTION_SERVER_BACKGROUND_KEY_FETCH_NETWORK_CONNECT_TIMEOUT_MS
+ (int) ADDITIONAL_TIMEOUT;
- public static void configureFledgeBackgroundFetchEligibleUpdateBaseIntervalS(
- final long phOverridingValue) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_FLEDGE_BACKGROUND_FETCH_ELIGIBLE_UPDATE_BASE_INTERVAL_S,
- Long.toString(phOverridingValue),
- /* makeDefault */ false);
-
- Flags phFlags = FlagsFactory.getFlags();
- assertEquals(
- "Failed to configure P/H flag",
- phOverridingValue,
- phFlags.getFledgeBackgroundFetchEligibleUpdateBaseIntervalS());
- }
-
/** Enables test to override the flag enabling ad selection filtering */
public static void overrideFledgeAdSelectionFilteringEnabled(boolean value) {
DeviceConfig.setProperty(
@@ -182,19 +158,6 @@ public final class PhFlagsFixture {
}
/**
- * Allows tests to override seed enrollment data flag thereby seeding data into enrollment table
- *
- * @param enable disable enrollment seed
- */
- public static void overrideEnableEnrollmentSeed(boolean enable) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- FlagsConstants.KEY_ENABLE_ENROLLMENT_TEST_SEED,
- Boolean.toString(enable),
- false);
- }
-
- /**
* Enables test to override the flag enabling the enrollment check for callers of Fledge APIs.
*
* @param enable whether enable or disable the check
@@ -202,7 +165,7 @@ public final class PhFlagsFixture {
public static void overrideFledgeEnrollmentCheck(boolean enable) {
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_ADSERVICES,
- FlagsConstants.KEY_DISABLE_FLEDGE_ENROLLMENT_CHECK,
+ KEY_DISABLE_FLEDGE_ENROLLMENT_CHECK,
Boolean.toString(!enable),
false);
}
@@ -310,69 +273,6 @@ public final class PhFlagsFixture {
true);
}
- /** Switches the fetchAndJoinCustomAudience API on/off. */
- public static void overrideFledgeFetchCustomAudienceEnabled(boolean value) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_ENABLED,
- Boolean.toString(value),
- true);
- }
-
- /** Configures the maximum size of a custom audience's name. */
- public static void overrideFledgeCustomAudienceMaxNameSizeB(int value) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_NAME_SIZE_B,
- Integer.toString(value),
- true);
- }
-
- /** Configures the maximum size of a custom audience's user bidding signals. */
- public static void overrideFledgeFetchCustomAudienceMaxUserBiddingSignalsSizeB(int value) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_FLEDGE_FETCH_CUSTOM_AUDIENCE_MAX_USER_BIDDING_SIGNALS_SIZE_B,
- Integer.toString(value),
- true);
- }
-
- /** Configures the maximum number of ads allowed per custom audience. */
- public static void overrideFledgeCustomAudienceMaxNumAds(int value) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_NUM_ADS,
- Integer.toString(value),
- true);
- }
-
- /** Configures the maximum total number of custom audiences in the datastore. */
- public static void overrideFledgeCustomAudienceMaxCount(int value) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_COUNT,
- Integer.toString(value),
- true);
- }
-
- /** Configures the maximum number of custom audiences per owner application in the datastore. */
- public static void overrideFledgeCustomAudiencePerAppMaxCount(int value) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_FLEDGE_CUSTOM_AUDIENCE_PER_APP_MAX_COUNT,
- Integer.toString(value),
- true);
- }
-
- /** Configures the maximum number of owner applications in the datastore. */
- public static void overrideFledgeCustomAudienceMaxOwnerCount(int value) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_FLEDGE_CUSTOM_AUDIENCE_MAX_OWNER_COUNT,
- Integer.toString(value),
- true);
- }
-
/** Overrides whether the {@code registerAdBeacon} feature is enabled. */
public static void overrideFledgeRegisterAdBeaconEnabled(boolean value) {
DeviceConfig.setProperty(
diff --git a/adservices/tests/unittest/fixtures/java/com/android/adservices/service/measurement/AsyncRegistrationFixture.java b/adservices/tests/unittest/fixtures/java/com/android/adservices/service/measurement/AsyncRegistrationFixture.java
index bd7aaf89a..1b5ddcb20 100644
--- a/adservices/tests/unittest/fixtures/java/com/android/adservices/service/measurement/AsyncRegistrationFixture.java
+++ b/adservices/tests/unittest/fixtures/java/com/android/adservices/service/measurement/AsyncRegistrationFixture.java
@@ -18,6 +18,7 @@ package com.android.adservices.service.measurement;
import android.net.Uri;
+import com.android.adservices.service.measurement.registration.AsyncRedirect;
import com.android.adservices.service.measurement.registration.AsyncRegistration;
import java.util.UUID;
@@ -40,7 +41,8 @@ public class AsyncRegistrationFixture {
.setType(ValidAsyncRegistrationParams.TYPE)
.setDebugKeyAllowed(ValidAsyncRegistrationParams.DEBUG_KEY_ALLOWED)
.setRegistrationId(ValidAsyncRegistrationParams.REGISTRATION_ID)
- .setPostBody(ValidAsyncRegistrationParams.POST_BODY);
+ .setPostBody(ValidAsyncRegistrationParams.POST_BODY)
+ .setRedirectBehavior(ValidAsyncRegistrationParams.REDIRECT_BEHAVIOR);
}
public static AsyncRegistration getValidAsyncRegistration() {
@@ -62,5 +64,7 @@ public class AsyncRegistrationFixture {
public static final String REGISTRATION_ID = "R1";
public static final String PLATFORM_AD_ID = "test-platform-ad-id";
public static final String POST_BODY = "{\"ad_location\":\"bottom_right\"}";
+ public static final AsyncRedirect.RedirectBehavior REDIRECT_BEHAVIOR =
+ AsyncRedirect.RedirectBehavior.AS_IS;
}
}
diff --git a/adservices/tests/unittest/framework/src/android/adservices/adselection/SignedContextualAdsTest.java b/adservices/tests/unittest/framework/src/android/adservices/adselection/SignedContextualAdsTest.java
index f46a51cf6..3362c47c0 100644
--- a/adservices/tests/unittest/framework/src/android/adservices/adselection/SignedContextualAdsTest.java
+++ b/adservices/tests/unittest/framework/src/android/adservices/adselection/SignedContextualAdsTest.java
@@ -16,9 +16,10 @@
package android.adservices.adselection;
-import static junit.framework.Assert.assertEquals;
+import static android.adservices.adselection.SignedContextualAdsFixture.AD_WITH_BID_1;
+
+import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertThrows;
import android.adservices.common.CommonFixture;
@@ -26,8 +27,11 @@ import android.os.Parcel;
import org.junit.Test;
+import java.util.Collections;
+
/** Unit tests for {@link SignedContextualAds} */
public class SignedContextualAdsTest {
+ public static final byte[] TEST_SIGNATURE = new byte[] {0, 1, 2};
@Test
public void testBuildContextualAdsSuccess() {
@@ -36,156 +40,141 @@ public class SignedContextualAdsTest {
.setBuyer(SignedContextualAdsFixture.BUYER)
.setDecisionLogicUri(SignedContextualAdsFixture.DECISION_LOGIC_URI)
.setAdsWithBid(SignedContextualAdsFixture.ADS_WITH_BID)
- .setSignature(SignedContextualAdsFixture.PLACEHOLDER_SIGNATURE)
+ .setSignature(TEST_SIGNATURE)
.build();
- assertEquals(contextualAds.getBuyer(), SignedContextualAdsFixture.BUYER);
- assertEquals(
- contextualAds.getDecisionLogicUri(), SignedContextualAdsFixture.DECISION_LOGIC_URI);
- assertEquals(contextualAds.getAdsWithBid(), SignedContextualAdsFixture.ADS_WITH_BID);
- assertArrayEquals(
- contextualAds.getSignature(), SignedContextualAdsFixture.PLACEHOLDER_SIGNATURE);
+ assertThat(contextualAds.getBuyer()).isEqualTo(SignedContextualAdsFixture.BUYER);
+ assertThat(contextualAds.getDecisionLogicUri())
+ .isEqualTo(SignedContextualAdsFixture.DECISION_LOGIC_URI);
+ assertThat(contextualAds.getAdsWithBid())
+ .isEqualTo(SignedContextualAdsFixture.ADS_WITH_BID);
+ assertThat(contextualAds.getSignature()).isEqualTo(TEST_SIGNATURE);
}
@Test
public void testParcelValidContextualAdsSuccess() {
- SignedContextualAds contextualAds = SignedContextualAdsFixture.aSignedContextualAd();
+ SignedContextualAds contextualAds = SignedContextualAdsFixture.aSignedContextualAds();
Parcel p = Parcel.obtain();
contextualAds.writeToParcel(p, 0);
p.setDataPosition(0);
SignedContextualAds fromParcel = SignedContextualAds.CREATOR.createFromParcel(p);
- assertEquals(contextualAds.getBuyer(), fromParcel.getBuyer());
- assertEquals(contextualAds.getDecisionLogicUri(), fromParcel.getDecisionLogicUri());
- assertEquals(contextualAds.getAdsWithBid(), fromParcel.getAdsWithBid());
- assertArrayEquals(contextualAds.getSignature(), fromParcel.getSignature());
+ assertThat(fromParcel.getBuyer()).isEqualTo(contextualAds.getBuyer());
+ assertThat(fromParcel.getDecisionLogicUri()).isEqualTo(contextualAds.getDecisionLogicUri());
+ assertThat(fromParcel.getAdsWithBid()).isEqualTo(contextualAds.getAdsWithBid());
+ assertThat(fromParcel.getSignature()).isEqualTo(contextualAds.getSignature());
}
@Test
public void testSetContextualAdsNullBuyerFailure() {
assertThrows(
- NullPointerException.class,
- () -> {
- new SignedContextualAds.Builder().setBuyer(null);
- });
+ NullPointerException.class, () -> new SignedContextualAds.Builder().setBuyer(null));
}
@Test
public void testSetContextualAdsNullDecisionLogicUriFailure() {
assertThrows(
NullPointerException.class,
- () -> {
- new SignedContextualAds.Builder().setDecisionLogicUri(null);
- });
+ () -> new SignedContextualAds.Builder().setDecisionLogicUri(null));
}
@Test
public void testSetContextualAdsNullAdWithBidFailure() {
assertThrows(
NullPointerException.class,
- () -> {
- new SignedContextualAds.Builder().setAdsWithBid(null);
- });
+ () -> new SignedContextualAds.Builder().setAdsWithBid(null));
}
@Test
public void testSetContextualAdsNullSignatureFailure() {
assertThrows(
NullPointerException.class,
- () -> {
- new SignedContextualAds.Builder().setSignature(null);
- });
+ () -> new SignedContextualAds.Builder().setSignature(null));
}
@Test
public void testParcelNullDestFailure() {
- SignedContextualAds contextualAds = SignedContextualAdsFixture.aSignedContextualAd();
+ SignedContextualAds contextualAds = SignedContextualAdsFixture.aSignedContextualAds();
Parcel nullDest = null;
- assertThrows(
- NullPointerException.class,
- () -> {
- contextualAds.writeToParcel(nullDest, 0);
- });
+ assertThrows(NullPointerException.class, () -> contextualAds.writeToParcel(nullDest, 0));
}
@Test
public void testBuildContextualAdsUnsetBuyerFailure() {
assertThrows(
NullPointerException.class,
- () -> {
- new SignedContextualAds.Builder()
- .setDecisionLogicUri(SignedContextualAdsFixture.DECISION_LOGIC_URI)
- .setAdsWithBid(SignedContextualAdsFixture.ADS_WITH_BID)
- .setSignature(SignedContextualAdsFixture.PLACEHOLDER_SIGNATURE)
- .build();
- });
+ () ->
+ new SignedContextualAds.Builder()
+ .setDecisionLogicUri(SignedContextualAdsFixture.DECISION_LOGIC_URI)
+ .setAdsWithBid(SignedContextualAdsFixture.ADS_WITH_BID)
+ .setSignature(TEST_SIGNATURE)
+ .build());
}
@Test
public void testBuildContextualAdsUnsetDecisionLogicUriFailure() {
assertThrows(
NullPointerException.class,
- () -> {
- new SignedContextualAds.Builder()
- .setBuyer(SignedContextualAdsFixture.BUYER)
- .setAdsWithBid(SignedContextualAdsFixture.ADS_WITH_BID)
- .setSignature(SignedContextualAdsFixture.PLACEHOLDER_SIGNATURE)
- .build();
- });
+ () ->
+ new SignedContextualAds.Builder()
+ .setBuyer(SignedContextualAdsFixture.BUYER)
+ .setAdsWithBid(SignedContextualAdsFixture.ADS_WITH_BID)
+ .setSignature(TEST_SIGNATURE)
+ .build());
}
@Test
public void testBuildContextualAdsUnsetAdWithBidFailure() {
assertThrows(
NullPointerException.class,
- () -> {
- new SignedContextualAds.Builder()
- .setBuyer(SignedContextualAdsFixture.BUYER)
- .setDecisionLogicUri(SignedContextualAdsFixture.DECISION_LOGIC_URI)
- .setSignature(SignedContextualAdsFixture.PLACEHOLDER_SIGNATURE)
- .build();
- });
+ () ->
+ new SignedContextualAds.Builder()
+ .setBuyer(SignedContextualAdsFixture.BUYER)
+ .setDecisionLogicUri(SignedContextualAdsFixture.DECISION_LOGIC_URI)
+ .setSignature(TEST_SIGNATURE)
+ .build());
}
@Test
public void testBuildContextualAdsUnsetSignatureFailure() {
assertThrows(
NullPointerException.class,
- () -> {
- new SignedContextualAds.Builder()
- .setBuyer(SignedContextualAdsFixture.BUYER)
- .setDecisionLogicUri(SignedContextualAdsFixture.DECISION_LOGIC_URI)
- .setAdsWithBid(SignedContextualAdsFixture.ADS_WITH_BID)
- .build();
- });
+ () ->
+ new SignedContextualAds.Builder()
+ .setBuyer(SignedContextualAdsFixture.BUYER)
+ .setDecisionLogicUri(SignedContextualAdsFixture.DECISION_LOGIC_URI)
+ .setAdsWithBid(SignedContextualAdsFixture.ADS_WITH_BID)
+ .build());
}
@Test
public void testContextualAdsDescribeContents() {
- SignedContextualAds obj = SignedContextualAdsFixture.aSignedContextualAd();
+ SignedContextualAds obj = SignedContextualAdsFixture.aSignedContextualAds();
- assertEquals(obj.describeContents(), 0);
+ assertThat(obj.describeContents()).isEqualTo(0);
}
@Test
public void testContextualAdsHaveSameHashCode() {
- SignedContextualAds obj1 = SignedContextualAdsFixture.aSignedContextualAd();
- SignedContextualAds obj2 = SignedContextualAdsFixture.aSignedContextualAd();
+ SignedContextualAds obj1 =
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder().build();
+ SignedContextualAds obj2 =
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder().build();
CommonFixture.assertHaveSameHashCode(obj1, obj2);
}
@Test
public void testContextualAdsHaveDifferentHashCode() {
- SignedContextualAds obj1 = SignedContextualAdsFixture.aSignedContextualAd();
+ SignedContextualAds obj1 = SignedContextualAdsFixture.aSignedContextualAds();
SignedContextualAds obj2 =
- SignedContextualAdsFixture.aSignedContextualAdBuilder()
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder()
.setBuyer(SignedContextualAdsFixture.BUYER_2)
.build();
SignedContextualAds obj3 =
- SignedContextualAdsFixture.aSignedContextualAdBuilder()
- .setSignature(new byte[] {1, 2, 3})
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder()
+ .setAdsWithBid(Collections.singletonList(AD_WITH_BID_1))
.build();
CommonFixture.assertDifferentHashCode(obj1, obj2, obj3);
diff --git a/adservices/tests/unittest/service-core/AndroidManifest.xml b/adservices/tests/unittest/service-core/AndroidManifest.xml
index 44a4d197f..7be4ea18e 100644
--- a/adservices/tests/unittest/service-core/AndroidManifest.xml
+++ b/adservices/tests/unittest/service-core/AndroidManifest.xml
@@ -24,7 +24,6 @@
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_AD_ID" />
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_TOPICS" />
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_CUSTOM_AUDIENCE" />
- <uses-permission android:name="android.permission.ACCESS_ADSERVICES_PROTECTED_SIGNALS" />
<!-- Needed to resolve Intent to ComponentName for measurement verifiedDestination -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
diff --git a/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchConsentWorkerTest.java b/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchConsentWorkerTest.java
index e7344abe1..2bf1221c7 100644
--- a/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchConsentWorkerTest.java
+++ b/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchConsentWorkerTest.java
@@ -64,6 +64,8 @@ import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.FluentFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Before;
import org.junit.Test;
@@ -73,6 +75,9 @@ import org.mockito.Mockito;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
@SpyStatic(FlagsFactory.class)
@RequiresSdkLevelAtLeastS
@@ -87,6 +92,8 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
private static final Topic TOPIC1 = Topic.create(0, 1, 11);
private static final Topic TOPIC2 = Topic.create(12, 2, 22);
private static final Topic TOPIC3 = Topic.create(123, 3, 33);
+ private static final int APPSEARCH_WRITE_TIMEOUT_MS = 1000;
+
private final List<Topic> mTopics = Arrays.asList(TOPIC1, TOPIC2, TOPIC3);
@Mock private Flags mMockFlags;
@@ -97,6 +104,8 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
when(mMockFlags.getAdservicesApkShaCertificate())
.thenReturn(Flags.ADSERVICES_APK_SHA_CERTIFICATE);
when(mMockFlags.getAppsearchWriterAllowListOverride()).thenReturn("");
+ // Reduce AppSearch write timeout to speed up the tests.
+ when(mMockFlags.getAppSearchWriteTimeout()).thenReturn(APPSEARCH_WRITE_TIMEOUT_MS);
}
@Test
@@ -144,6 +153,21 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@Test
@SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void testSetConsent_failure_timeout() {
+ initTimeoutResponse();
+
+ RuntimeException e =
+ assertThrows(
+ RuntimeException.class,
+ () -> AppSearchConsentWorker.getInstance().setConsent(API_TYPE, CONSENTED));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
+ @SpyStatic(PlatformStorage.class)
@MockStatic(UserHandle.class)
public void testSetConsent() {
initSuccessResponse();
@@ -285,6 +309,8 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
RuntimeException.class,
() -> appSearchConsentWorker.clearAppsWithConsent(TEST));
assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(ExecutionException.class);
}
@Test
@@ -408,6 +434,8 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
RuntimeException.class,
() -> appSearchConsentWorker.removeAppWithConsent(consentType, TEST));
assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(ExecutionException.class);
}
@Test
@@ -488,7 +516,7 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@Test
@SpyStatic(PlatformStorage.class)
- public void testRecordGaUxNotificationDisplayed_faiure() {
+ public void testRecordGaUxNotificationDisplayed_failure() {
runRecordNotificationDisplayedTestFailure(/* isBetaUx= */ false);
}
@@ -511,6 +539,41 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
}
@Test
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void testRecordNotificationDisplayed_failure_timeout() {
+ runRecordNotificationDisplayedTestFailureTimeout(/* isBetaUx= */ true);
+ }
+
+ @Test
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void testRecordGaUxNotificationDisplayed_failure_timeout() {
+ runRecordNotificationDisplayedTestFailureTimeout(/* isBetaUx= */ false);
+ }
+
+ private void runRecordNotificationDisplayedTestFailureTimeout(boolean isBetaUx) {
+ initTimeoutResponse();
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+
+ RuntimeException e;
+ if (isBetaUx) {
+ e =
+ assertThrows(
+ RuntimeException.class, () -> worker.recordNotificationDisplayed(true));
+ } else {
+ e =
+ assertThrows(
+ RuntimeException.class,
+ () -> worker.recordGaUxNotificationDisplayed(true));
+ }
+
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
@MockStatic(AppSearchNotificationDao.class)
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
@@ -574,6 +637,24 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@Test
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
+ public void testSetCurrentPrivacySandboxFeature_failure_timeout() {
+ initTimeoutResponse();
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e =
+ assertThrows(
+ RuntimeException.class,
+ () ->
+ worker.setCurrentPrivacySandboxFeature(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_RECONSENT));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
public void testSetCurrentPrivacySandboxFeature() {
initSuccessResponse();
@@ -616,6 +697,27 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@MockStatic(AppSearchInteractionsDao.class)
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
+ public void testRecordUserManualInteractionWithConsent_failure_timeout() {
+ initTimeoutResponse();
+
+ when(AppSearchInteractionsDao.getRowId(any(), any())).thenReturn("" + UID);
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ int interactions = ConsentManager.MANUAL_INTERACTIONS_RECORDED;
+
+ RuntimeException e =
+ assertThrows(
+ RuntimeException.class,
+ () -> worker.recordUserManualInteractionWithConsent(interactions));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
+ @MockStatic(AppSearchInteractionsDao.class)
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
public void testRecordUserManualInteractionWithConsent() {
initSuccessResponse();
@@ -638,7 +740,7 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@Test
@SpyStatic(PlatformStorage.class)
- public void testRecordBlockedTopics_failure() {
+ public void testRecordBlockedTopic_failure() {
initFailureResponse();
AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
@@ -651,7 +753,27 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@MockStatic(AppSearchTopicsConsentDao.class)
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
- public void testRecordBlockedTopics_new() {
+ public void testRecordBlockedTopic_failure_timeout() {
+ initTimeoutResponse();
+
+ String query = "" + UID;
+ ExtendedMockito.doReturn(query).when(() -> AppSearchTopicsConsentDao.getQuery(any()));
+ ExtendedMockito.doReturn(null)
+ .when(() -> AppSearchTopicsConsentDao.readConsentData(any(), any(), any(), any()));
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e =
+ assertThrows(RuntimeException.class, () -> worker.recordBlockedTopic(TOPIC1));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
+ @MockStatic(AppSearchTopicsConsentDao.class)
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void testRecordBlockedTopic_new() {
initSuccessResponse();
String query = "" + UID;
@@ -667,7 +789,7 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@MockStatic(AppSearchTopicsConsentDao.class)
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
- public void testRecordBlockedTopics() throws Exception {
+ public void testRecordBlockedTopic() {
String query = "" + UID;
ExtendedMockito.doReturn(query).when(() -> AppSearchTopicsConsentDao.getQuery(any()));
AppSearchTopicsConsentDao dao = Mockito.mock(AppSearchTopicsConsentDao.class);
@@ -686,7 +808,7 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@Test
@MockStatic(AppSearchTopicsConsentDao.class)
@SpyStatic(PlatformStorage.class)
- public void testRecordUnblockedTopics_failure() throws Exception {
+ public void testRecordUnblockedTopic_failure() throws Exception {
AppSearchTopicsConsentDao dao = Mockito.mock(AppSearchTopicsConsentDao.class);
ExtendedMockito.doReturn(dao)
.when(() -> AppSearchTopicsConsentDao.readConsentData(any(), any(), any(), any()));
@@ -702,13 +824,21 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
verify(dao).removeBlockedTopic(TOPIC1);
verify(dao).writeData(any(), any(), any());
assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+
+ Throwable cause = e.getCause();
+ assertThat(cause).isNotNull();
+ assertThat(cause).isInstanceOf(ExecutionException.class);
+
+ Throwable rootCause = cause.getCause();
+ assertThat(rootCause).isNotNull();
+ assertThat(rootCause).isInstanceOf(InterruptedException.class);
}
@Test
@MockStatic(AppSearchTopicsConsentDao.class)
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
- public void testRecordUnblockedTopics_new() {
+ public void testRecordUnblockedTopic_new() {
String query = "" + UID;
ExtendedMockito.doReturn(query).when(() -> AppSearchTopicsConsentDao.getQuery(any()));
ExtendedMockito.doReturn(null)
@@ -722,7 +852,7 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@MockStatic(AppSearchTopicsConsentDao.class)
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
- public void testRecordUnblockedTopics() {
+ public void testRecordUnblockedTopic() {
String query = "" + UID;
ExtendedMockito.doReturn(query).when(() -> AppSearchTopicsConsentDao.getQuery(any()));
AppSearchTopicsConsentDao dao = Mockito.mock(AppSearchTopicsConsentDao.class);
@@ -753,6 +883,20 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@Test
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
+ public void testClearBlockedTopics_failure_timeout() {
+ initTimeoutResponse();
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e =
+ assertThrows(RuntimeException.class, () -> worker.clearBlockedTopics());
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
public void testClearBlockedTopics() {
initSuccessResponse();
@@ -781,6 +925,26 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
when(mockResponse.getMigrationFailures()).thenReturn(List.of());
}
+ private void initTimeoutResponse() {
+ AppSearchSession mockSession = Mockito.mock(AppSearchSession.class);
+ UserHandle mockUserHandle = Mockito.mock(UserHandle.class);
+ Mockito.when(UserHandle.getUserHandleForUid(Binder.getCallingUid()))
+ .thenReturn(mockUserHandle);
+ Mockito.when(mockUserHandle.getIdentifier()).thenReturn(UID);
+ ExtendedMockito.doReturn(Futures.immediateFuture(mockSession))
+ .when(() -> PlatformStorage.createSearchSessionAsync(any()));
+ verify(mockSession, atMost(1)).setSchemaAsync(any(SetSchemaRequest.class));
+
+ SetSchemaResponse mockResponse = Mockito.mock(SetSchemaResponse.class);
+ when(mockSession.setSchemaAsync(any(SetSchemaRequest.class)))
+ .thenReturn(Futures.immediateFuture(mockResponse));
+ AppSearchBatchResult<String, Void> result = Mockito.mock(AppSearchBatchResult.class);
+ when(mockSession.putAsync(any())).thenReturn(getLongRunningOperation(result));
+
+ verify(mockResponse, atMost(1)).getMigrationFailures();
+ when(mockResponse.getMigrationFailures()).thenReturn(List.of());
+ }
+
private void initFailureResponse() {
AppSearchSession mockSession = Mockito.mock(AppSearchSession.class);
ExtendedMockito.doReturn(Futures.immediateFuture(mockSession))
@@ -801,6 +965,17 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
when(mockResponse.getMigrationFailures()).thenReturn(List.of(failure));
}
+ private <T> ListenableFuture<T> getLongRunningOperation(T result) {
+ // Wait for a time that's longer than the AppSearch write timeout, then return the result.
+ ListeningExecutorService ls =
+ MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
+ return ls.submit(
+ () -> {
+ TimeUnit.MILLISECONDS.sleep(APPSEARCH_WRITE_TIMEOUT_MS + 500);
+ return result;
+ });
+ }
+
@Test
@SpyStatic(AppSearchUxStatesDao.class)
public void isAdIdEnabledTest_trueBit() {
@@ -826,8 +1001,6 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
public void setAdIdEnabledTest_success() {
- initSuccessResponse();
-
String query = "" + UID;
ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
AppSearchUxStatesDao dao = Mockito.mock(AppSearchUxStatesDao.class);
@@ -845,17 +1018,17 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@Test
@SpyStatic(PlatformStorage.class)
- public void setAdIdEnabledTest_trueBit() {
- setAdIdEnabledTest(true);
+ public void setAdIdEnabledTest_failure_trueBit() {
+ setAdIdEnabledTestFailure(true);
}
@Test
@SpyStatic(PlatformStorage.class)
- public void setAdIdEnabledTest_falseBit() {
- setAdIdEnabledTest(false);
+ public void setAdIdEnabledTest_failure_falseBit() {
+ setAdIdEnabledTestFailure(false);
}
- private void setAdIdEnabledTest(boolean isAdIdEnabled) {
+ private void setAdIdEnabledTestFailure(boolean isAdIdEnabled) {
initFailureResponse();
AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
@@ -865,6 +1038,27 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
}
@Test
+ @MockStatic(AppSearchUxStatesDao.class)
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void setAdIdEnabledTest_timeout() {
+ String query = "" + UID;
+ ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
+ AppSearchUxStatesDao dao = Mockito.mock(AppSearchUxStatesDao.class);
+ ExtendedMockito.doReturn(dao)
+ .when(() -> AppSearchUxStatesDao.readData(any(), any(), any(), any()));
+ when(dao.writeData(any(), any(), any()))
+ .thenReturn(FluentFuture.from(getLongRunningOperation(null)));
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e =
+ assertThrows(RuntimeException.class, () -> worker.setAdIdEnabled(true));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
@SpyStatic(AppSearchUxStatesDao.class)
public void isU18AccountTest_trueBit() {
isU18AccountTest(true);
@@ -889,8 +1083,6 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
public void setU18AccountTest_success() {
- initSuccessResponse();
-
String query = "" + UID;
ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
AppSearchUxStatesDao dao = Mockito.mock(AppSearchUxStatesDao.class);
@@ -928,6 +1120,28 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
}
@Test
+ @MockStatic(AppSearchUxStatesDao.class)
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void setU18AccountTest_timeout() {
+ String query = "" + UID;
+ ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
+ AppSearchUxStatesDao dao = Mockito.mock(AppSearchUxStatesDao.class);
+ ExtendedMockito.doReturn(dao)
+ .when(() -> AppSearchUxStatesDao.readData(any(), any(), any(), any()));
+ AppSearchBatchResult<String, Void> result = Mockito.mock(AppSearchBatchResult.class);
+ when(dao.writeData(any(), any(), any()))
+ .thenReturn(FluentFuture.from(getLongRunningOperation(result)));
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e =
+ assertThrows(RuntimeException.class, () -> worker.setU18Account(false));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
@SpyStatic(AppSearchUxStatesDao.class)
public void isEntryPointEnabledTest_trueBit() {
isEntryPointEnabledTest(true);
@@ -996,6 +1210,30 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
}
@Test
+ @MockStatic(AppSearchUxStatesDao.class)
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void setEntryPointEnabledTest_timeout() {
+ initSuccessResponse();
+
+ String query = "" + UID;
+ ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
+ AppSearchUxStatesDao dao = Mockito.mock(AppSearchUxStatesDao.class);
+ ExtendedMockito.doReturn(dao)
+ .when(() -> AppSearchUxStatesDao.readData(any(), any(), any(), any()));
+ AppSearchBatchResult<String, Void> result = Mockito.mock(AppSearchBatchResult.class);
+ when(dao.writeData(any(), any(), any()))
+ .thenReturn(FluentFuture.from(getLongRunningOperation(result)));
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e =
+ assertThrows(RuntimeException.class, () -> worker.setEntryPointEnabled(true));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
@SpyStatic(AppSearchUxStatesDao.class)
public void isAdultAccountTest_trueBit() {
isAdultAccountTest(true);
@@ -1040,7 +1278,7 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@MockStatic(AppSearchUxStatesDao.class)
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
- public void setU18AdultAccountTest_success() {
+ public void setAdultAccountTest_success() {
initSuccessResponse();
String query = "" + UID;
@@ -1059,6 +1297,30 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
}
@Test
+ @MockStatic(AppSearchUxStatesDao.class)
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void setAdultAccountTest_timeout() {
+ initSuccessResponse();
+
+ String query = "" + UID;
+ ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
+ AppSearchUxStatesDao dao = Mockito.mock(AppSearchUxStatesDao.class);
+ ExtendedMockito.doReturn(dao)
+ .when(() -> AppSearchUxStatesDao.readData(any(), any(), any(), any()));
+ AppSearchBatchResult<String, Void> result = Mockito.mock(AppSearchBatchResult.class);
+ when(dao.writeData(any(), any(), any()))
+ .thenReturn(FluentFuture.from(getLongRunningOperation(result)));
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e =
+ assertThrows(RuntimeException.class, () -> worker.setAdultAccount(true));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
@SpyStatic(AppSearchUxStatesDao.class)
public void wasU18NotificationDisplayedTest_trueBit() {
wasU18NotificationDisplayedTest(true);
@@ -1128,6 +1390,31 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
}
@Test
+ @MockStatic(AppSearchUxStatesDao.class)
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void setU18NotificationDisplayedTest_timeout() {
+ initSuccessResponse();
+
+ String query = "" + UID;
+ ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
+ AppSearchUxStatesDao dao = Mockito.mock(AppSearchUxStatesDao.class);
+ ExtendedMockito.doReturn(dao)
+ .when(() -> AppSearchUxStatesDao.readData(any(), any(), any(), any()));
+ AppSearchBatchResult<String, Void> result = Mockito.mock(AppSearchBatchResult.class);
+ when(dao.writeData(any(), any(), any()))
+ .thenReturn(FluentFuture.from(getLongRunningOperation(result)));
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e =
+ assertThrows(
+ RuntimeException.class, () -> worker.setU18NotificationDisplayed(true));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+
+ @Test
@SpyStatic(AppSearchUxStatesDao.class)
public void getUxTest_allUxs() {
for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
@@ -1155,8 +1442,6 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
public void setUxTest_allUxsSuccess() {
- initSuccessResponse();
-
for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
String query = "" + UID;
ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
@@ -1175,6 +1460,29 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
}
@Test
+ @MockStatic(AppSearchUxStatesDao.class)
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void setUxTest_allUxs_timeout() {
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ String query = "" + UID;
+ ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
+ AppSearchUxStatesDao dao = Mockito.mock(AppSearchUxStatesDao.class);
+ ExtendedMockito.doReturn(dao)
+ .when(() -> AppSearchUxStatesDao.readData(any(), any(), any(), any()));
+ AppSearchBatchResult<String, Void> result = Mockito.mock(AppSearchBatchResult.class);
+ when(dao.writeData(any(), any(), any()))
+ .thenReturn(FluentFuture.from(getLongRunningOperation(result)));
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e = assertThrows(RuntimeException.class, () -> worker.setUx(ux));
+ assertThat(e.getMessage()).isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+ }
+
+ @Test
@SpyStatic(AppSearchUxStatesDao.class)
public void getEnrollmentChannelTest_allUxsAllEnrollmentChannels() {
for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
@@ -1217,8 +1525,6 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
@SpyStatic(PlatformStorage.class)
@SpyStatic(UserHandle.class)
public void setEnrollmentChannelTest_allUxsAllEnrollmentChannelsSuccess() {
- initSuccessResponse();
-
for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
for (PrivacySandboxEnrollmentChannelCollection channel :
ux.getEnrollmentChannelCollection()) {
@@ -1240,4 +1546,35 @@ public final class AppSearchConsentWorkerTest extends AdServicesExtendedMockitoT
}
}
}
+
+ @Test
+ @MockStatic(AppSearchUxStatesDao.class)
+ @SpyStatic(PlatformStorage.class)
+ @SpyStatic(UserHandle.class)
+ public void setEnrollmentChannelTest_allUxsAllEnrollmentChannels_timeout() {
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ for (PrivacySandboxEnrollmentChannelCollection channel :
+ ux.getEnrollmentChannelCollection()) {
+ String query = "" + UID;
+ ExtendedMockito.doReturn(query).when(() -> AppSearchUxStatesDao.getQuery(any()));
+ AppSearchUxStatesDao dao = Mockito.mock(AppSearchUxStatesDao.class);
+ ExtendedMockito.doReturn(dao)
+ .when(() -> AppSearchUxStatesDao.readData(any(), any(), any(), any()));
+ AppSearchBatchResult<String, Void> result =
+ Mockito.mock(AppSearchBatchResult.class);
+ when(dao.writeData(any(), any(), any()))
+ .thenReturn(FluentFuture.from(getLongRunningOperation(result)));
+
+ AppSearchConsentWorker worker = AppSearchConsentWorker.getInstance();
+ RuntimeException e =
+ assertThrows(
+ RuntimeException.class,
+ () -> worker.setEnrollmentChannel(ux, channel));
+ assertThat(e.getMessage())
+ .isEqualTo(ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ assertThat(e.getCause()).isNotNull();
+ assertThat(e.getCause()).isInstanceOf(TimeoutException.class);
+ }
+ }
+ }
}
diff --git a/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchDaoTest.java b/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchDaoTest.java
index 47bc18645..116891316 100644
--- a/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchDaoTest.java
+++ b/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchDaoTest.java
@@ -52,6 +52,8 @@ import com.android.adservices.service.consent.ConsentConstants;
import com.google.common.util.concurrent.FluentFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Before;
import org.junit.Rule;
@@ -63,6 +65,8 @@ import org.mockito.MockitoAnnotations;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
@SmallTest
public class AppSearchDaoTest {
@@ -87,6 +91,8 @@ public class AppSearchDaoTest {
new PackageIdentifier(
/* packageName= */ TEST, /* sha256= */ new Signature(SHA).toByteArray());
+ private static final int APPSEARCH_READ_TIMEOUT_MS = 500;
+
@Rule
public final AdServicesExtendedMockitoRule adServicesExtendedMockitoRule =
new AdServicesExtendedMockitoRule.Builder(this).mockStatic(FlagsFactory.class).build();
@@ -95,6 +101,7 @@ public class AppSearchDaoTest {
public void before() {
MockitoAnnotations.initMocks(this);
when(mFlags.getAppsearchWriterAllowListOverride()).thenReturn("");
+ when(mFlags.getAppSearchReadTimeout()).thenReturn(APPSEARCH_READ_TIMEOUT_MS);
doReturn(mFlags).when(FlagsFactory::getFlags);
}
@@ -205,6 +212,30 @@ public class AppSearchDaoTest {
}
@Test
+ public void testReadConsentData_timeout() {
+ AppSearchDao result =
+ AppSearchDao.readConsentData(
+ AppSearchConsentDao.class,
+ getLongRunningOperation(mGlobalSearchSession),
+ mExecutor,
+ NAMESPACE,
+ TEST,
+ mAdServicesPackageName);
+ assertThat(result).isNull();
+ }
+
+ private <T> ListenableFuture<T> getLongRunningOperation(T result) {
+ // Wait for a time that's longer than the AppSearch read timeout, then return the result.
+ ListeningExecutorService ls =
+ MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
+ return ls.submit(
+ () -> {
+ TimeUnit.MILLISECONDS.sleep(APPSEARCH_READ_TIMEOUT_MS + 500);
+ return result;
+ });
+ }
+
+ @Test
public void testReadAppSearchData_emptyQuery() {
AppSearchDao dao =
AppSearchDao.readAppSearchSessionData(
@@ -262,7 +293,8 @@ public class AppSearchDaoTest {
when(mockSession.setSchemaAsync(any(SetSchemaRequest.class)))
.thenReturn(Futures.immediateFuture(mockResponse));
- AppSearchResult mockResult = Mockito.mock(AppSearchResult.class);
+ AppSearchResult<Void> mockResult =
+ AppSearchResult.newFailedResult(AppSearchResult.RESULT_INVALID_ARGUMENT, "test");
SetSchemaResponse.MigrationFailure failure =
new SetSchemaResponse.MigrationFailure(
/* namespace= */ TEST,
@@ -278,11 +310,12 @@ public class AppSearchDaoTest {
Futures.immediateFuture(mockSession),
List.of(PACKAGE_IDENTIFIER),
mExecutor);
- ExecutionException e = assertThrows(ExecutionException.class, () -> result.get());
+ ExecutionException e = assertThrows(ExecutionException.class, result::get);
assertThat(e.getMessage())
.isEqualTo(
"java.lang.RuntimeException: "
- + ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE);
+ + ConsentConstants.ERROR_MESSAGE_APPSEARCH_FAILURE
+ + " Migration failure: [FAILURE(3)]: test");
}
@Test
@@ -337,7 +370,7 @@ public class AppSearchDaoTest {
mExecutor,
TEST,
NAMESPACE);
- ExecutionException e = assertThrows(ExecutionException.class, () -> result.get());
+ ExecutionException e = assertThrows(ExecutionException.class, result::get);
assertThat(e.getMessage())
.isEqualTo(
"java.lang.RuntimeException: "
diff --git a/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorkerTest.java b/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorkerTest.java
index 0765ba527..638ee6714 100644
--- a/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorkerTest.java
+++ b/adservices/tests/unittest/service-core/appsearch/src/com/android/adservices/service/appsearch/AppSearchMeasurementRollbackWorkerTest.java
@@ -41,6 +41,8 @@ import androidx.test.filters.SmallTest;
import com.android.adservices.concurrency.AdServicesExecutors;
import com.android.adservices.mockito.AdServicesExtendedMockitoRule;
+import com.android.adservices.service.Flags;
+import com.android.adservices.service.FlagsFactory;
import com.android.adservices.service.common.compat.FileCompatUtils;
import com.android.adservices.service.consent.ConsentConstants;
@@ -66,7 +68,7 @@ public class AppSearchMeasurementRollbackWorkerTest {
FileCompatUtils.getAdservicesFilename("measurement_rollback");
private static final String USERID = "user1";
private static final long APEX_VERSION = 100L;
- private static final int FUTURE_TIMEOUT_MILLISECONDS = 3000;
+ private static final int APPSEARCH_WRITE_TIMEOUT_MS = 1000;
private final Context mContext = ApplicationProvider.getApplicationContext();
private final String mAdServicesPackageName =
@@ -74,17 +76,22 @@ public class AppSearchMeasurementRollbackWorkerTest {
private final Executor mExecutor = AdServicesExecutors.getBackgroundExecutor();
private AppSearchMeasurementRollbackWorker mWorker;
@Mock private ListenableFuture<AppSearchSession> mAppSearchSession;
+ @Mock private Flags mMockFlags;
@Rule
public final AdServicesExtendedMockitoRule adServicesExtendedMockitoRule =
new AdServicesExtendedMockitoRule.Builder(this)
.mockStatic(PlatformStorage.class)
.mockStatic(AppSearchDao.class)
+ .mockStatic(FlagsFactory.class)
.setStrictness(Strictness.LENIENT)
.build();
@Before
public void setup() {
+ doReturn(mMockFlags).when(FlagsFactory::getFlags);
+ doReturn(APPSEARCH_WRITE_TIMEOUT_MS).when(mMockFlags).getAppSearchWriteTimeout();
+
ArgumentCaptor<PlatformStorage.SearchContext> cap =
ArgumentCaptor.forClass(PlatformStorage.SearchContext.class);
doReturn(mAppSearchSession)
@@ -107,7 +114,7 @@ public class AppSearchMeasurementRollbackWorkerTest {
@SuppressWarnings("FutureReturnValueIgnored")
@Test
public void testClearAdServicesDeletionOccurred() {
- FluentFuture mockResult =
+ FluentFuture<AppSearchBatchResult<String, Void>> mockResult =
FluentFuture.from(
Futures.immediateFuture(
new AppSearchBatchResult.Builder<String, Void>().build()));
@@ -128,13 +135,14 @@ public class AppSearchMeasurementRollbackWorkerTest {
@Test
public void testClearAdServicesDeletionOccurred_throwsChecked() {
- Callable<Void> callable =
+ Callable<AppSearchBatchResult<String, Void>> callable =
() -> {
- TimeUnit.MILLISECONDS.sleep(FUTURE_TIMEOUT_MILLISECONDS);
+ TimeUnit.MILLISECONDS.sleep(APPSEARCH_WRITE_TIMEOUT_MS + 500);
return null;
};
- FluentFuture mockResult = FluentFuture.from(Futures.submit(callable, mExecutor));
+ FluentFuture<AppSearchBatchResult<String, Void>> mockResult =
+ FluentFuture.from(Futures.submit(callable, mExecutor));
doReturn(mockResult).when(() -> AppSearchDao.deleteData(any(), any(), any(), any(), any()));
RuntimeException e =
@@ -234,17 +242,17 @@ public class AppSearchMeasurementRollbackWorkerTest {
@Test
public void testRecordAdServicesDeletionOccurred_throwsChecked() {
- // The manager class waits for 2 seconds on the future.get() call before timing out. So
- // creating a future that takes longer than 2 sec to resolve, in order to create a
+ // The manager class waits for a few seconds on the future.get() call before timing out. So
+ // creating a future that takes longer than the timeout to resolve, in order to create a
// TimeoutException.
- Callable<Void> callable =
+ Callable<AppSearchBatchResult<String, Void>> callable =
() -> {
- TimeUnit.MILLISECONDS.sleep(FUTURE_TIMEOUT_MILLISECONDS);
+ TimeUnit.MILLISECONDS.sleep(APPSEARCH_WRITE_TIMEOUT_MS + 500);
return null;
};
- ListenableFuture<Void> future = Futures.submit(callable, mExecutor);
- FluentFuture mockFuture = FluentFuture.from(future);
+ FluentFuture<AppSearchBatchResult<String, Void>> mockFuture =
+ FluentFuture.from(Futures.submit(callable, mExecutor));
AppSearchMeasurementRollbackDao dao = mock(AppSearchMeasurementRollbackDao.class);
doReturn(mockFuture).when(dao).writeData(any(), any(), any());
diff --git a/adservices/tests/unittest/service-core/assets/attribution_service_test.json b/adservices/tests/unittest/service-core/assets/attribution_service_test.json
index 223e9cbf9..7612332a2 100644
--- a/adservices/tests/unittest/service-core/assets/attribution_service_test.json
+++ b/adservices/tests/unittest/service-core/assets/attribution_service_test.json
@@ -102,7 +102,7 @@
"reportTime": 8730000001,
"triggerPriority": 101,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T1"
}],
@@ -244,7 +244,7 @@
"reportTime": 8730000001,
"triggerPriority": 101,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T1"
}],
@@ -423,7 +423,7 @@
"reportTime": 8730000001,
"triggerPriority": 101,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T1"
},
@@ -438,7 +438,7 @@
"reportTime": 8730000001,
"triggerPriority": 101,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T2"
}
@@ -805,7 +805,7 @@
"triggerPriority": 101,
"status": 0,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S2",
"triggerId": "T1"
}],
@@ -965,7 +965,7 @@
"triggerPriority": 101,
"status": 0,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S2",
"triggerId": "T1"
}],
@@ -1883,7 +1883,7 @@
"reportTime": 8730000001,
"triggerPriority": 101,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T1"
}],
@@ -2580,7 +2580,7 @@
"reportTime": 8730000001,
"triggerPriority": 102,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T2"
},
@@ -2595,7 +2595,7 @@
"reportTime": 8730000001,
"triggerPriority": 103,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T3"
},
@@ -2610,7 +2610,7 @@
"reportTime": 8730000001,
"triggerPriority": 104,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T4"
}
@@ -2875,7 +2875,7 @@
"reportTime": 8730000001,
"triggerPriority": 101,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T1"
},
@@ -2890,7 +2890,7 @@
"reportTime": 8730000001,
"triggerPriority": 101,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T2"
},
@@ -2905,7 +2905,7 @@
"reportTime": 8730000001,
"triggerPriority": 102,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T4"
}
@@ -3765,7 +3765,7 @@
"reportTime": 8643600030,
"triggerPriority": 0,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T2"
}
@@ -3928,7 +3928,7 @@
"reportTime": 8643600030,
"triggerPriority": 0,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0024263,
+ "randomizedTriggerRate": 0.0001372,
"sourceId": "S1",
"triggerId": "T2"
}
@@ -5052,7 +5052,7 @@
"reportTime": 8730000001,
"triggerPriority": 101,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0170218,
+ "randomizedTriggerRate": 0.0008051,
"sourceId": "S1",
"triggerId": "T1"
}],
@@ -5401,7 +5401,7 @@
"reportTime": 8730000002,
"triggerPriority": 101,
"sourceType": "navigation",
- "randomizedTriggerRate": 0.0170218,
+ "randomizedTriggerRate": 0.0008051,
"sourceId": "S1",
"triggerId": "T1"
}],
diff --git a/adservices/tests/unittest/service-core/assets/measurement_app_uninstall_deletion_test.json b/adservices/tests/unittest/service-core/assets/measurement_app_uninstall_deletion_test.json
index c9e8a4f5e..ce426c9dd 100644
--- a/adservices/tests/unittest/service-core/assets/measurement_app_uninstall_deletion_test.json
+++ b/adservices/tests/unittest/service-core/assets/measurement_app_uninstall_deletion_test.json
@@ -784,7 +784,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.test",
"webDestination": "https://foo.test",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2-REMOVE",
@@ -801,7 +802,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.test",
"webDestination": "https://foo.test",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -822,7 +824,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.test",
"webDestination": "https://foo.test",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -1192,7 +1195,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -1209,7 +1213,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -1365,7 +1370,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -1382,7 +1388,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/measurement_delete_expired_test.json b/adservices/tests/unittest/service-core/assets/measurement_delete_expired_test.json
index b835aeda9..95bbb6199 100644
--- a/adservices/tests/unittest/service-core/assets/measurement_delete_expired_test.json
+++ b/adservices/tests/unittest/service-core/assets/measurement_delete_expired_test.json
@@ -296,7 +296,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -313,7 +314,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR3",
@@ -330,7 +332,8 @@
"retryCount": 5,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR4",
@@ -347,7 +350,8 @@
"retryCount": 5,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -374,7 +378,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/flex_api_with_no_origin_multiple_domain.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/flex_api_with_no_origin_multiple_domain.json
index 28000d86a..d11dc5443 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/flex_api_with_no_origin_multiple_domain.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/flex_api_with_no_origin_multiple_domain.json
@@ -332,7 +332,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -349,7 +350,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -420,7 +422,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/registrant_not_found.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/registrant_not_found.json
index c5e9d4b56..0ee22ebf7 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/registrant_not_found.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/registrant_not_found.json
@@ -143,7 +143,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -160,7 +161,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -307,7 +309,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -324,7 +327,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain.json
index c9b7e17e1..5e63f9e8d 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain.json
@@ -312,7 +312,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -329,7 +330,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -488,7 +490,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain_preserve.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain_preserve.json
index 533129bd5..008c0aa91 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain_preserve.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_multiple_origin_no_domain_preserve.json
@@ -325,7 +325,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -342,7 +343,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -580,7 +582,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain.json
index abd601f82..d99396781 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain.json
@@ -325,7 +325,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -342,7 +343,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -500,7 +502,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain_preserve.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain_preserve.json
index 802e38319..160e84813 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain_preserve.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_multiple_domain_preserve.json
@@ -339,7 +339,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -356,7 +357,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -595,7 +597,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_nor_range.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_nor_range.json
index 5ed787715..58f75087d 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_nor_range.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_no_origin_nor_range.json
@@ -152,7 +152,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -169,7 +170,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -324,7 +326,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -341,7 +344,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_origin_but_no_range.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_origin_but_no_range.json
index 0528d34e8..e6137bd08 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_origin_but_no_range.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_origin_but_no_range.json
@@ -178,7 +178,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -195,7 +196,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -288,7 +290,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_but_no_origin.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_but_no_origin.json
index 2f08f9ea8..0abc4ceb0 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_but_no_origin.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_but_no_origin.json
@@ -170,7 +170,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -187,7 +188,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -360,7 +362,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -377,7 +380,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_and_origin.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_and_origin.json
index 74b7ca85a..0994666c4 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_and_origin.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_and_origin.json
@@ -247,7 +247,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -264,7 +265,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -423,7 +425,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_no_origin.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_no_origin.json
index 6aa23b053..b7f45c81c 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_no_origin.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_ending_edge_no_origin.json
@@ -170,7 +170,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -187,7 +188,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -360,7 +362,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -377,7 +380,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_and_origin.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_and_origin.json
index bf15f2fe8..ec5354205 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_and_origin.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_and_origin.json
@@ -234,7 +234,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -251,7 +252,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -397,7 +399,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_no_origin.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_no_origin.json
index 96e63cfaf..4f0528007 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_no_origin.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_range_on_starting_edge_no_origin.json
@@ -170,7 +170,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -187,7 +188,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -360,7 +362,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -377,7 +380,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_and_origin.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_and_origin.json
index 540f8cefd..4ff46fea4 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_and_origin.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_and_origin.json
@@ -234,7 +234,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -251,7 +252,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -397,7 +399,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_no_origin_preserve.json b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_no_origin_preserve.json
index 0a4c0a369..e0775912c 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_no_origin_preserve.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_browser_deletion_tests/with_start_equals_end_no_origin_preserve.json
@@ -169,7 +169,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
},
{
"registrationId": "AR2",
@@ -186,7 +187,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
@@ -281,7 +283,8 @@
"retryCount": 1,
"verifiedDestination": "https://foo.com",
"webDestination": "https://foo.com",
- "sourceType": 1
+ "sourceType": 1,
+ "redirectBehavior": "AS_IS"
}
]
},
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_debug_source_storage_limit.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_debug_source_storage_limit.json
index ff052bee4..b38a24723 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_debug_source_storage_limit.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_debug_source_storage_limit.json
@@ -153,7 +153,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key": "347982378",
"trigger_debug_key": "147982378"
}
@@ -181,7 +181,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key": "347982378",
"trigger_debug_key": "147982378"
}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_large_keys.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_large_keys.json
index 167693041..c7bae560b 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_large_keys.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_large_keys.json
@@ -103,7 +103,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_many_trigger_data.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_many_trigger_data.json
index 7210704bb..5fad10144 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_many_trigger_data.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_many_trigger_data.json
@@ -121,7 +121,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_over_contributions_limit.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_over_contributions_limit.json
index c5e8b3cad..20f7179f3 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_over_contributions_limit.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_over_contributions_limit.json
@@ -160,7 +160,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -172,7 +172,7 @@
"source_event_id": "1",
"trigger_data": "3",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_three_of_three_entries.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_three_of_three_entries.json
index f228340d0..bc5b4d132 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_three_of_three_entries.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_three_of_three_entries.json
@@ -105,7 +105,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions.json
index 985a338ed..54739775a 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions.json
@@ -103,7 +103,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api.json
index 11df48af0..c619387a7 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api.json
@@ -107,7 +107,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key" : "347982378",
"trigger_debug_key" : "8971346783"
}
@@ -135,7 +135,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key" : "347982378",
"trigger_debug_key" : "8971346783"
}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_source.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_source.json
index 13cbac1a2..bfd9f49a5 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_source.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_source.json
@@ -106,7 +106,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key" : "347982378"
}
}],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_trigger.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_trigger.json
index 2d394041f..77e5f09e9 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_trigger.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_debug_api_trigger.json
@@ -106,7 +106,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"trigger_debug_key" : "8971346783"
}
}],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api.json
index a2e78e209..6c4c776b2 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api.json
@@ -107,7 +107,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_source.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_source.json
index 9f0ad2801..8bd9dd685 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_source.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_source.json
@@ -106,7 +106,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_trigger.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_trigger.json
index 7cae580ac..83516309f 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_trigger.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_no_adid_debug_api_trigger.json
@@ -106,7 +106,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_null_reports.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_null_reports.json
index ba0fae5d7..5b551ae95 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_null_reports.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/aggregatable/aggregatable_two_contributions_null_reports.json
@@ -107,7 +107,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_3_conversions.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_3_conversions.json
index 5e1ff2b5c..b8d9fe1ab 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_3_conversions.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_3_conversions.json
@@ -1,7 +1,6 @@
{
"description": "Three reporting windows configured for CTC - 2h (w1), 2d (w2) and expiry (w3). Source (app) has T1 (web), T2(web) and T3(web) in W1, where T4 gets ignored due to equal priority",
"phflags_override": {
- "measurement_enable_configurable_event_reporting_windows": "true",
"measurement_event_reports_ctc_early_reporting_windows": "7200,172800",
"measurement_flex_api_max_information_gain_dual_destination_event": "9",
"measurement_flex_api_max_information_gain_dual_destination_navigation": "14"
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2.json
index a6294ab4b..3c6ad0eda 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2.json
@@ -1,7 +1,6 @@
{
"description": "Three reporting windows configured for CTC - 2h (w1), 2d (w2) and expiry (w3). Source has T1(app) in W1 and T2(app) in W2.",
"phflags_override": {
- "measurement_enable_configurable_event_reporting_windows": "true",
"measurement_event_reports_ctc_early_reporting_windows": "7200,172800"
},
"input": {
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2_w3.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2_w3.json
index 98fdf514e..670f89e0c 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2_w3.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_ctc_w1_w2_w3.json
@@ -1,7 +1,6 @@
{
"description": "Three reporting windows configured for CTC - 2h (w1), 2d (w2) and expiry (w3). Source (web) source has T1(app) in W1, T2(web) in W2 and T4(app) in W3 where T3(web) gets replaced by T4 because T4 has higher priority.",
"phflags_override": {
- "measurement_enable_configurable_event_reporting_windows": "true",
"measurement_event_reports_ctc_early_reporting_windows": "7200,172800",
"measurement_flex_api_max_information_gain_dual_destination_event": "9",
"measurement_flex_api_max_information_gain_dual_destination_navigation": "14"
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_install_attribution.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_install_attribution.json
index 0bd0470df..dc8e961a0 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_install_attribution.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_install_attribution.json
@@ -1,7 +1,7 @@
{
"description": "Three reporting windows configured for VTC - 1h (w1), 1d (w2) and expiry (w3). Source has 2 app triggers due to install attribution in w1 and w2.",
"phflags_override": {
- "measurement_enable_configurable_event_reporting_windows": "true",
+ "measurement_vtc_configurable_max_event_reports_count": "2",
"measurement_event_reports_vtc_early_reporting_windows": "3600,86400",
"measurement_flex_api_max_information_gain_dual_destination_event": "9",
"measurement_flex_api_max_information_gain_dual_destination_navigation": "14"
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w1.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w1.json
index 3aa8dafc2..4641d4e53 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w1.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w1.json
@@ -1,7 +1,6 @@
{
"description": "Three reporting windows configured for VTC - 1h (w1), 1d (w2) and expiry (w3). Source has trigger attributed in W1.",
"phflags_override": {
- "measurement_enable_configurable_event_reporting_windows": "true",
"measurement_event_reports_vtc_early_reporting_windows": "3600,86400"
},
"input": {
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w2.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w2.json
index 9c6ec1539..ff5af97ef 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w2.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w2.json
@@ -1,7 +1,6 @@
{
"description": "Three reporting windows configured for VTC - 1h (w1), 1d (w2) and expiry (w3). Source has trigger attributed in W2 (also has another trigger which gets ignored due to lower priority).",
"phflags_override": {
- "measurement_enable_configurable_event_reporting_windows": "true",
"measurement_event_reports_vtc_early_reporting_windows": "3600,86400"
},
"input": {
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w3.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w3.json
index bc775e3a4..224f52c57 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w3.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/configurable_reporting/configurable_reporting_event_vtc_w3.json
@@ -1,7 +1,6 @@
{
"description": "Three reporting windows configured for VTC - 1h (w1), 1d (w2) and expiry (w3). Source(app) has web trigger attributed in W3.",
"phflags_override": {
- "measurement_enable_configurable_event_reporting_windows": "true",
"measurement_event_reports_vtc_early_reporting_windows": "3600,86400"
},
"input": {
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_aggregatable_two_contributions.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_aggregatable_two_contributions.json
index ebd6ed643..2338ff7f0 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_aggregatable_two_contributions.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_aggregatable_two_contributions.json
@@ -151,7 +151,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key": "347982378"
}
}],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-app_source_destination_limit.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-app_source_destination_limit.json
index a663f249a..280c87b41 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-app_source_destination_limit.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-app_source_destination_limit.json
@@ -111,7 +111,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-web_source_destination_limit.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-web_source_destination_limit.json
index d3d1ca334..2e8540bea 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-web_source_destination_limit.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_register_web-web_source_destination_limit.json
@@ -98,7 +98,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger-reporting-origin-limit-app-app.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger-reporting-origin-limit-app-app.json
index 39716916d..f4498b61c 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger-reporting-origin-limit-app-app.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger-reporting-origin-limit-app-app.json
@@ -120,7 +120,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
@@ -136,7 +136,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-app.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-app.json
index 459632d36..a4efff0cc 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-app.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-app.json
@@ -91,7 +91,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [],
@@ -106,7 +106,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"debug_aggregatable_results": [],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-web.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-web.json
index 4fdfa14c0..77ff7530a 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-web.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_app-web.json
@@ -102,7 +102,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}],
"debug_event_level_results": [{
@@ -116,7 +116,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-app.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-app.json
index bc0de4ec0..6d43ca834 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-app.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-app.json
@@ -101,7 +101,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}],
"debug_event_level_results": [{
@@ -115,7 +115,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-different-registrant.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-different-registrant.json
index b11caa533..42e17840d 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-different-registrant.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-different-registrant.json
@@ -103,7 +103,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"debug_event_level_results": [{
@@ -117,7 +117,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-same-registrant.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-same-registrant.json
index ee2b33f98..3e9241406 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-same-registrant.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_attributions_per_source_destination_limit_web-web-same-registrant.json
@@ -99,7 +99,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"debug_event_level_results": [{
@@ -113,7 +113,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346783",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-app.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-app.json
index 422d8a143..4d91151df 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-app.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-app.json
@@ -79,7 +79,7 @@
{
"payload": {
"attribution_destination": "android-app://example.2d1.test",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0001372,
"scheduled_report_time": "1643325573",
"source_event_id": "1",
"source_type": "navigation",
@@ -95,7 +95,7 @@
{
"payload": {
"attribution_destination": "android-app://example.2d1.test",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0001372,
"scheduled_report_time": "1643325573",
"source_event_id": "1",
"source_type": "navigation",
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-web.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-web.json
index a18be7506..3182ac4ce 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-web.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_app-web.json
@@ -98,7 +98,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346781",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0008051
}
}],
"debug_event_level_results": [{
@@ -112,7 +112,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346781",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0008051
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-app.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-app.json
index a425ba0f3..86e4d16d0 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-app.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-app.json
@@ -97,7 +97,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346781",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0008051
}
}],
"debug_event_level_results": [{
@@ -111,7 +111,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346781",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0008051
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-different-registrant.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-different-registrant.json
index ba15a27bd..29e524120 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-different-registrant.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-different-registrant.json
@@ -101,7 +101,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346781",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0001372
}
}],
"debug_event_level_results": [{
@@ -115,7 +115,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346781",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0001372
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-same-registrant.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-same-registrant.json
index b0c0aa01e..9eb5b1b4b 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-same-registrant.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/debug_report/debug_report_trigger_event_report_window_passed_web-web-same-registrant.json
@@ -95,7 +95,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346781",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0001372
}
}],
"debug_event_level_results": [{
@@ -109,7 +109,7 @@
"source_type": "navigation",
"source_debug_key": "347982378",
"trigger_debug_key": "8971346781",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0001372
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_3_app_sources_3_web_triggers_3_reports.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_3_app_sources_3_web_triggers_3_reports.json
index 1405c785d..5eaa9d1ac 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_3_app_sources_3_web_triggers_3_reports.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_3_app_sources_3_web_triggers_3_reports.json
@@ -123,7 +123,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}, {
"report_time": "800176400001",
@@ -134,7 +134,7 @@
"source_event_id": "2",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}, {
"report_time": "800176400001",
@@ -145,7 +145,7 @@
"source_event_id": "3",
"trigger_data": "3",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_cannot_redirect.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_cannot_redirect.json
index 518fbf142..7fabaaf82 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_cannot_redirect.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/list_sources/list_sources_cannot_redirect.json
@@ -228,7 +228,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/basic_use_of_redirect.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/basic_use_of_redirect.json
index 45fdc162c..975bd064b 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/basic_use_of_redirect.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/basic_use_of_redirect.json
@@ -44,9 +44,7 @@
"Attribution-Reporting-Register-Source": {
"source_event_id": "3",
"destination": "android-app://example.2d1.test",
- "priority": "100",
- "expiry": "800172800002"
-
+ "priority": "100"
},
"Location": null,
"Attribution-Reporting-Redirect": null
@@ -124,7 +122,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -136,7 +134,7 @@
"source_event_id": "2",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/basic_use_of_redirect_to_well_known.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/basic_use_of_redirect_to_well_known.json
new file mode 100644
index 000000000..ceb8bd2ad
--- /dev/null
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/basic_use_of_redirect_to_well_known.json
@@ -0,0 +1,113 @@
+{
+ "description": "Three sources with equal event-time, and three triggers that match. The second and third sources and triggers are obtained by redirect from the first HTTP fetch of each, using redirection to the .well-known path. Event report task within the expiry window sends the data corresponding to the three sources.",
+ "phflags_override": {
+ "measurement_enable_redirect_to_well_known_path": "true"
+ },
+ "input": {
+ "sources": [{
+ "registration_request": {
+ "attribution_src_url": "https://www.ad-tech1.test",
+ "source_type": "navigation",
+ "registrant": "example.1s1.test"
+ },
+ "responses": [
+ {
+ "url": "https://www.ad-tech1.test",
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "source_event_id": "1",
+ "destination": "android-app://example.2d1.test",
+ "priority": "100",
+ "expiry": "172801"
+ },
+ "Location": "https://www.ad-tech2.test",
+ "Attribution-Reporting-Redirect-Config": "redirect-302-to-well-known"
+ }
+ },
+ {
+ "url": "https://www.ad-tech2.test/.well-known/attribution-reporting/register-redirect?302_url=https%3A%2F%2Fwww.ad-tech2.test",
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "source_event_id": "2",
+ "destination": "android-app://example.2d1.test",
+ "priority": "100",
+ "expiry": "172801"
+ },
+
+ "Location": null,
+ "Attribution-Reporting-Redirect": null
+ }
+ }
+ ],
+ "timestamp": "800000000001"
+ }],
+ "triggers": [{
+ "registration_request": {
+ "attribution_src_url": "https://www.ad-tech1.test",
+ "registrant": "example.2d1.test"
+ },
+ "responses": [
+ {
+ "url": "https://www.ad-tech1.test",
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "event_trigger_data": [
+ {
+ "trigger_data": "1",
+ "priority": "101"
+ }
+ ]
+ },
+ "Location": "https://www.ad-tech2.test",
+ "Attribution-Reporting-Redirect-Config": "redirect-302-to-well-known"
+ }
+ },
+ {
+ "url": "https://www.ad-tech2.test/.well-known/attribution-reporting/register-redirect?302_url=https%3A%2F%2Fwww.ad-tech2.test",
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "event_trigger_data": [
+ {
+ "trigger_data": "2",
+ "priority": "101"
+ }
+ ]
+ },
+ "Location": null,
+ "Attribution-Reporting-Redirect": null
+ }
+ }
+ ],
+ "timestamp": "800000600001"
+ }]
+ },
+ "output": {
+ "event_level_results": [
+ {
+ "report_time": "800176400001",
+ "report_url": "https://www.ad-tech1.test/.well-known/attribution-reporting/report-event-attribution",
+ "payload": {
+ "attribution_destination": "android-app://example.2d1.test",
+ "scheduled_report_time": "800176400",
+ "source_event_id": "1",
+ "trigger_data": "1",
+ "source_type": "navigation",
+ "randomized_trigger_rate": 0.0008051
+ }
+ },
+ {
+ "report_time": "800176400001",
+ "report_url": "https://www.ad-tech2.test/.well-known/attribution-reporting/report-event-attribution",
+ "payload": {
+ "attribution_destination": "android-app://example.2d1.test",
+ "scheduled_report_time": "800176400",
+ "source_event_id": "2",
+ "trigger_data": "2",
+ "source_type": "navigation",
+ "randomized_trigger_rate": 0.0008051
+ }
+ }
+ ],
+ "aggregatable_results": []
+ }
+}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/complex_use_of_redirects.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/complex_use_of_redirects.json
index 413283b34..2240b5661 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/complex_use_of_redirects.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/complex_use_of_redirects.json
@@ -50,9 +50,7 @@
"Attribution-Reporting-Register-Source": {
"source_event_id": "3",
"destination": "android-app://example.2d1.test",
- "priority": "100",
- "expiry": "800172800002"
-
+ "priority": "100"
},
"Location": "https://www.unenrolled-non-registering2.test",
"Attribution-Reporting-Redirect": [
@@ -66,9 +64,7 @@
"Attribution-Reporting-Register-Source": {
"source_event_id": "4",
"destination": "android-app://example.2d1.test",
- "priority": "100",
- "expiry": "800172800002"
-
+ "priority": "100"
},
"Location": null,
"Attribution-Reporting-Redirect": null
@@ -80,9 +76,7 @@
"Attribution-Reporting-Register-Source": {
"source_event_id": "6",
"destination": "android-app://example.2d1.test",
- "priority": "100",
- "expiry": "800172800002"
-
+ "priority": "100"
},
"Attribution-Reporting-Redirect": [
"https://www.ad-tech5.test"
@@ -96,9 +90,7 @@
"Attribution-Reporting-Register-Source": {
"source_event_id": "5",
"destination": "android-app://example.2d1.test",
- "priority": "100",
- "expiry": "800172800002"
-
+ "priority": "100"
},
"Location": null,
"Attribution-Reporting-Redirect": null
@@ -231,7 +223,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -243,7 +235,7 @@
"source_event_id": "2",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/complex_use_of_redirects_to_well_known.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/complex_use_of_redirects_to_well_known.json
new file mode 100644
index 000000000..e9a811d4c
--- /dev/null
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/complex_use_of_redirects_to_well_known.json
@@ -0,0 +1,287 @@
+{
+ "description": "7 (5 registering & 2 non-registering) redirects each for source & triggers. Redirection to .well-known path is enabled intermediately, making all subsequent Location-type registrations redirect to the .well-known path, even without the header. All 5 sources and triggers match. Event report task within the expiry window sends the data corresponding to the 5 sources.",
+ "phflags_override": {
+ "measurement_enable_redirect_to_well_known_path": "true"
+ },
+ "input": {
+ "sources": [{
+ "registration_request": {
+ "attribution_src_url": "https://www.ad-tech1.test",
+ "source_type": "navigation",
+ "registrant": "example.1s1.test"
+ },
+ "responses": [
+ {
+ "url": "https://www.ad-tech1.test",
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "source_event_id": "1",
+ "destination": "android-app://example.2d1.test",
+ "priority": "100",
+ "expiry": "172801"
+ },
+ "Location": null,
+ "Attribution-Reporting-Redirect": [
+ "https://www.ad-tech2.test",
+ "https://www.enrolled-non-registering1.test"
+ ]
+ }
+ },
+ {
+ "url": "https://www.ad-tech2.test",
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "source_event_id": "2",
+ "destination": "android-app://example.2d1.test",
+ "priority": "100",
+ "expiry": "172801"
+ },
+
+ "Location": null,
+ "Attribution-Reporting-Redirect": null
+ }
+ },
+ {
+ "url": "https://www.enrolled-non-registering1.test",
+ "response": {
+ "Location": "https://www.ad-tech3.test",
+ "Attribution-Reporting-Redirect-Config": "redirect-302-to-well-known"
+ }
+ },
+ {
+ "url": "https://www.ad-tech3.test/.well-known/attribution-reporting/register-redirect?302_url=https%3A%2F%2Fwww.ad-tech3.test",
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "source_event_id": "3",
+ "destination": "android-app://example.2d1.test",
+ "priority": "100"
+ },
+ "Location": "https://www.unenrolled-non-registering2.test",
+ "Attribution-Reporting-Redirect": [
+ "https://www.ad-tech4.test"
+ ]
+ }
+ },
+ {
+ "url": "https://www.ad-tech4.test",
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "source_event_id": "4",
+ "destination": "android-app://example.2d1.test",
+ "priority": "100"
+ },
+ "Location": null,
+ "Attribution-Reporting-Redirect": null
+ }
+ },
+ {
+ "url": "https://www.unenrolled-non-registering2.test/.well-known/attribution-reporting/register-redirect?302_url=https%3A%2F%2Fwww.unenrolled-non-registering2.test",
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "source_event_id": "6",
+ "destination": "android-app://example.2d1.test",
+ "priority": "100"
+ },
+ "Attribution-Reporting-Redirect": [
+ "https://www.ad-tech5.test"
+ ]
+ },
+ "enroll": false
+ },
+ {
+ "url": "https://www.ad-tech5.test",
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "source_event_id": "5",
+ "destination": "android-app://example.2d1.test",
+ "priority": "100",
+ "expiry": "800172800002"
+
+ },
+ "Location": null,
+ "Attribution-Reporting-Redirect": null
+ }
+ }
+ ],
+ "timestamp": "800000000001"
+ }],
+ "triggers": [{
+ "registration_request": {
+ "attribution_src_url": "https://www.ad-tech1.test",
+ "registrant": "example.2d1.test"
+ },
+ "responses": [
+ {
+ "url": "https://www.ad-tech1.test",
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "event_trigger_data": [
+ {
+ "trigger_data": "1",
+ "priority": "101"
+ }
+ ]
+ },
+ "Location": null,
+ "Attribution-Reporting-Redirect": [
+ "https://www.ad-tech2.test",
+ "https://www.enrolled-non-registering1.test"
+ ]
+ }
+ },
+ {
+ "url": "https://www.ad-tech2.test",
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "event_trigger_data": [
+ {
+ "trigger_data": "2",
+ "priority": "101"
+ }
+ ]
+ },
+ "Location": null,
+ "Attribution-Reporting-Redirect": null
+ }
+ },
+ {
+ "url": "https://www.enrolled-non-registering1.test",
+ "response": {
+ "Location": "https://www.ad-tech3.test",
+ "Attribution-Reporting-Redirect-Config": "redirect-302-to-well-known"
+ }
+ },
+ {
+ "url": "https://www.ad-tech3.test/.well-known/attribution-reporting/register-redirect?302_url=https%3A%2F%2Fwww.ad-tech3.test",
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "event_trigger_data": [
+ {
+ "trigger_data": "3",
+ "priority": "101"
+ }
+ ]
+ },
+ "Location": "https://www.unenrolled-non-registering2.test",
+ "Attribution-Reporting-Redirect": [
+ "https://www.ad-tech4.test"
+ ]
+ }
+ },
+ {
+ "url": "https://www.ad-tech4.test",
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "event_trigger_data": [
+ {
+ "trigger_data": "4",
+ "priority": "101"
+ }
+ ]
+ },
+ "Location": null,
+ "Attribution-Reporting-Redirect": null
+ }
+ },
+ {
+ "url": "https://www.unenrolled-non-registering2.test/.well-known/attribution-reporting/register-redirect?302_url=https%3A%2F%2Fwww.unenrolled-non-registering2.test",
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "event_trigger_data": [
+ {
+ "trigger_data": "6",
+ "priority": "101"
+ }
+ ]
+ },
+ "Attribution-Reporting-Redirect": [
+ "https://www.ad-tech5.test"
+ ]
+ },
+ "enroll": false
+ },
+ {
+ "url": "https://www.ad-tech5.test",
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "event_trigger_data": [
+ {
+ "trigger_data": "5",
+ "priority": "101"
+ }
+ ]
+ },
+ "Location": null,
+ "Attribution-Reporting-Redirect": null
+ }
+ }
+ ],
+ "timestamp": "800000600001"
+ }]
+ },
+ "output": {
+ "event_level_results": [
+ {
+ "report_time": "800176400001",
+ "report_url": "https://www.ad-tech1.test/.well-known/attribution-reporting/report-event-attribution",
+ "payload": {
+ "attribution_destination": "android-app://example.2d1.test",
+ "scheduled_report_time": "800176400",
+ "source_event_id": "1",
+ "trigger_data": "1",
+ "source_type": "navigation",
+ "randomized_trigger_rate": 0.0008051
+ }
+ },
+ {
+ "report_time": "800176400001",
+ "report_url": "https://www.ad-tech2.test/.well-known/attribution-reporting/report-event-attribution",
+ "payload": {
+ "attribution_destination": "android-app://example.2d1.test",
+ "scheduled_report_time": "800176400",
+ "source_event_id": "2",
+ "trigger_data": "2",
+ "source_type": "navigation",
+ "randomized_trigger_rate": 0.0008051
+ }
+ },
+ {
+ "report_time": "800176400001",
+ "report_url": "https://www.ad-tech3.test/.well-known/attribution-reporting/report-event-attribution",
+ "payload": {
+ "attribution_destination": "android-app://example.2d1.test",
+ "scheduled_report_time": "800176400",
+ "source_event_id": "3",
+ "trigger_data": "3",
+ "source_type": "navigation",
+ "randomized_trigger_rate": 0.0024263
+ }
+ },
+ {
+ "report_time": "800176400001",
+ "report_url": "https://www.ad-tech4.test/.well-known/attribution-reporting/report-event-attribution",
+ "payload": {
+ "attribution_destination": "android-app://example.2d1.test",
+ "scheduled_report_time": "800176400",
+ "source_event_id": "4",
+ "trigger_data": "4",
+ "source_type": "navigation",
+ "randomized_trigger_rate": 0.0024263
+ }
+ },
+ {
+ "report_time": "800176400001",
+ "report_url": "https://www.ad-tech5.test/.well-known/attribution-reporting/report-event-attribution",
+ "payload": {
+ "attribution_destination": "android-app://example.2d1.test",
+ "scheduled_report_time": "800176400",
+ "source_event_id": "5",
+ "trigger_data": "5",
+ "source_type": "navigation",
+ "randomized_trigger_rate": 0.0024263
+ }
+ }
+ ],
+ "aggregatable_results": []
+ }
+}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_1_allowed.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_1_allowed.json
index a86d67674..f6921321a 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_1_allowed.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_1_allowed.json
@@ -126,7 +126,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_2_allowed.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_2_allowed.json
index 587739024..e9228b9c4 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_2_allowed.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_2_allowed.json
@@ -126,7 +126,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_disabled.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_disabled.json
index a9752fec1..2da69130d 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_disabled.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/coordinator_origin_disabled.json
@@ -126,7 +126,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/enrollment_flag_disabled.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/enrollment_flag_disabled.json
index 0b966e24d..4a17c0eb6 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/enrollment_flag_disabled.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/enrollment_flag_disabled.json
@@ -108,7 +108,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": [{
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_debug_source_storage_limit.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_debug_source_storage_limit.json
index 71b47b104..1ba32b6d5 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_debug_source_storage_limit.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_debug_source_storage_limit.json
@@ -88,7 +88,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key": "347982378",
"trigger_debug_key": "147982378"
}
@@ -102,7 +102,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key": "347982378",
"trigger_debug_key": "147982378"
}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_report_window.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_report_window.json
index 67ef2d38d..615ab4931 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_report_window.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_report_window.json
@@ -121,7 +121,7 @@
"payload": {
"attribution_destination": "android-app://destination.test",
"scheduled_report_time": "1643325573",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0001372,
"source_event_id": "123",
"source_type": "navigation",
"trigger_data": "1"
@@ -133,7 +133,7 @@
"payload": {
"attribution_destination": "android-app://destination.test",
"scheduled_report_time": "1643325573",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0001372,
"source_event_id": "123",
"source_type": "navigation",
"trigger_data": "2"
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_time_based_source_selection.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_time_based_source_selection.json
index 6d9b78f24..b84aeab36 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_time_based_source_selection.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/event_time_based_source_selection.json
@@ -78,7 +78,7 @@
"source_event_id": "2",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/limit_num_reports_for_click.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/limit_num_reports_for_click.json
index 9adf76d18..71dd31cc7 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/limit_num_reports_for_click.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/limit_num_reports_for_click.json
@@ -124,7 +124,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -136,7 +136,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -148,7 +148,7 @@
"source_event_id": "1",
"trigger_data": "3",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_as_reporting_origin.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_as_reporting_origin.json
index f3944e4eb..bef06b6e4 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_as_reporting_origin.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_as_reporting_origin.json
@@ -55,7 +55,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_basic_use_of_redirect.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_basic_use_of_redirect.json
index 944d30722..b519eb9f5 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_basic_use_of_redirect.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_basic_use_of_redirect.json
@@ -93,7 +93,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -105,7 +105,7 @@
"source_event_id": "2",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_ip_as_reporting_origin.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_ip_as_reporting_origin.json
index d7fad3f79..1e0697941 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_ip_as_reporting_origin.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/localhost_ip_as_reporting_origin.json
@@ -55,7 +55,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/only_one_source_of_multiple_matches_can_be_attributed.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/only_one_source_of_multiple_matches_can_be_attributed.json
index 4563f3798..7a5af3e5c 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/only_one_source_of_multiple_matches_can_be_attributed.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/only_one_source_of_multiple_matches_can_be_attributed.json
@@ -103,7 +103,7 @@
"source_event_id": "2",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -115,7 +115,7 @@
"source_event_id": "2",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/priority_based_source_selection.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/priority_based_source_selection.json
index 41595f546..fdc35df28 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/priority_based_source_selection.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/priority_based_source_selection.json
@@ -78,7 +78,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWebSource_3_sources_3_triggers_3_reports.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWebSource_3_sources_3_triggers_3_reports.json
index 8827e69b5..2c000a83b 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWebSource_3_sources_3_triggers_3_reports.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWebSource_3_sources_3_triggers_3_reports.json
@@ -128,7 +128,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}, {
"report_time": "800176400001",
@@ -139,7 +139,7 @@
"source_event_id": "2",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}, {
"report_time": "800176400001",
@@ -150,7 +150,7 @@
"source_event_id": "3",
"trigger_data": "3",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching.json
index eac5f0a52..03fb47d11 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching.json
@@ -64,7 +64,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_different_registrant.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_different_registrant.json
index ddb67affd..5ef74d0e6 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_different_registrant.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_different_registrant.json
@@ -66,7 +66,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_same_registrant.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_same_registrant.json
index b712042b8..f0c60f59e 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_same_registrant.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_ar_debug_same_registrant.json
@@ -66,7 +66,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key" : "347982378",
"trigger_debug_key" : "8971346783"
}
@@ -80,7 +80,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key" : "347982378",
"trigger_debug_key" : "8971346783"
}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_no_adid_no_ar_debug.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_no_adid_no_ar_debug.json
index 15dbcae8f..e43a0c409 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_no_adid_no_ar_debug.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_api_no_adid_no_ar_debug.json
@@ -64,7 +64,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_disabled_different_registrant.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_disabled_different_registrant.json
index 061c0c743..8142f2c57 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_disabled_different_registrant.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_disabled_different_registrant.json
@@ -69,7 +69,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_enabled_different_registrant.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_enabled_different_registrant.json
index ac91e0adf..0917d9434 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_enabled_different_registrant.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-1_web-web_matching_debug_join_enabled_different_registrant.json
@@ -69,7 +69,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key" : "347982378",
"trigger_debug_key" : "8971346783"
}
@@ -83,7 +83,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263,
+ "randomized_trigger_rate": 0.0008051,
"source_debug_key" : "347982378",
"trigger_debug_key" : "8971346783"
}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_app_and_web_matching.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_app_and_web_matching.json
index 8be0277e0..dcf130f11 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_app_and_web_matching.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_app_and_web_matching.json
@@ -88,7 +88,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}, {
"report_time": "800176400001",
@@ -99,7 +99,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_web_only_matching.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_web_only_matching.json
index faa480667..ccb8f3fce 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_web_only_matching.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_1-2_web_only_matching.json
@@ -83,7 +83,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_adid_debug_api.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_adid_debug_api.json
index da1aab976..b047a48a8 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_adid_debug_api.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_adid_debug_api.json
@@ -83,7 +83,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}]
}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_ar_debug_adid_debug_api.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_ar_debug_adid_debug_api.json
index b161cb42f..681d1f66d 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_ar_debug_adid_debug_api.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_ar_debug_adid_debug_api.json
@@ -83,7 +83,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}]
}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_debug_api_ar_debug.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_debug_api_ar_debug.json
index 9fb5654c9..57c247e4e 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_debug_api_ar_debug.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_app-web_debug_api_ar_debug.json
@@ -82,7 +82,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}]
}
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_multiple_destinations.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_multiple_destinations.json
index 93f63a51e..ca316b775 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_multiple_destinations.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_multiple_destinations.json
@@ -89,7 +89,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -101,7 +101,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_redirects_ignored.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_redirects_ignored.json
index 646b2e2b1..280fc4193 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_redirects_ignored.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_redirects_ignored.json
@@ -106,7 +106,7 @@
"source_event_id": "1",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_web_app_matching_debug_api_adid_ar_debug.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_web_app_matching_debug_api_adid_ar_debug.json
index 11d36313c..5a229be9b 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_web_app_matching_debug_api_adid_ar_debug.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/registerWeb_web_app_matching_debug_api_adid_ar_debug.json
@@ -68,7 +68,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_1-1_app-app_matching.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_1-1_app-app_matching.json
index 768d5f994..080c62ca1 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_1-1_app-app_matching.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_1-1_app-app_matching.json
@@ -55,7 +55,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_empty_object_event_trigger_data.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_empty_object_event_trigger_data.json
index d2be23319..9fd1eb923 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_empty_object_event_trigger_data.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_empty_object_event_trigger_data.json
@@ -50,7 +50,7 @@
"source_event_id": "0",
"trigger_data": "0",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_null_trigger_data_null_source_event_id.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_null_trigger_data_null_source_event_id.json
index c36147be6..670c8de80 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_null_trigger_data_null_source_event_id.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-app_null_trigger_data_null_source_event_id.json
@@ -55,7 +55,7 @@
"source_event_id": "0",
"trigger_data": "0",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_dual_destination_source_storage_limit_debug_report.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_dual_destination_source_storage_limit_debug_report.json
index 2041a9d2f..22e7b538a 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_dual_destination_source_storage_limit_debug_report.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_dual_destination_source_storage_limit_debug_report.json
@@ -99,7 +99,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0170218
+ "randomized_trigger_rate": 0.0054129
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_source_storage_limit_debug_report.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_source_storage_limit_debug_report.json
index dad35eb61..9a88bf402 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_source_storage_limit_debug_report.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_app-web_source_storage_limit_debug_report.json
@@ -94,7 +94,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_web-web_source_storage_limit_debug_report.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_web-web_source_storage_limit_debug_report.json
index be217c98c..aaa2b6d4c 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_web-web_source_storage_limit_debug_report.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/register_web-web_source_storage_limit_debug_report.json
@@ -100,7 +100,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"verbose_debug_reports": [
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_one_trigger.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_one_trigger.json
index 443987f27..9dec79b88 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_one_trigger.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_one_trigger.json
@@ -99,7 +99,7 @@
"source_event_id": "2",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}],
"aggregatable_results": []
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_three_triggers_one_dedup.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_three_triggers_one_dedup.json
index 17a8ecc36..0343b9bf3 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_three_triggers_one_dedup.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/three_sources_three_triggers_one_dedup.json
@@ -149,7 +149,7 @@
"source_event_id": "2",
"trigger_data": "1",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -161,7 +161,7 @@
"source_event_id": "2",
"trigger_data": "0",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/two_simple_matches_testing_multiplicity.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/two_simple_matches_testing_multiplicity.json
index fa9c81136..aaabe1703 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/two_simple_matches_testing_multiplicity.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/misc/two_simple_matches_testing_multiplicity.json
@@ -103,7 +103,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
},
{
@@ -115,7 +115,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_disabled_basic.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_disabled_basic.json
index d859f3413..8fcd67d55 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_disabled_basic.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_disabled_basic.json
@@ -193,7 +193,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_original_source_wins_install_attribution.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_original_source_wins_install_attribution.json
index ee188284d..9956388e9 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_original_source_wins_install_attribution.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_original_source_wins_install_attribution.json
@@ -373,7 +373,7 @@
"source_event_id": "1",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_reg_has_original_xna_source_avoids_creating_derived_source.json b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_reg_has_original_xna_source_avoids_creating_derived_source.json
index 233e156c5..bd792b74c 100644
--- a/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_reg_has_original_xna_source_avoids_creating_derived_source.json
+++ b/adservices/tests/unittest/service-core/assets/msmt_e2e_tests/xna/xna_reg_has_original_xna_source_avoids_creating_derived_source.json
@@ -183,7 +183,7 @@
"source_event_id": "2",
"trigger_data": "2",
"source_type": "navigation",
- "randomized_trigger_rate": 0.0024263
+ "randomized_trigger_rate": 0.0008051
}
}
],
diff --git a/adservices/tests/unittest/service-core/assets/msmt_interop_tests/event_report_windows.json b/adservices/tests/unittest/service-core/assets/msmt_interop_tests/event_report_windows.json
new file mode 100644
index 000000000..e9a96f2fe
--- /dev/null
+++ b/adservices/tests/unittest/service-core/assets/msmt_interop_tests/event_report_windows.json
@@ -0,0 +1,289 @@
+{
+ "description": "Set report windows for navigation type event-level reporting",
+ "input": {
+ "registrations": [
+ {
+ "timestamp": "0",
+ "registration_request": {
+ "context_origin": "https://source.test",
+ "attribution_src_url": "https://reporter.test/register-source",
+ "source_type": "navigation"
+ },
+ "responses": [
+ {
+ "url": "https://reporter.test/register-source",
+ "debug_permission": true,
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "destination": "https://destination.test",
+ "source_event_id": "123",
+ "expiry": "1296000",
+ "event_report_windows": {
+ "start_time": 3600,
+ // 2592000 s clamped down to expiry.
+ "end_times": [86400, 2592000]
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "timestamp": "1000",
+ "registration_request": {
+ "context_origin": "https://source.test",
+ "attribution_src_url": "https://reporter2.test/register-source",
+ "source_type": "navigation"
+ },
+ "responses": [
+ {
+ "url": "https://reporter2.test/register-source",
+ "debug_permission": true,
+ "response": {
+ "Attribution-Reporting-Register-Source": {
+ "destination": "https://destination2.test",
+ "source_event_id": "456",
+ "event_report_windows": {
+ "start_time": 0,
+ // 1800 rounded to 3600 (1 hr).
+ "end_times": [1800]
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ // Should result in an event-level report in the first window
+ // rounded up to 1 hour (3600 s).
+ "timestamp": "1900000",
+ "registration_request": {
+ "attribution_src_url": "https://reporter2.test/register-trigger",
+ "context_origin": "https://destination2.test"
+ },
+ "responses": [
+ {
+ "url": "https://reporter2.test/register-trigger",
+ "debug_permission": true,
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "debug_reporting": true,
+ "event_trigger_data": [
+ {
+ "trigger_data": "4"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ // Should not result in an event-level report as the event report start
+ // time has passed,
+ {
+ // 3,600,000 ms = 1 hour = clamped event_report_window value.
+ "timestamp": "3590000",
+ "registration_request": {
+ "attribution_src_url": "https://reporter.test/register-trigger",
+ "context_origin": "https://destination.test"
+ },
+ "responses": [
+ {
+ "url": "https://reporter.test/register-trigger",
+ "debug_permission": true,
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "debug_reporting": true,
+ "event_trigger_data": [
+ {
+ "trigger_data": "1"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ // Should result in an event-level report in the first window.
+ "timestamp": "3600000",
+ "registration_request": {
+ "attribution_src_url": "https://reporter.test/register-trigger",
+ "context_origin": "https://destination.test"
+ },
+ "responses": [
+ {
+ "url": "https://reporter.test/register-trigger",
+ "debug_permission": true,
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "debug_reporting": true,
+ "event_trigger_data": [
+ {
+ "trigger_data": "1"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ // Should not result in an event-level report.
+ "timestamp": "3700000",
+ "registration_request": {
+ "attribution_src_url": "https://reporter2.test/register-trigger",
+ "context_origin": "https://destination2.test"
+ },
+ "responses": [
+ {
+ "url": "https://reporter2.test/register-trigger",
+ "debug_permission": true,
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "debug_reporting": true,
+ "event_trigger_data": [
+ {
+ "trigger_data": "5"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ // Should result in an event-level report in the last window.
+ "timestamp": "1209600000",
+ "registration_request": {
+ "attribution_src_url": "https://reporter.test/register-trigger",
+ "context_origin": "https://destination.test"
+ },
+ "responses": [
+ {
+ "url": "https://reporter.test/register-trigger",
+ "debug_permission": true,
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "debug_reporting": true,
+ "event_trigger_data": [
+ {
+ "trigger_data": "2"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ // Should not result in an event-level report as the last window was
+ // clamped to 1296000 s.
+ "timestamp": "1296000000",
+ "registration_request": {
+ "attribution_src_url": "https://reporter.test/register-trigger",
+ "context_origin": "https://destination.test"
+ },
+ "responses": [
+ {
+ "url": "https://reporter.test/register-trigger",
+ "debug_permission": true,
+ "response": {
+ "Attribution-Reporting-Register-Trigger": {
+ "debug_reporting": true,
+ "event_trigger_data": [
+ {
+ "trigger_data": "3"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "output": {
+ "unparsable_registrations": [],
+ "reports": [
+ {
+ "payload": [
+ {
+ "body": {
+ "attribution_destination": "https://destination.test",
+ "source_event_id": "123",
+ "source_site": "https://source.test"
+ },
+ "type": "trigger-event-report-window-not-started"
+ }
+ ],
+ "report_time": "3590000",
+ "report_url": "https://reporter.test/.well-known/attribution-reporting/debug/verbose"
+ },
+ {
+ "payload": {
+ "attribution_destination": "https://destination2.test",
+ "randomized_trigger_rate": 0.0001372,
+ // 3601 s = 3600 s (rounded window) + 1 s (source timestamp).
+ "scheduled_report_time": "3601",
+ "source_event_id": "456",
+ "source_type": "navigation",
+ "trigger_data": "4"
+ },
+ "report_url": "https://reporter2.test/.well-known/attribution-reporting/report-event-attribution",
+ "report_time": "3601000"
+ },
+ {
+ "payload": [
+ {
+ "body": {
+ "attribution_destination": "https://destination2.test",
+ "source_event_id": "456",
+ "source_site": "https://source.test"
+ },
+ "type": "trigger-event-report-window-passed"
+ }
+ ],
+ "report_time": "3700000",
+ "report_url": "https://reporter2.test/.well-known/attribution-reporting/debug/verbose"
+ },
+ {
+ "payload": {
+ "attribution_destination": "https://destination.test",
+ "randomized_trigger_rate": 0.0008051,
+ "scheduled_report_time": "86400",
+ "source_event_id": "123",
+ "source_type": "navigation",
+ "trigger_data": "1"
+ },
+ "report_url": "https://reporter.test/.well-known/attribution-reporting/report-event-attribution",
+ "report_time": "86400000"
+ },
+ {
+ "payload": {
+ "attribution_destination": "https://destination.test",
+ "randomized_trigger_rate": 0.0008051,
+ "scheduled_report_time": "1296000",
+ "source_event_id": "123",
+ "source_type": "navigation",
+ "trigger_data": "2"
+ },
+ "report_url": "https://reporter.test/.well-known/attribution-reporting/report-event-attribution",
+ "report_time": "1296000000"
+ },
+ {
+ "payload": [
+ {
+ "body": {
+ "attribution_destination": "https://destination.test"
+ },
+ // Source has expired at this point.
+ "type": "trigger-no-matching-source"
+ }
+ ],
+ "report_time": "1296000000",
+ "report_url": "https://reporter.test/.well-known/attribution-reporting/debug/verbose"
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/adservices/tests/unittest/service-core/common/Android.bp b/adservices/tests/unittest/service-core/common/Android.bp
new file mode 100644
index 000000000..b128e30ec
--- /dev/null
+++ b/adservices/tests/unittest/service-core/common/Android.bp
@@ -0,0 +1,33 @@
+// Copyright (C) 2024 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: "AdServicesServiceCoreCommonUnitTests",
+ srcs: [
+ "src/**/*.java",
+ ],
+ defaults: ["AdServices-ServiceCoreUnitTest-Defaults"],
+}
+
+android_test {
+ name: "AdExtServicesServiceCoreCommonUnitTests",
+ srcs: [
+ "src/**/*.java",
+ ],
+ defaults: ["AdExtServices-ServiceCoreUnitTest-Defaults"],
+ test_config: "AndroidTest.ExtServices.xml",
+}
diff --git a/adservices/tests/unittest/service-core/common/AndroidManifest.xml b/adservices/tests/unittest/service-core/common/AndroidManifest.xml
new file mode 100644
index 000000000..cdbd758b5
--- /dev/null
+++ b/adservices/tests/unittest/service-core/common/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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.servicecorecommontest">
+ <!-- android:debuggable="true" is needed. See b/228384531 -->
+ <application android:debuggable="true">
+ <uses-library android:name="android.ext.adservices" android:required="false"/>
+ </application>
+
+ <!-- Entries below are necessary so atest can work without specifying the project. -->
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.adservices.servicecorecommontest">
+ </instrumentation>
+</manifest>
diff --git a/adservices/tests/unittest/service-core/common/AndroidTest.ExtServices.xml b/adservices/tests/unittest/service-core/common/AndroidTest.ExtServices.xml
new file mode 100644
index 000000000..900999fa6
--- /dev/null
+++ b/adservices/tests/unittest/service-core/common/AndroidTest.ExtServices.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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 AdServices Service-core common test cases in ExtServices">
+ <object class="com.android.tradefed.testtype.suite.module.MaxSdkModuleController"
+ type="module_controller">
+ <option name="max-sdk-level" value="32"/>
+ </object>
+
+ <!-- Prevent test from running on Android T+ -->
+ <object class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController"
+ type="module_controller"/>
+
+ <!-- Prevent tests from running on Android Q- -->
+ <object class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"
+ type="module_controller">
+ <option name="mainline-module-package-name" value="com.google.android.extservices"/>
+ </object>
+
+ <option name="test-tag" value="AdExtServicesServiceCoreCommonUnitTests"/>
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.extservices.apex"/>
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="check-min-sdk" value="true"/>
+ <option name="test-file-name" value="AdExtServicesServiceCoreCommonUnitTests.apk"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE"/>
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.adservices.servicecorecommontest"/>
+ </test>
+</configuration>
diff --git a/adservices/tests/unittest/service-core/common/AndroidTest.xml b/adservices/tests/unittest/service-core/common/AndroidTest.xml
new file mode 100644
index 000000000..f9a08c35b
--- /dev/null
+++ b/adservices/tests/unittest/service-core/common/AndroidTest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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 Ad Services Service-core common test cases">
+ <object class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"
+ type="module_controller">
+ <option name="mainline-module-package-name" value="com.google.android.adservices"/>
+ </object>
+
+ <option name="test-tag" value="AdServicesServiceCoreCommonUnitTests"/>
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.adservices.apex"/>
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="check-min-sdk" value="true"/>
+ <option name="test-file-name" value="AdServicesServiceCoreCommonUnitTests.apk"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="setprop log.tag.adservices VERBOSE"/>
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.adservices.servicecorecommontest"/>
+ </test>
+</configuration>
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/errorlogging/AdServicesErrorLoggerImplTest.java b/adservices/tests/unittest/service-core/common/src/com/android/adservices/errorlogging/AdServicesErrorLoggerImplTest.java
index 847c08e52..bdf20f56d 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/errorlogging/AdServicesErrorLoggerImplTest.java
+++ b/adservices/tests/unittest/service-core/common/src/com/android/adservices/errorlogging/AdServicesErrorLoggerImplTest.java
@@ -21,10 +21,9 @@ import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICE
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__TOPICS;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.database.sqlite.SQLiteException;
@@ -37,11 +36,10 @@ import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCase {
- private AdServicesErrorLoggerImpl mErrorLogger;
-
// Constants used for tests
private static final String CLASS_NAME = "TopicsService";
private static final String METHOD_NAME = "getTopics";
@@ -50,17 +48,19 @@ public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCa
private static final String SQ_LITE_EXCEPTION = "SQLiteException";
@Mock private Flags mFlags;
- @Mock StatsdAdServicesErrorLogger mStatsdLoggerMock;
+ @Mock private StatsdAdServicesErrorLogger mStatsdLoggerMock;
+
+ private AdServicesErrorLoggerImpl mErrorLogger;
@Before
public void setUp() {
mErrorLogger = new AdServicesErrorLoggerImpl(mFlags, mStatsdLoggerMock);
- doReturn(ImmutableList.of()).when(mFlags).getErrorCodeLoggingDenyList();
+ mockErrorCodeLoggingDenyList(ImmutableList.of());
}
@Test
public void testLogError_errorLoggingFlagDisabled() {
- doReturn(false).when(mFlags).getAdServicesErrorLoggingEnabled();
+ mockAdServicesErrorLogging(/* enabled= */ false);
mErrorLogger.logError(
AD_SERVICES_ERROR_REPORTED__ERROR_CODE__CONSENT_REVOKED_ERROR, PPAPI_NAME);
@@ -70,10 +70,9 @@ public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCa
@Test
public void testLogError_errorLoggingFlagEnabled_errorCodeLoggingDenied() {
- doReturn(true).when(mFlags).getAdServicesErrorLoggingEnabled();
- doReturn(ImmutableList.of(AD_SERVICES_ERROR_REPORTED__ERROR_CODE__CONSENT_REVOKED_ERROR))
- .when(mFlags)
- .getErrorCodeLoggingDenyList();
+ mockAdServicesErrorLogging(/* enabled= */ true);
+ mockErrorCodeLoggingDenyList(
+ ImmutableList.of(AD_SERVICES_ERROR_REPORTED__ERROR_CODE__CONSENT_REVOKED_ERROR));
mErrorLogger.logError(
AD_SERVICES_ERROR_REPORTED__ERROR_CODE__CONSENT_REVOKED_ERROR, PPAPI_NAME);
@@ -83,16 +82,23 @@ public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCa
@Test
public void testLogError_errorLoggingFlagEnabled() {
- doReturn(true).when(mFlags).getAdServicesErrorLoggingEnabled();
+ mockAdServicesErrorLogging(/* enabled= */ true);
+ ArgumentCaptor<AdServicesErrorStats> adServicesErrorStatsArgumentCaptor =
+ ArgumentCaptor.forClass(AdServicesErrorStats.class);
+
mErrorLogger.logError(
AD_SERVICES_ERROR_REPORTED__ERROR_CODE__CONSENT_REVOKED_ERROR, PPAPI_NAME);
- verify(mStatsdLoggerMock).logAdServicesError(any());
+ verify(mStatsdLoggerMock).logAdServicesError(adServicesErrorStatsArgumentCaptor.capture());
+ AdServicesErrorStats adServicesErrorStats = adServicesErrorStatsArgumentCaptor.getValue();
+ expect.that(adServicesErrorStats.getErrorCode())
+ .isEqualTo(AD_SERVICES_ERROR_REPORTED__ERROR_CODE__CONSENT_REVOKED_ERROR);
+ expect.that(adServicesErrorStats.getPpapiName()).isEqualTo(PPAPI_NAME);
}
@Test
public void testLogErrorWithExceptionInfo_errorLoggingFlagDisabled() {
- doReturn(false).when(mFlags).getAdServicesErrorLoggingEnabled();
+ mockAdServicesErrorLogging(/* enabled= */ false);
mErrorLogger.logErrorWithExceptionInfo(
new Exception(),
@@ -104,10 +110,9 @@ public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCa
@Test
public void testLogErrorWithExceptionInfo_errorLoggingFlagEnabled_errorCodeLoggingDenied() {
- doReturn(true).when(mFlags).getAdServicesErrorLoggingEnabled();
- doReturn(ImmutableList.of(AD_SERVICES_ERROR_REPORTED__ERROR_CODE__DATABASE_READ_EXCEPTION))
- .when(mFlags)
- .getErrorCodeLoggingDenyList();
+ mockAdServicesErrorLogging(/* enabled= */ true);
+ mockErrorCodeLoggingDenyList(
+ ImmutableList.of(AD_SERVICES_ERROR_REPORTED__ERROR_CODE__DATABASE_READ_EXCEPTION));
mErrorLogger.logErrorWithExceptionInfo(
new Exception(),
@@ -119,8 +124,7 @@ public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCa
@Test
public void testLogErrorWithExceptionInfo_errorLoggingFlagEnabled() {
- doReturn(true).when(mFlags).getAdServicesErrorLoggingEnabled();
-
+ mockAdServicesErrorLogging(/* enabled= */ true);
Exception exception = createSQLiteException(CLASS_NAME, METHOD_NAME, LINE_NUMBER);
mErrorLogger.logErrorWithExceptionInfo(
@@ -138,13 +142,12 @@ public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCa
.setLineNumber(LINE_NUMBER)
.setLastObservedExceptionName(SQ_LITE_EXCEPTION)
.build();
- verify(mStatsdLoggerMock).logAdServicesError(eq(stats));
+ verify(mStatsdLoggerMock).logAdServicesError(stats);
}
@Test
public void testLogErrorWithExceptionInfo_fullyQualifiedClassName_errorLoggingFlagEnabled() {
- doReturn(true).when(mFlags).getAdServicesErrorLoggingEnabled();
-
+ mockAdServicesErrorLogging(/* enabled= */ true);
String fullClassName = "com.android.adservices.topics.TopicsService";
Exception exception = createSQLiteException(fullClassName, METHOD_NAME, LINE_NUMBER);
@@ -163,12 +166,12 @@ public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCa
.setLineNumber(LINE_NUMBER)
.setLastObservedExceptionName(SQ_LITE_EXCEPTION)
.build();
- verify(mStatsdLoggerMock).logAdServicesError(eq(stats));
+ verify(mStatsdLoggerMock).logAdServicesError(stats);
}
@Test
public void testLogErrorWithExceptionInfo_emptyClassName_errorLoggingFlagEnabled() {
- doReturn(true).when(mFlags).getAdServicesErrorLoggingEnabled();
+ mockAdServicesErrorLogging(/* enabled= */ true);
Exception exception = createSQLiteException(/* className = */ "", METHOD_NAME, LINE_NUMBER);
@@ -186,7 +189,7 @@ public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCa
.setLineNumber(LINE_NUMBER)
.setLastObservedExceptionName(SQ_LITE_EXCEPTION)
.build();
- verify(mStatsdLoggerMock).logAdServicesError(eq(stats));
+ verify(mStatsdLoggerMock).logAdServicesError(stats);
}
Exception createSQLiteException(String className, String methodName, int lineNumber) {
@@ -200,17 +203,11 @@ public final class AdServicesErrorLoggerImplTest extends AdServicesMockitoTestCa
return exception;
}
- Exception createSQLiteExceptionwith3StackTraceElements(
- String className, String methodName, int lineNumber) {
- StackTraceElement[] stackTraceElements =
- new StackTraceElement[] {
- new StackTraceElement("AdServicesErrorLoggerImpl", "logError", "file", 4),
- new StackTraceElement("ErrorLogUtil", "e", "file", 4),
- new StackTraceElement(className, methodName, "file", lineNumber)
- };
+ private void mockAdServicesErrorLogging(boolean enabled) {
+ when(mFlags.getAdServicesErrorLoggingEnabled()).thenReturn(enabled);
+ }
- Exception exception = new SQLiteException();
- exception.setStackTrace(stackTraceElements);
- return exception;
+ private void mockErrorCodeLoggingDenyList(ImmutableList<Integer> errorCodeLoggingDenyList) {
+ when(mFlags.getErrorCodeLoggingDenyList()).thenReturn(errorCodeLoggingDenyList);
}
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/customaudience/DBCustomAudienceBackgroundFetchDataTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/customaudience/DBCustomAudienceBackgroundFetchDataTest.java
index e9574eca6..a078f13c0 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/customaudience/DBCustomAudienceBackgroundFetchDataTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/customaudience/DBCustomAudienceBackgroundFetchDataTest.java
@@ -26,26 +26,21 @@ import static org.junit.Assert.assertThrows;
import android.adservices.common.CommonFixture;
import android.adservices.customaudience.CustomAudienceFixture;
+import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
import com.android.adservices.customaudience.DBCustomAudienceBackgroundFetchDataFixture;
import com.android.adservices.service.Flags;
import com.android.adservices.service.FlagsFactory;
-import com.android.adservices.service.PhFlagsFixture;
import com.android.adservices.service.customaudience.BackgroundFetchRunner;
import com.android.adservices.service.customaudience.CustomAudienceUpdatableData;
import com.android.adservices.service.customaudience.CustomAudienceUpdatableDataFixture;
-import com.android.modules.utils.testing.TestableDeviceConfig;
+import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic;
-import org.json.JSONException;
-import org.junit.Rule;
import org.junit.Test;
import java.time.Instant;
-public class DBCustomAudienceBackgroundFetchDataTest {
- // This rule is used for configuring P/H flags
- @Rule
- public final TestableDeviceConfig.TestableDeviceConfigRule mDeviceConfigRule =
- new TestableDeviceConfig.TestableDeviceConfigRule();
+public final class DBCustomAudienceBackgroundFetchDataTest
+ extends AdServicesExtendedMockitoTestCase {
@Test
public void testBuildFetchDataSuccess() {
@@ -179,22 +174,28 @@ public class DBCustomAudienceBackgroundFetchDataTest {
@Test
public void testComputeNextEligibleUpdateTimeWithPhFlags() {
- long configuredBaseIntervalS = 100L;
- PhFlagsFixture.configureFledgeBackgroundFetchEligibleUpdateBaseIntervalS(
- configuredBaseIntervalS);
+ Flags flags = FlagsFactory.getFlagsForTest();
+ long configuredBaseIntervalS = flags.getFledgeBackgroundFetchEligibleUpdateBaseIntervalS();
Instant expectedEligibleUpdateTime =
CommonFixture.FIXED_NOW.plusSeconds(configuredBaseIntervalS);
Instant actualEligibleUpdateTime =
DBCustomAudienceBackgroundFetchData
.computeNextEligibleUpdateTimeAfterSuccessfulUpdate(
- CommonFixture.FIXED_NOW);
+ CommonFixture.FIXED_NOW, flags);
assertEquals(expectedEligibleUpdateTime, actualEligibleUpdateTime);
}
@Test
- public void testCopyWithFullSuccessfulUpdatableDataResetsFailureCounts() throws JSONException {
+ @SpyStatic(FlagsFactory.class)
+ public void testCopyWithFullSuccessfulUpdatableDataResetsFailureCounts() throws Exception {
+ // NOTE: copyWithUpdatableData() will eventually call the
+ // computeNextEligibleUpdateTimeAfterSuccessfulUpdate() method that calls
+ // FlagsFactory.getInstance(), so we need to mock that method (otherwise it would call
+ // DeviceConfig and fail due to lack of permissions)
+ extendedMockito.mockGetFlags(FlagsFactory.getFlagsForTest());
+
DBCustomAudienceBackgroundFetchData originalFetchData =
DBCustomAudienceBackgroundFetchDataFixture.getValidBuilderByBuyer(
CommonFixture.VALID_BUYER_1)
@@ -206,8 +207,7 @@ public class DBCustomAudienceBackgroundFetchDataTest {
Instant attemptedUpdateTime = CommonFixture.FIXED_NOW.plusSeconds(10);
Instant expectedEligibleUpdateTime =
DBCustomAudienceBackgroundFetchData
- .computeNextEligibleUpdateTimeAfterSuccessfulUpdate(
- attemptedUpdateTime, FlagsFactory.getFlagsForTest());
+ .computeNextEligibleUpdateTimeAfterSuccessfulUpdate(attemptedUpdateTime);
CustomAudienceUpdatableData updatableData =
CustomAudienceUpdatableDataFixture.getValidBuilderFullSuccessfulResponse()
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/enrollment/EnrollmentDaoTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/enrollment/EnrollmentDaoTest.java
index 5c16e32d8..aa0ac3f7c 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/enrollment/EnrollmentDaoTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/enrollment/EnrollmentDaoTest.java
@@ -79,7 +79,7 @@ public class EnrollmentDaoTest {
@Mock private EnrollmentUtil mEnrollmentUtil;
@Mock private SharedDbHelper mMockDbHelper;
- private static final EnrollmentData ENROLLMENT_DATA1 =
+ public static final EnrollmentData ENROLLMENT_DATA1 =
new EnrollmentData.Builder()
.setEnrollmentId("1")
.setCompanyId("1001")
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/AbstractDbIntegrationTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/AbstractDbIntegrationTest.java
index 3cea7026f..b55f82855 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/AbstractDbIntegrationTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/AbstractDbIntegrationTest.java
@@ -666,6 +666,9 @@ public abstract class AbstractDbIntegrationTest {
values.put(
MeasurementTables.AsyncRegistrationContract.PLATFORM_AD_ID,
asyncRegistration.getPlatformAdId());
+ values.put(
+ MeasurementTables.AsyncRegistrationContract.REDIRECT_BEHAVIOR,
+ asyncRegistration.getRedirectBehavior().name());
long rowId =
db.insert(
MeasurementTables.AsyncRegistrationContract.TABLE,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/DbState.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/DbState.java
index 24139fe83..f6c071288 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/DbState.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/DbState.java
@@ -30,6 +30,7 @@ import com.android.adservices.service.measurement.Source;
import com.android.adservices.service.measurement.Trigger;
import com.android.adservices.service.measurement.aggregation.AggregateEncryptionKey;
import com.android.adservices.service.measurement.aggregation.AggregateReport;
+import com.android.adservices.service.measurement.registration.AsyncRedirect;
import com.android.adservices.service.measurement.registration.AsyncRegistration;
import com.android.adservices.service.measurement.reporting.DebugReport;
import com.android.adservices.service.measurement.util.UnsignedLong;
@@ -609,6 +610,8 @@ public class DbState {
.setVerifiedDestination(Uri.parse(aJSON.getString("verifiedDestination")))
.setWebDestination(Uri.parse(aJSON.getString("webDestination")))
.setSourceType(Source.SourceType.values()[aJSON.getInt("sourceType")])
+ .setRedirectBehavior(
+ AsyncRedirect.RedirectBehavior.valueOf(aJSON.getString("redirectBehavior")))
.build();
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDaoTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDaoTest.java
index f12e36b93..fec0f7ce1 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDaoTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDaoTest.java
@@ -4887,44 +4887,6 @@ public class MeasurementDaoTest {
.getCount());
}
- private static AsyncRegistration buildAsyncRegistration(String id) {
-
- return new AsyncRegistration.Builder()
- .setId(id)
- .setOsDestination(Uri.parse("android-app://installed-app-destination"))
- .setRegistrant(INSTALLED_REGISTRANT)
- .setTopOrigin(INSTALLED_REGISTRANT)
- .setAdIdPermission(false)
- .setType(AsyncRegistration.RegistrationType.APP_SOURCE)
- .setRegistrationId(UUID.randomUUID().toString())
- .build();
- }
-
- private static AsyncRegistration buildAsyncRegistrationWithNotDestination(String id) {
- return new AsyncRegistration.Builder()
- .setId(id)
- .setOsDestination(Uri.parse("android-app://not-installed-app-destination"))
- .setRegistrant(INSTALLED_REGISTRANT)
- .setTopOrigin(INSTALLED_REGISTRANT)
- .setAdIdPermission(false)
- .setType(AsyncRegistration.RegistrationType.APP_SOURCE)
- .setRequestTime(Long.MAX_VALUE)
- .setRegistrationId(UUID.randomUUID().toString())
- .build();
- }
-
- private static AsyncRegistration buildAsyncRegistrationWithNotRegistrant(String id) {
- return new AsyncRegistration.Builder()
- .setId(id)
- .setOsDestination(Uri.parse("android-app://installed-app-destination"))
- .setRegistrant(NOT_INSTALLED_REGISTRANT)
- .setTopOrigin(NOT_INSTALLED_REGISTRANT)
- .setAdIdPermission(false)
- .setType(AsyncRegistration.RegistrationType.APP_SOURCE)
- .setRegistrationId(UUID.randomUUID().toString())
- .build();
- }
-
@Test
public void testDeleteDebugReport() {
SQLiteDatabase db = MeasurementDbHelper.getInstance(sContext).safeGetWritableDatabase();
@@ -6163,6 +6125,9 @@ public class MeasurementDaoTest {
assertEquals(
asyncRegistration.getPlatformAdId(), validAsyncRegistration.getPlatformAdId());
assertEquals(asyncRegistration.getPostBody(), validAsyncRegistration.getPostBody());
+ assertEquals(
+ asyncRegistration.getRedirectBehavior(),
+ validAsyncRegistration.getRedirectBehavior());
}
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDbSchemaTrail.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDbSchemaTrail.java
index 526eb9595..35d0321a2 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDbSchemaTrail.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/MeasurementDbSchemaTrail.java
@@ -2036,6 +2036,46 @@ public class MeasurementDbSchemaTrail {
+ " TEXT "
+ ")";
+ public static final String CREATE_TABLE_ASYNC_REGISTRATION_V31 =
+ "CREATE TABLE "
+ + AsyncRegistrationContract.TABLE
+ + " ("
+ + AsyncRegistrationContract.ID
+ + " TEXT PRIMARY KEY NOT NULL, "
+ + AsyncRegistrationContract.REGISTRATION_URI
+ + " TEXT, "
+ + AsyncRegistrationContract.WEB_DESTINATION
+ + " TEXT, "
+ + AsyncRegistrationContract.OS_DESTINATION
+ + " TEXT, "
+ + AsyncRegistrationContract.VERIFIED_DESTINATION
+ + " TEXT, "
+ + AsyncRegistrationContract.TOP_ORIGIN
+ + " TEXT, "
+ + AsyncRegistrationContract.SOURCE_TYPE
+ + " INTEGER, "
+ + AsyncRegistrationContract.REGISTRANT
+ + " TEXT, "
+ + AsyncRegistrationContract.REQUEST_TIME
+ + " INTEGER, "
+ + AsyncRegistrationContract.RETRY_COUNT
+ + " INTEGER, "
+ + AsyncRegistrationContract.TYPE
+ + " INTEGER, "
+ + AsyncRegistrationContract.DEBUG_KEY_ALLOWED
+ + " INTEGER, "
+ + AsyncRegistrationContract.AD_ID_PERMISSION
+ + " INTEGER, "
+ + AsyncRegistrationContract.REGISTRATION_ID
+ + " TEXT NOT NULL,"
+ + AsyncRegistrationContract.PLATFORM_AD_ID
+ + " TEXT, "
+ + AsyncRegistrationContract.REQUEST_POST_BODY
+ + " TEXT, "
+ + AsyncRegistrationContract.REDIRECT_BEHAVIOR
+ + " TEXT "
+ + ")";
+
private static final String CREATE_TABLE_DEBUG_REPORT_V6 =
"CREATE TABLE IF NOT EXISTS "
+ DebugReportContract.TABLE
@@ -2489,6 +2529,12 @@ public class MeasurementDbSchemaTrail {
return createStatements;
}
+ private static Map<String, String> getCreateStatementByTableV31() {
+ Map<String, String> createStatements = new HashMap<>(getCreateStatementByTableV30());
+ createStatements.put(AsyncRegistrationContract.TABLE, CREATE_TABLE_ASYNC_REGISTRATION_V31);
+ return createStatements;
+ }
+
private static Map<String, String> getCreateIndexesV7() {
Map<String, String> createIndexes = new HashMap<>();
createIndexes.putAll(CREATE_INDEXES_V6);
@@ -2595,6 +2641,10 @@ public class MeasurementDbSchemaTrail {
return getCreateIndexesV29();
}
+ private static Map<String, String> getCreateIndexesV31() {
+ return getCreateIndexesV30();
+ }
+
private static final Map<Integer, Collection<String>> CREATE_TABLES_STATEMENTS_BY_VERSION =
new ImmutableMap.Builder<Integer, Collection<String>>()
.put(6, CREATE_STATEMENT_BY_TABLE_V6.values())
@@ -2622,6 +2672,7 @@ public class MeasurementDbSchemaTrail {
.put(28, getCreateStatementByTableV28().values())
.put(29, getCreateStatementByTableV29().values())
.put(30, getCreateStatementByTableV30().values())
+ .put(31, getCreateStatementByTableV31().values())
.build();
private static final Map<Integer, Collection<String>> CREATE_INDEXES_STATEMENTS_BY_VERSION =
@@ -2651,6 +2702,7 @@ public class MeasurementDbSchemaTrail {
.put(28, getCreateIndexesV28().values())
.put(29, getCreateIndexesV29().values())
.put(30, getCreateIndexesV30().values())
+ .put(31, getCreateIndexesV31().values())
.build();
/**
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/ContentValueFixtures.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/ContentValueFixtures.java
index a12ea65f9..0b3893126 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/ContentValueFixtures.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/ContentValueFixtures.java
@@ -536,6 +536,15 @@ public class ContentValueFixtures {
return asyncRegistration;
}
+ /**
+ * Get content values for V31 migration
+ *
+ * @return ContentValues for AsyncRegistration table
+ */
+ public static ContentValues generateAsyncRegistrationContentValuesV31() {
+ return generateAsyncRegistrationContentValuesV24();
+ }
+
public static ContentValues generateSourceContentValuesV1() {
ContentValues source = new ContentValues();
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV30Test.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV30Test.java
index ca859a498..d076d277b 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV30Test.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV30Test.java
@@ -63,7 +63,6 @@ public class MeasurementDbMigratorV30Test extends MeasurementDbMigratorTestBase
MeasurementTables.SourceContract.TABLE,
Set.of(MeasurementTables.SourceContract.ID));
MigrationTestHelper.verifyDataInDb(db, fakeData, new HashMap<>(), columnsToBeSkipped);
- // Check that new columns are initialized with empty string
List<Pair<String, String>> tableAndNewColumnPairs = new ArrayList<>();
tableAndNewColumnPairs.add(
new Pair<>(
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV31Test.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV31Test.java
new file mode 100644
index 000000000..d41fb695b
--- /dev/null
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/measurement/migration/MeasurementDbMigratorV31Test.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 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.data.measurement.migration;
+
+import static com.android.adservices.data.DbTestUtil.getDbHelperForTest;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.android.adservices.data.measurement.MeasurementDbHelper;
+import com.android.adservices.data.measurement.MeasurementTables;
+import com.android.adservices.service.measurement.registration.AsyncRedirect;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MeasurementDbMigratorV31Test extends MeasurementDbMigratorTestBase {
+ @Test
+ public void performMigration_v30ToV31WithData_maintainsDataIntegrity() {
+ // Setup
+ MeasurementDbHelper dbHelper =
+ new MeasurementDbHelper(
+ sContext,
+ MEASUREMENT_DATABASE_NAME_FOR_MIGRATION,
+ 30,
+ getDbHelperForTest());
+ SQLiteDatabase db = dbHelper.getWritableDatabase();
+ Map<String, List<ContentValues>> testData = createFakeDataV30();
+ MigrationTestHelper.populateDb(db, testData);
+
+ // Execution
+ getTestSubject().performMigration(db, 30, 31);
+
+ // Assertion
+ MigrationTestHelper.verifyDataInDb(db, testData);
+
+ String[] columns =
+ new String[] {
+ MeasurementTables.AsyncRegistrationContract.REDIRECT_BEHAVIOR,
+ };
+ try (Cursor cursor =
+ db.query(
+ MeasurementTables.AsyncRegistrationContract.TABLE,
+ columns, /* selection */
+ null, /* selectionArgs */
+ null, /* groupBy */
+ null, /* having */
+ null, /* orderBy */
+ null)) {
+ assertEquals(1, cursor.getCount());
+ while (cursor.moveToNext()) {
+ assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS.name(),
+ cursor.getString(cursor.getColumnIndex(columns[0])));
+ }
+ }
+ }
+
+ private Map<String, List<ContentValues>> createFakeDataV30() {
+ Map<String, List<ContentValues>> tableRowsMap = new LinkedHashMap<>();
+
+ // AsyncRegistration table
+ List<ContentValues> asyncRegistrationRows = new ArrayList<>();
+ ContentValues asyncRegistration =
+ ContentValueFixtures.generateAsyncRegistrationContentValuesV24();
+ asyncRegistration.put(
+ MeasurementTables.AsyncRegistrationContract.ID, UUID.randomUUID().toString());
+ asyncRegistrationRows.add(asyncRegistration);
+ tableRowsMap.put(MeasurementTables.AsyncRegistrationContract.TABLE, asyncRegistrationRows);
+
+ return tableRowsMap;
+ }
+
+ @Override
+ int getTargetVersion() {
+ return 31;
+ }
+
+ @Override
+ AbstractMeasurementDbMigrator getTestSubject() {
+ return new MeasurementDbMigratorV31();
+ }
+}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/DBSignalsUpdateMetadataTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/DBSignalsUpdateMetadataTest.java
new file mode 100644
index 000000000..f18839359
--- /dev/null
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/DBSignalsUpdateMetadataTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 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.data.signals;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThrows;
+
+import android.adservices.common.AdTechIdentifier;
+import android.adservices.common.CommonFixture;
+
+import org.junit.Test;
+
+public class DBSignalsUpdateMetadataTest {
+
+ @Test
+ public void testCreateSignalsUpdateMetadata() {
+ AdTechIdentifier buyer = CommonFixture.VALID_BUYER_1;
+ DBSignalsUpdateMetadata signalsUpdateMetadata =
+ DBSignalsUpdateMetadata.create(buyer, CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI);
+ assertEquals(buyer, signalsUpdateMetadata.getBuyer());
+ assertEquals(
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
+ signalsUpdateMetadata.getLastSignalsUpdatedTime());
+ }
+
+ @Test
+ public void testBuildSignalsUpdateMetadata() {
+ AdTechIdentifier buyer = CommonFixture.VALID_BUYER_1;
+ DBSignalsUpdateMetadata signalsUpdatedTime =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ assertEquals(buyer, signalsUpdatedTime.getBuyer());
+ assertEquals(
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
+ signalsUpdatedTime.getLastSignalsUpdatedTime());
+ }
+
+ @Test
+ public void testNullFails() {
+ assertThrows(
+ IllegalStateException.class,
+ () -> {
+ DBSignalsUpdateMetadata.builder().build();
+ });
+ }
+
+ @Test
+ public void testEquals() {
+ AdTechIdentifier buyer = CommonFixture.VALID_BUYER_1;
+ DBSignalsUpdateMetadata signalsUpdateMetadata1 =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ DBSignalsUpdateMetadata signalsUpdateMetadata2 =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ assertEquals(signalsUpdateMetadata1, signalsUpdateMetadata2);
+ }
+
+ @Test
+ public void testNotEquals() {
+ AdTechIdentifier buyer1 = CommonFixture.VALID_BUYER_1;
+ AdTechIdentifier buyer2 = CommonFixture.VALID_BUYER_2;
+ DBSignalsUpdateMetadata signalsUpdateMetadata1 =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer1)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ DBSignalsUpdateMetadata signalsUpdateMetadata2 =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer2)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ assertNotEquals(signalsUpdateMetadata1, signalsUpdateMetadata2);
+ }
+
+ @Test
+ public void testHashCode() {
+ AdTechIdentifier buyer = CommonFixture.VALID_BUYER_1;
+ DBSignalsUpdateMetadata signalsUpdateMetadata1 =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ DBSignalsUpdateMetadata signalsUpdateMetadata2 =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(buyer)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ assertEquals(signalsUpdateMetadata1.hashCode(), signalsUpdateMetadata2.hashCode());
+ }
+}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/EncoderLogicHandlerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/EncoderLogicHandlerTest.java
index f27a31a7f..98b5af305 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/EncoderLogicHandlerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/EncoderLogicHandlerTest.java
@@ -76,6 +76,8 @@ public class EncoderLogicHandlerTest {
@Mock private AdServicesHttpsClient mAdServicesHttpsClient;
+ @Mock private ProtectedSignalsDao mProtectedSignalsDao;
+
@Captor ArgumentCaptor<DBEncoderLogicMetadata> mDBEncoderLogicArgumentCaptor;
private ListeningExecutorService mExecutorService = MoreExecutors.newDirectExecutorService();
@@ -90,6 +92,7 @@ public class EncoderLogicHandlerTest {
mEncoderPersistenceDao,
mEncoderEndpointsDao,
mEncoderLogicMetadataDao,
+ mProtectedSignalsDao,
mAdServicesHttpsClient,
mExecutorService);
}
@@ -273,6 +276,7 @@ public class EncoderLogicHandlerTest {
verify(mEncoderLogicMetadataDao).deleteEncoder(buyer);
verify(mEncoderPersistenceDao).deleteEncoder(buyer);
verify(mEncoderEndpointsDao).deleteEncoderEndpoint(buyer);
+ verify(mProtectedSignalsDao).deleteSignalsUpdateMetadata(buyer);
}
@Test
@@ -290,6 +294,9 @@ public class EncoderLogicHandlerTest {
verify(mEncoderEndpointsDao).deleteEncoderEndpoint(buyer1);
verify(mEncoderEndpointsDao).deleteEncoderEndpoint(buyer2);
+
+ verify(mProtectedSignalsDao).deleteSignalsUpdateMetadata(buyer1);
+ verify(mProtectedSignalsDao).deleteSignalsUpdateMetadata(buyer2);
}
@SuppressWarnings("FutureReturnValueIgnored")
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDaoTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDaoTest.java
index fbf954608..c7668d4d3 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDaoTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDaoTest.java
@@ -20,7 +20,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -48,6 +50,7 @@ import org.mockito.Mock;
import org.mockito.MockitoSession;
import java.time.Duration;
+import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@@ -176,16 +179,27 @@ public class ProtectedSignalsDaoTest {
public void testInsertAndDelete() {
// Insert two signals
mProtectedSignalsDao.insertAndDelete(
+ BUYER_1,
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
Arrays.asList(DBProtectedSignalFixture.SIGNAL, DBProtectedSignalFixture.SIGNAL),
Collections.emptyList());
// Get all the signals for the test buyer
List<DBProtectedSignal> readResult = mProtectedSignalsDao.getSignalsByBuyer(BUYER_1);
+ assertEquals(
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1).getLastSignalsUpdatedTime());
// Delete one of the signals and insert two more
mProtectedSignalsDao.insertAndDelete(
+ BUYER_1,
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
Arrays.asList(DBProtectedSignalFixture.SIGNAL, DBProtectedSignalFixture.SIGNAL),
readResult.subList(0, 1));
// Check that the deletions and insertion occurred
readResult = mProtectedSignalsDao.getSignalsByBuyer(BUYER_1);
+ assertEquals(
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1).getLastSignalsUpdatedTime());
+
assertEquals(3, readResult.size());
assertNotNull(readResult.get(0).getId());
assertEqualsExceptId(DBProtectedSignalFixture.SIGNAL, readResult.get(0));
@@ -197,17 +211,32 @@ public class ProtectedSignalsDaoTest {
public void testDeleteSignalsBeforeTime() {
// Insert two signals
mProtectedSignalsDao.insertAndDelete(
+ BUYER_1,
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
Arrays.asList(
DBProtectedSignalFixture.SIGNAL,
DBProtectedSignalFixture.LATER_TIME_SIGNAL),
Collections.emptyList());
+ assertEquals(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER_1)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build(),
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
// Delete the older signal
assertEquals(
1,
- mProtectedSignalsDao.deleteSignalsBeforeTime(
+ mProtectedSignalsDao.deleteExpiredSignalsAndUpdateSignalsUpdateMetadata(
DBProtectedSignalFixture.SIGNAL
.getCreationTime()
- .plus(Duration.ofMillis(1))));
+ .plus(Duration.ofMillis(1)),
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI));
+ assertEquals(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER_1)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build(),
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
// Check that the deletions and insertion occurred
List<DBProtectedSignal> readResult = mProtectedSignalsDao.getSignalsByBuyer(BUYER_1);
assertEquals(1, readResult.size());
@@ -226,7 +255,10 @@ public class ProtectedSignalsDaoTest {
DBProtectedSignal signal2 = DBProtectedSignalFixture.getBuilder().setBuyer(BUYER_2).build();
// Insert two signals
mProtectedSignalsDao.insertAndDelete(
- Arrays.asList(signal1, signal2), Collections.emptyList());
+ BUYER_1,
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
+ Arrays.asList(signal1, signal2),
+ Collections.emptyList());
when(mEnrollmentDaoMock.getAllFledgeEnrolledAdTechs())
.thenReturn(new HashSet<>(Arrays.asList(BUYER_1, BUYER_2)));
assertEquals(0, mProtectedSignalsDao.deleteDisallowedBuyerSignals(mEnrollmentDaoMock));
@@ -235,10 +267,17 @@ public class ProtectedSignalsDaoTest {
assertEquals(1, readResult.size());
assertNotNull(readResult.get(0).getId());
assertEqualsExceptId(signal1, readResult.get(0));
+ assertEquals(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER_1)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build(),
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
readResult = mProtectedSignalsDao.getSignalsByBuyer(BUYER_2);
assertEquals(1, readResult.size());
assertNotNull(readResult.get(0).getId());
assertEqualsExceptId(signal2, readResult.get(0));
+ assertNull(mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_2));
}
@Test
@@ -249,10 +288,37 @@ public class ProtectedSignalsDaoTest {
DBProtectedSignalFixture.getBuilder().setBuyer(CommonFixture.VALID_BUYER_2).build();
// Insert two signals
mProtectedSignalsDao.insertAndDelete(
- Arrays.asList(signal1, signal2), Collections.emptyList());
+ BUYER_1,
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
+ List.of(signal1),
+ Collections.emptyList());
+ mProtectedSignalsDao.insertAndDelete(
+ BUYER_2,
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI,
+ List.of(signal2),
+ Collections.emptyList());
+ assertEquals(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER_1)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build(),
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
+ assertEquals(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER_2)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build(),
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_2));
when(mEnrollmentDaoMock.getAllFledgeEnrolledAdTechs())
.thenReturn(Collections.singleton(CommonFixture.VALID_BUYER_1));
assertEquals(1, mProtectedSignalsDao.deleteDisallowedBuyerSignals(mEnrollmentDaoMock));
+ assertEquals(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER_1)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build(),
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
+ assertNull(mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_2));
// Check that the correct deletion occurred
List<DBProtectedSignal> readResult = mProtectedSignalsDao.getSignalsByBuyer(BUYER_1);
assertEquals(1, readResult.size());
@@ -264,8 +330,10 @@ public class ProtectedSignalsDaoTest {
public void testDeleteDisallowedPackageSignalsNoSignals() {
assertEquals(
0,
- mProtectedSignalsDao.deleteAllDisallowedPackageSignals(
- mPackageManagerMock, mFlagsMock));
+ mProtectedSignalsDao.deleteAllDisallowedPackageSignalsAndUpdateSignalUpdateMetadata(
+ mPackageManagerMock,
+ mFlagsMock,
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI));
}
@Test
@@ -292,8 +360,10 @@ public class ProtectedSignalsDaoTest {
assertEquals(2, readResult1.size());
assertEquals(
0,
- mProtectedSignalsDao.deleteAllDisallowedPackageSignals(
- mPackageManagerMock, new FlagsWithAllAppsAllowed()));
+ mProtectedSignalsDao.deleteAllDisallowedPackageSignalsAndUpdateSignalUpdateMetadata(
+ mPackageManagerMock,
+ new FlagsWithAllAppsAllowed(),
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI));
// Check that no deletion occurred
List<DBProtectedSignal> readResult2 = mProtectedSignalsDao.getSignalsByBuyer(BUYER_1);
assertEquals(2, readResult2.size());
@@ -322,13 +392,107 @@ public class ProtectedSignalsDaoTest {
assertEquals(2, readResult1.size());
assertEquals(
1,
- mProtectedSignalsDao.deleteAllDisallowedPackageSignals(
- CONTEXT.getPackageManager(), new FlagsThatAllowOneApp()));
+ mProtectedSignalsDao.deleteAllDisallowedPackageSignalsAndUpdateSignalUpdateMetadata(
+ CONTEXT.getPackageManager(),
+ new FlagsThatAllowOneApp(),
+ CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI));
List<DBProtectedSignal> readResult2 = mProtectedSignalsDao.getSignalsByBuyer(BUYER_1);
assertEquals(1, readResult2.size());
assertEquals(PACKAGE_1, readResult2.get(0).getPackageName());
}
+ @Test
+ public void testPersistMetadata() {
+ assertNull(
+ "Initial state of the table should be empty",
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
+
+ DBSignalsUpdateMetadata signalsUpdateMetadata =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER_1)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ assertEquals(
+ "One entry should have been inserted",
+ 1,
+ mProtectedSignalsDao.persistSignalsUpdateMetadata(signalsUpdateMetadata));
+ }
+
+ @Test
+ public void testDeleteMetadata() {
+ assertNull(
+ "Initial state of the table should be empty",
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
+
+ DBSignalsUpdateMetadata signalsUpdateMetadata =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER_1)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ assertEquals(
+ "One entry should have been inserted",
+ 1,
+ mProtectedSignalsDao.persistSignalsUpdateMetadata(signalsUpdateMetadata));
+
+ mProtectedSignalsDao.deleteSignalsUpdateMetadata(BUYER_1);
+ assertNull(
+ "Metadata should have been deleted",
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
+ }
+
+ @Test
+ public void testQuerySignalsUpdateMetadata() {
+ assertNull(
+ "Initial state of the table should be empty",
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
+
+ DBSignalsUpdateMetadata signalsUpdateMetadata =
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER_1)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ assertEquals(
+ "One entry should have been inserted",
+ 1,
+ mProtectedSignalsDao.persistSignalsUpdateMetadata(signalsUpdateMetadata));
+ DBSignalsUpdateMetadata retrieved = mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1);
+
+ assertEquals(signalsUpdateMetadata.getBuyer(), retrieved.getBuyer());
+ assertEquals(
+ signalsUpdateMetadata.getLastSignalsUpdatedTime(),
+ retrieved.getLastSignalsUpdatedTime());
+ }
+
+ @Test
+ public void testPersistMetadataReplacesExisting() {
+ assertNull(
+ "Initial state of the table should be empty",
+ mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1));
+
+ DBSignalsUpdateMetadata.Builder anBuilder =
+ DBSignalsUpdateMetadata.builder().setBuyer(BUYER_1);
+ DBSignalsUpdateMetadata previous =
+ anBuilder
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI)
+ .build();
+ mProtectedSignalsDao.persistSignalsUpdateMetadata(previous);
+
+ DBSignalsUpdateMetadata retrieved = mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1);
+ assertEquals(previous.getLastSignalsUpdatedTime(), retrieved.getLastSignalsUpdatedTime());
+
+ DBSignalsUpdateMetadata updated =
+ anBuilder
+ .setLastSignalsUpdatedTime(
+ CommonFixture.FIXED_NEXT_ONE_DAY.truncatedTo(ChronoUnit.MILLIS))
+ .build();
+
+ mProtectedSignalsDao.persistSignalsUpdateMetadata(updated);
+ retrieved = mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER_1);
+ assertNotEquals(
+ previous.getLastSignalsUpdatedTime(), retrieved.getLastSignalsUpdatedTime());
+ assertEquals(updated.getLastSignalsUpdatedTime(), retrieved.getLastSignalsUpdatedTime());
+ }
+
private void assertEqualsExceptId(DBProtectedSignal expected, DBProtectedSignal actual) {
assertEquals(expected.getBuyer(), actual.getBuyer());
assertArrayEquals(expected.getKey(), actual.getKey());
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDatabaseMigrationTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDatabaseMigrationTest.java
index 2c668cca7..82fa411ef 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDatabaseMigrationTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/data/signals/ProtectedSignalsDatabaseMigrationTest.java
@@ -57,7 +57,7 @@ public class ProtectedSignalsDatabaseMigrationTest {
assertFalse(tables.contains(DBEncodedPayload.TABLE_NAME));
assertFalse(tables.contains(DBEncoderEndpoint.TABLE_NAME));
}
- // Re-open the database with version 3.
+ // Re-open the database with version 2.
try (SupportSQLiteDatabase db = helper.runMigrationsAndValidate(TEST_DB, 2, true)) {
List<String> tables = listTables(db);
assertTrue(tables.contains(DBProtectedSignal.TABLE_NAME));
@@ -119,4 +119,25 @@ public class ProtectedSignalsDatabaseMigrationTest {
CommonFixture.VALID_BUYER_2.toString(), c.getString(c.getColumnIndex("buyer")));
}
}
+
+ @Test
+ public void testMigration3To4() throws IOException {
+ try (SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, 3)) {
+ List<String> tables = listTables(db);
+ assertTrue(tables.contains(DBProtectedSignal.TABLE_NAME));
+ assertTrue(tables.contains(DBEncoderLogicMetadata.TABLE_NAME));
+ assertTrue(tables.contains(DBEncodedPayload.TABLE_NAME));
+ assertTrue(tables.contains(DBEncoderEndpoint.TABLE_NAME));
+ assertFalse(tables.contains(DBSignalsUpdateMetadata.TABLE_NAME));
+ }
+ // Re-open the database with version 4.
+ try (SupportSQLiteDatabase db = helper.runMigrationsAndValidate(TEST_DB, 4, true)) {
+ List<String> tables = listTables(db);
+ assertTrue(tables.contains(DBProtectedSignal.TABLE_NAME));
+ assertTrue(tables.contains(DBEncoderLogicMetadata.TABLE_NAME));
+ assertTrue(tables.contains(DBEncodedPayload.TABLE_NAME));
+ assertTrue(tables.contains(DBEncoderEndpoint.TABLE_NAME));
+ assertTrue(tables.contains(DBSignalsUpdateMetadata.TABLE_NAME));
+ }
+ }
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/PhFlagsTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/PhFlagsTest.java
index c5e9716b3..f86269555 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/PhFlagsTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/PhFlagsTest.java
@@ -50,17 +50,19 @@ import static com.android.adservices.service.Flags.DEFAULT_ADSERVICES_CONSENT_MI
import static com.android.adservices.service.Flags.DEFAULT_ADSERVICES_ENABLEMENT_CHECK_ENABLED;
import static com.android.adservices.service.Flags.DEFAULT_ADSERVICES_VERSION_MAPPINGS;
import static com.android.adservices.service.Flags.DEFAULT_AD_ID_FETCHER_TIMEOUT_MS;
+import static com.android.adservices.service.Flags.DEFAULT_APPSEARCH_READ_TIMEOUT_MS;
+import static com.android.adservices.service.Flags.DEFAULT_APPSEARCH_WRITE_TIMEOUT_MS;
import static com.android.adservices.service.Flags.DEFAULT_AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS;
import static com.android.adservices.service.Flags.DEFAULT_BACKGROUND_JOB_SAMPLING_LOGGING_RATE;
import static com.android.adservices.service.Flags.DEFAULT_BLOCKED_TOPICS_SOURCE_OF_TRUTH;
import static com.android.adservices.service.Flags.DEFAULT_CLASSIFIER_TYPE;
import static com.android.adservices.service.Flags.DEFAULT_COMPUTE_VERSION_FROM_MAPPINGS_ENABLED;
+import static com.android.adservices.service.Flags.DEFAULT_CONSENT_MANAGER_OTA_DEBUG_MODE;
import static com.android.adservices.service.Flags.DEFAULT_CONSENT_SOURCE_OF_TRUTH;
import static com.android.adservices.service.Flags.DEFAULT_ENABLE_ADEXT_DATA_SERVICE_APIS;
import static com.android.adservices.service.Flags.DEFAULT_ENABLE_ADEXT_SERVICE_DEBUG_PROXY;
import static com.android.adservices.service.Flags.DEFAULT_ENABLE_ADSERVICES_API_ENABLED;
import static com.android.adservices.service.Flags.DEFAULT_ENABLE_AD_SERVICES_SYSTEM_API;
-import static com.android.adservices.service.Flags.DEFAULT_EU_NOTIF_FLOW_CHANGE_ENABLED;
import static com.android.adservices.service.Flags.DEFAULT_MAINLINE_TRAIN_VERSION;
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_ASYNC_REGISTRATION_JOB_TRIGGER_MAX_DELAY_MS;
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_ASYNC_REGISTRATION_JOB_TRIGGER_MIN_DELAY_MS;
@@ -68,7 +70,6 @@ import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_ATTRIBUTI
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_DEBUG_JOIN_KEY_ENROLLMENT_ALLOWLIST;
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_DEBUG_JOIN_KEY_HASH_LIMIT;
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_ENABLE_COARSE_EVENT_REPORT_DESTINATIONS;
-import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS;
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_MAX_AGGREGATE_DEDUPLICATION_KEYS_PER_REGISTRATION;
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_MAX_AGGREGATE_REPORT_UPLOAD_RETRY_WINDOW_MS;
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_MAX_ATTRIBUTIONS_PER_INVOCATION;
@@ -83,9 +84,8 @@ import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_PLATFORM_
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_PLATFORM_DEBUG_AD_ID_MATCHING_LIMIT;
import static com.android.adservices.service.Flags.DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT;
import static com.android.adservices.service.Flags.DEFAULT_NOTIFICATION_DISMISSED_ON_CLICK;
-import static com.android.adservices.service.Flags.DEFAULT_RVC_NOTIFICATION_ENABLED;
+import static com.android.adservices.service.Flags.DEFAULT_RVC_POST_OTA_NOTIFICATION_ENABLED;
import static com.android.adservices.service.Flags.DEFAULT_RVC_POST_OTA_NOTIF_AGE_CHECK;
-import static com.android.adservices.service.Flags.DEFAULT_CONSENT_MANAGER_OTA_DEBUG_MODE;
import static com.android.adservices.service.Flags.DEFAULT_U18_UX_ENABLED;
import static com.android.adservices.service.Flags.DISABLE_FLEDGE_ENROLLMENT_CHECK;
import static com.android.adservices.service.Flags.DISABLE_MEASUREMENT_ENROLLMENT_CHECK;
@@ -283,15 +283,12 @@ import static com.android.adservices.service.Flags.MEASUREMENT_DELETE_EXPIRED_JO
import static com.android.adservices.service.Flags.MEASUREMENT_DELETE_UNINSTALLED_JOB_PERIOD_MS;
import static com.android.adservices.service.Flags.MEASUREMENT_DELETE_UNINSTALLED_JOB_PERSISTED;
import static com.android.adservices.service.Flags.MEASUREMENT_DESTINATION_RATE_LIMIT_WINDOW;
-import static com.android.adservices.service.Flags.MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_AGGREGATABLE_REPORT_PAYLOAD_PADDING;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_API_STATUS_ALLOW_LIST_CHECK;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_APP_PACKAGE_NAME_LOGGING;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_ARA_DEDUPLICATION_ALIGNMENT_V1;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_ARA_PARSING_ALIGNMENT_V1;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_CONFIGURABLE_AGGREGATE_REPORT_DELAY;
-import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_DATASTORE_MANAGER_THROW_DATASTORE_EXCEPTION;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_DEBUG_REPORT;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_DELETE_REPORTS_ON_UNRECOVERABLE_EXCEPTION;
@@ -299,6 +296,7 @@ import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_DESTINATIO
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_LOOKBACK_WINDOW_FILTER;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_MAX_AGGREGATE_REPORTS_PER_SOURCE;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_PREINSTALL_CHECK;
+import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_REPORTING_JOBS_THROW_JSON_EXCEPTION;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_REPORTING_JOBS_THROW_UNACCOUNTED_EXCEPTION;
import static com.android.adservices.service.Flags.MEASUREMENT_ENABLE_SCOPED_ATTRIBUTION_RATE_LIMIT;
@@ -323,7 +321,6 @@ import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_FALLBACK_RE
import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_FALLBACK_REPORTING_JOB_REQUIRED_BATTERY_NOT_LOW;
import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_FALLBACK_REPORTING_JOB_REQUIRED_NETWORK_TYPE;
import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_MAIN_REPORTING_JOB_PERIOD_MS;
-import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_NOISE_PROBABILITY;
import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_REPORTING_JOB_PERSISTED;
import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_REPORTING_JOB_REQUIRED_BATTERY_NOT_LOW;
import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_REPORTING_JOB_REQUIRED_NETWORK_TYPE;
@@ -338,10 +335,6 @@ import static com.android.adservices.service.Flags.MEASUREMENT_FLEX_API_MAX_INFO
import static com.android.adservices.service.Flags.MEASUREMENT_FLEX_API_MAX_INFORMATION_GAIN_NAVIGATION;
import static com.android.adservices.service.Flags.MEASUREMENT_FLEX_API_MAX_TRIGGER_DATA_CARDINALITY;
import static com.android.adservices.service.Flags.MEASUREMENT_FLEX_LITE_API_ENABLED;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY;
import static com.android.adservices.service.Flags.MEASUREMENT_IS_CLICK_VERIFICATION_ENABLED;
import static com.android.adservices.service.Flags.MEASUREMENT_IS_CLICK_VERIFIED_BY_INPUT_EVENT;
import static com.android.adservices.service.Flags.MEASUREMENT_JOB_AGGREGATE_FALLBACK_REPORTING_KILL_SWITCH;
@@ -386,7 +379,6 @@ import static com.android.adservices.service.Flags.MEASUREMENT_MIN_INSTALL_ATTRI
import static com.android.adservices.service.Flags.MEASUREMENT_MIN_POST_INSTALL_EXCLUSIVITY_WINDOW;
import static com.android.adservices.service.Flags.MEASUREMENT_MIN_REPORTING_ORIGIN_UPDATE_WINDOW;
import static com.android.adservices.service.Flags.MEASUREMENT_MIN_REPORTING_REGISTER_SOURCE_EXPIRATION_IN_SECONDS;
-import static com.android.adservices.service.Flags.MEASUREMENT_NAVIGATION_NOISE_PROBABILITY;
import static com.android.adservices.service.Flags.MEASUREMENT_NETWORK_CONNECT_TIMEOUT_MS;
import static com.android.adservices.service.Flags.MEASUREMENT_NETWORK_READ_TIMEOUT_MS;
import static com.android.adservices.service.Flags.MEASUREMENT_RATE_LIMIT_WINDOW_MILLISECONDS;
@@ -442,6 +434,7 @@ import static com.android.adservices.service.Flags.TOPICS_NUMBER_OF_TOP_TOPICS;
import static com.android.adservices.service.Flags.TOPICS_ON_DEVICE_CLASSIFIER_KILL_SWITCH;
import static com.android.adservices.service.Flags.TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC;
import static com.android.adservices.service.Flags.TOPICS_PRIVACY_BUDGET_FOR_TOPIC_ID_DISTRIBUTION;
+import static com.android.adservices.service.Flags.TOPICS_TEST_ENCRYPTION_PUBLIC_KEY;
import static com.android.adservices.service.Flags.UI_DIALOG_FRAGMENT;
import static com.android.adservices.service.Flags.UI_EEA_COUNTRIES;
import static com.android.adservices.service.Flags.UI_FEATURE_TYPE_LOGGING_ENABLED;
@@ -474,8 +467,8 @@ import static com.android.adservices.service.FlagsConstants.KEY_COBALT_LOGGING_E
import static com.android.adservices.service.FlagsConstants.KEY_COBALT_LOGGING_JOB_PERIOD_MS;
import static com.android.adservices.service.FlagsConstants.KEY_COBALT_UPLOAD_SERVICE_UNBIND_DELAY_MS;
import static com.android.adservices.service.FlagsConstants.KEY_COMPAT_LOGGING_KILL_SWITCH;
-import static com.android.adservices.service.FlagsConstants.KEY_CONSENT_MANAGER_OTA_DEBUG_MODE;
import static com.android.adservices.service.FlagsConstants.KEY_CONSENT_ALREADY_INTERACTED_FIX_ENABLE;
+import static com.android.adservices.service.FlagsConstants.KEY_CONSENT_MANAGER_OTA_DEBUG_MODE;
import static com.android.adservices.service.FlagsConstants.KEY_CONSENT_NOTIFICATION_ACTIVITY_DEBUG_MODE;
import static com.android.adservices.service.FlagsConstants.KEY_CONSENT_NOTIFICATION_RESET_TOKEN;
import static com.android.adservices.service.FlagsConstants.KEY_CONSENT_NOTIFIED_DEBUG_MODE;
@@ -513,7 +506,6 @@ import static com.android.adservices.service.FlagsConstants.KEY_ENROLLMENT_BLOCK
import static com.android.adservices.service.FlagsConstants.KEY_ENROLLMENT_ENABLE_LIMITED_LOGGING;
import static com.android.adservices.service.FlagsConstants.KEY_ENROLLMENT_MDD_RECORD_DELETION_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_ERROR_CODE_LOGGING_DENY_LIST;
-import static com.android.adservices.service.FlagsConstants.KEY_EU_NOTIF_FLOW_CHANGE_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_AD_COUNTER_HISTOGRAM_ABSOLUTE_MAX_PER_BUYER_EVENT_COUNT;
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_AD_COUNTER_HISTOGRAM_ABSOLUTE_MAX_TOTAL_EVENT_COUNT;
import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_AD_COUNTER_HISTOGRAM_LOWER_MAX_PER_BUYER_EVENT_COUNT;
@@ -676,8 +668,6 @@ import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_DELE
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_DELETE_UNINSTALLED_JOB_PERIOD_MS;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_DELETE_UNINSTALLED_JOB_PERSISTED;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_DESTINATION_RATE_LIMIT_WINDOW;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_AGGREGATABLE_REPORT_PAYLOAD_PADDING;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_API_STATUS_ALLOW_LIST_CHECK;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_APP_PACKAGE_NAME_LOGGING;
@@ -685,7 +675,6 @@ import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENAB
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_ARA_PARSING_ALIGNMENT_V1;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_COARSE_EVENT_REPORT_DESTINATIONS;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_CONFIGURABLE_AGGREGATE_REPORT_DELAY;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_DATASTORE_MANAGER_THROW_DATASTORE_EXCEPTION;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_DEBUG_REPORT;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_DELETE_REPORTS_ON_UNRECOVERABLE_EXCEPTION;
@@ -693,6 +682,7 @@ import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENAB
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_LOOKBACK_WINDOW_FILTER;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_MAX_AGGREGATE_REPORTS_PER_SOURCE;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_PREINSTALL_CHECK;
+import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_REPORTING_JOBS_THROW_CRYPTO_EXCEPTION;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_REPORTING_JOBS_THROW_JSON_EXCEPTION;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_REPORTING_JOBS_THROW_UNACCOUNTED_EXCEPTION;
@@ -703,7 +693,6 @@ import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENAB
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_SOURCE_DEBUG_REPORT;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_TRIGGER_DATA_MATCHING;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_TRIGGER_DEBUG_REPORT;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_XNA;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENFORCE_ENROLLMENT_ORIGIN_MATCH;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENFORCE_FOREGROUND_STATUS_DELETE_REGISTRATIONS;
@@ -718,7 +707,6 @@ import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_EVEN
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_EVENT_FALLBACK_REPORTING_JOB_REQUIRED_BATTERY_NOT_LOW;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_EVENT_FALLBACK_REPORTING_JOB_REQUIRED_NETWORK_TYPE;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_EVENT_MAIN_REPORTING_JOB_PERIOD_MS;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_EVENT_NOISE_PROBABILITY;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_EVENT_REPORTING_JOB_PERSISTED;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_EVENT_REPORTING_JOB_REQUIRED_BATTERY_NOT_LOW;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_EVENT_REPORTING_JOB_REQUIRED_NETWORK_TYPE;
@@ -733,10 +721,6 @@ import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_FLEX
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_FLEX_API_MAX_INFORMATION_GAIN_NAVIGATION;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_FLEX_API_MAX_TRIGGER_DATA_CARDINALITY;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_FLEX_LITE_API_ENABLED;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_IS_CLICK_VERIFICATION_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_IS_CLICK_VERIFIED_BY_INPUT_EVENT;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_JOB_AGGREGATE_FALLBACK_REPORTING_KILL_SWITCH;
@@ -791,7 +775,6 @@ import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_MIN_
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_MIN_POST_INSTALL_EXCLUSIVITY_WINDOW;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_MIN_REPORTING_ORIGIN_UPDATE_WINDOW;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_MIN_REPORTING_REGISTER_SOURCE_EXPIRATION_IN_SECONDS;
-import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_NAVIGATION_NOISE_PROBABILITY;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_NETWORK_CONNECT_TIMEOUT_MS;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_NETWORK_READ_TIMEOUT_MS;
import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_RATE_LIMIT_WINDOW_MILLISECONDS;
@@ -828,7 +811,7 @@ import static com.android.adservices.service.FlagsConstants.KEY_PROTECTED_SIGNAL
import static com.android.adservices.service.FlagsConstants.KEY_PROTECTED_SIGNALS_PERIODIC_ENCODING_JOB_PERIOD_MS;
import static com.android.adservices.service.FlagsConstants.KEY_PROTECTED_SIGNALS_SERVICE_KILL_SWITCH;
import static com.android.adservices.service.FlagsConstants.KEY_RECORD_MANUAL_INTERACTION_ENABLED;
-import static com.android.adservices.service.FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED;
+import static com.android.adservices.service.FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_RVC_POST_OTA_NOTIF_AGE_CHECK;
import static com.android.adservices.service.FlagsConstants.KEY_RVC_UX_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_SDK_REQUEST_PERMITS_PER_SECOND;
@@ -847,6 +830,7 @@ import static com.android.adservices.service.FlagsConstants.KEY_TOPICS_NUMBER_OF
import static com.android.adservices.service.FlagsConstants.KEY_TOPICS_ON_DEVICE_CLASSIFIER_KILL_SWITCH;
import static com.android.adservices.service.FlagsConstants.KEY_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC;
import static com.android.adservices.service.FlagsConstants.KEY_TOPICS_PRIVACY_BUDGET_FOR_TOPIC_ID_DISTRIBUTION;
+import static com.android.adservices.service.FlagsConstants.KEY_TOPICS_TEST_ENCRYPTION_PUBLIC_KEY;
import static com.android.adservices.service.FlagsConstants.KEY_U18_UX_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_UI_DIALOG_FRAGMENT_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_UI_EEA_COUNTRIES;
@@ -854,7 +838,6 @@ import static com.android.adservices.service.FlagsConstants.KEY_UI_FEATURE_TYPE_
import static com.android.adservices.service.FlagsConstants.KEY_UI_OTA_STRINGS_MANIFEST_FILE_URL;
import static com.android.adservices.service.FlagsConstants.KEY_UI_TOGGLE_SPEED_BUMP_ENABLED;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -1125,6 +1108,23 @@ public class PhFlagsTest {
}
@Test
+ public void testGetTopicsTestEncryptionPublicKey() {
+ assertThat(mPhFlags.getTopicsTestEncryptionPublicKey())
+ .isEqualTo(TOPICS_TEST_ENCRYPTION_PUBLIC_KEY);
+ assertThat(mPhFlags.getTopicsTestEncryptionPublicKey()).isEmpty();
+
+ // Now overriding with the value from PH.
+ String phOverridingValue = "NewKey";
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_ADSERVICES,
+ KEY_TOPICS_TEST_ENCRYPTION_PUBLIC_KEY,
+ phOverridingValue,
+ /* makeDefault */ false);
+
+ assertThat(mPhFlags.getTopicsTestEncryptionPublicKey()).isEqualTo(phOverridingValue);
+ }
+
+ @Test
public void testClassifierType() {
// Without any overriding, the value is the hard coded constant.
assertThat(mPhFlags.getClassifierType()).isEqualTo(DEFAULT_CLASSIFIER_TYPE);
@@ -5284,24 +5284,6 @@ public class PhFlagsTest {
}
@Test
- public void testGetMeasurementEnableConfigurableEventReportingWindows() {
- // Without any overriding, the value is the hard coded constant.
- assertThat(mPhFlags.getMeasurementEnableConfigurableEventReportingWindows())
- .isEqualTo(MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS);
-
- boolean phOverridingValue = !MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS;
-
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_ENABLE_CONFIGURABLE_EVENT_REPORTING_WINDOWS,
- Boolean.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementEnableConfigurableEventReportingWindows())
- .isEqualTo(phOverridingValue);
- }
-
- @Test
public void testGetMeasurementEventReportsVtcEarlyReportingWindows() {
// Without any overriding, the value is the hard coded constant.
assertThat(mPhFlags.getMeasurementEventReportsVtcEarlyReportingWindows())
@@ -7351,22 +7333,6 @@ public class PhFlagsTest {
}
@Test
- public void testEuNotifFlowChangeEnabled() {
- // Without any overriding, the value is the hard coded constant.
- assertThat(mPhFlags.getEuNotifFlowChangeEnabled())
- .isEqualTo(DEFAULT_EU_NOTIF_FLOW_CHANGE_ENABLED);
-
- boolean phOverridingValue = !DEFAULT_EU_NOTIF_FLOW_CHANGE_ENABLED;
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_EU_NOTIF_FLOW_CHANGE_ENABLED,
- Boolean.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getEuNotifFlowChangeEnabled()).isEqualTo(phOverridingValue);
- }
-
- @Test
public void testGetRecordManualInteractionEnabled() {
// Without any overriding, the value is the hard coded constant.
assertThat(mPhFlags.getRecordManualInteractionEnabled())
@@ -7677,7 +7643,8 @@ public class PhFlagsTest {
boolean adServicesSystemApi, boolean phOverridingValue, boolean expected) {
// Without any overriding, the value is the hard coded constant.
- assertThat(mPhFlags.getEnableRvcNotification()).isEqualTo(DEFAULT_RVC_NOTIFICATION_ENABLED);
+ assertThat(mPhFlags.getEnableRvcPostOtaNotification())
+ .isEqualTo(DEFAULT_RVC_POST_OTA_NOTIFICATION_ENABLED);
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_ADSERVICES,
@@ -7686,11 +7653,11 @@ public class PhFlagsTest {
/* makeDefault */ false);
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_RVC_NOTIFICATION_ENABLED,
+ KEY_RVC_POST_OTA_NOTIFICATION_ENABLED,
Boolean.toString(phOverridingValue),
/* makeDefault */ false);
- assertThat(mPhFlags.getEnableRvcNotification()).isEqualTo(expected);
+ assertThat(mPhFlags.getEnableRvcPostOtaNotification()).isEqualTo(expected);
}
@Test
@@ -7919,144 +7886,6 @@ public class PhFlagsTest {
}
@Test
- public void testGetMeasurementInstallAttrDualDestinationEventNoiseProbability() {
- assertThat(mPhFlags.getMeasurementInstallAttrDualDestinationEventNoiseProbability())
- .isEqualTo(MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY);
-
- // Now overriding with the value from PH.
- float phOverridingValue =
- MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY + .0001f;
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY,
- Float.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementInstallAttrDualDestinationEventNoiseProbability())
- .isEqualTo(phOverridingValue);
- }
-
- @Test
- public void testGetMeasurementDualDestinationNavigationNoiseProbability() {
- assertThat(mPhFlags.getMeasurementDualDestinationNavigationNoiseProbability())
- .isEqualTo(MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY);
-
- // Now overriding with the value from PH.
- float phOverridingValue =
- MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY + .0001f;
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY,
- Float.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementDualDestinationNavigationNoiseProbability())
- .isEqualTo(phOverridingValue);
- }
-
- @Test
- public void testGetMeasurementInstallAttrDualDestinationNavigationNoiseProbability() {
- assertThat(mPhFlags.getMeasurementInstallAttrDualDestinationNavigationNoiseProbability())
- .isEqualTo(MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY);
-
- // Now overriding with the value from PH.
- float phOverridingValue =
- MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY + .0001f;
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY,
- Float.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementInstallAttrDualDestinationNavigationNoiseProbability())
- .isEqualTo(phOverridingValue);
- }
-
- @Test
- public void testGetMeasurementDualDestinationEventNoiseProbability() {
- assertThat(mPhFlags.getMeasurementDualDestinationEventNoiseProbability())
- .isEqualTo(MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY);
-
- // Now overriding with the value from PH.
- float phOverridingValue = MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY + .0001f;
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY,
- Float.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementDualDestinationEventNoiseProbability())
- .isEqualTo(phOverridingValue);
- }
-
- @Test
- public void testGetMeasurementInstallAttrEventNoiseProbability() {
- assertThat(mPhFlags.getMeasurementInstallAttrEventNoiseProbability())
- .isEqualTo(MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY);
-
- // Now overriding with the value from PH.
- float phOverridingValue = MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY + .0001f;
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY,
- Float.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementInstallAttrEventNoiseProbability())
- .isEqualTo(phOverridingValue);
- }
-
- @Test
- public void testGetMeasurementInstallAttrNavigationNoiseProbability() {
- assertThat(mPhFlags.getMeasurementInstallAttrNavigationNoiseProbability())
- .isEqualTo(MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY);
-
- // Now overriding with the value from PH.
- float phOverridingValue = MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY + .0001f;
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY,
- Float.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementInstallAttrNavigationNoiseProbability())
- .isEqualTo(phOverridingValue);
- }
-
- @Test
- public void testGetMeasurementEventNoiseProbability() {
- assertThat(mPhFlags.getMeasurementEventNoiseProbability())
- .isEqualTo(MEASUREMENT_EVENT_NOISE_PROBABILITY);
-
- // Now overriding with the value from PH.
- float phOverridingValue = MEASUREMENT_EVENT_NOISE_PROBABILITY + .0001f;
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_EVENT_NOISE_PROBABILITY,
- Float.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementEventNoiseProbability()).isEqualTo(phOverridingValue);
- }
-
- @Test
- public void testGetMeasurementNavigationNoiseProbability() {
- assertThat(mPhFlags.getMeasurementNavigationNoiseProbability())
- .isEqualTo(MEASUREMENT_NAVIGATION_NOISE_PROBABILITY);
-
- // Now overriding with the value from PH.
- float phOverridingValue = MEASUREMENT_NAVIGATION_NOISE_PROBABILITY + .0001f;
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_NAVIGATION_NOISE_PROBABILITY,
- Float.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementNavigationNoiseProbability())
- .isEqualTo(phOverridingValue);
- }
-
- @Test
public void testGetMeasurementEnablePreinstallCheck() {
// The priority of applying the flag values: PH (DeviceConfig) and then hard-coded value.
assertThat(mPhFlags.getMeasurementEnablePreinstallCheck())
@@ -8182,24 +8011,6 @@ public class PhFlagsTest {
}
@Test
- public void testGetMeasurementEnableVtcConfigurableMaxEventReports() {
- // Without any overriding, the value is the hard coded constant.
- assertThat(mPhFlags.getMeasurementEnableVtcConfigurableMaxEventReports())
- .isEqualTo(DEFAULT_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS);
-
- boolean phOverridingValue = !DEFAULT_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS;
-
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- KEY_MEASUREMENT_ENABLE_VTC_CONFIGURABLE_MAX_EVENT_REPORTS,
- Boolean.toString(phOverridingValue),
- /* makeDefault */ false);
-
- assertThat(mPhFlags.getMeasurementEnableVtcConfigurableMaxEventReports())
- .isEqualTo(phOverridingValue);
- }
-
- @Test
public void testGetMeasurementVtcConfigurableMaxEventReportsCount() {
// Without any overriding, the value is the hard coded constant.
assertThat(mPhFlags.getMeasurementVtcConfigurableMaxEventReportsCount())
@@ -9710,6 +9521,22 @@ public class PhFlagsTest {
}
@Test
+ public void testGetMeasurementEnableRedirectToWellKnownPath() {
+ assertThat(mPhFlags.getMeasurementEnableRedirectToWellKnownPath())
+ .isEqualTo(MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH);
+
+ boolean phOverridingValue = !MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH;
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_ADSERVICES,
+ KEY_MEASUREMENT_ENABLE_REDIRECT_TO_WELL_KNOWN_PATH,
+ Boolean.toString(phOverridingValue),
+ /* makeDefault */ false);
+
+ assertThat(mPhFlags.getMeasurementEnableRedirectToWellKnownPath())
+ .isEqualTo(phOverridingValue);
+ }
+
+ @Test
public void testGetMeasurementEnableMaxAggregateReportsPerSource() {
assertThat(mPhFlags.getMeasurementEnableMaxAggregateReportsPerSource())
.isEqualTo(MEASUREMENT_ENABLE_MAX_AGGREGATE_REPORTS_PER_SOURCE);
@@ -10140,6 +9967,37 @@ public class PhFlagsTest {
assertThrows(IllegalArgumentException.class, mPhFlags::getBackgroundJobSamplingLoggingRate);
}
+ @Test
+ public void testGetAppSearchWriteTimeout() {
+ // Without any overriding, the value is the hard coded constant.
+ assertThat(mPhFlags.getAppSearchWriteTimeout())
+ .isEqualTo(DEFAULT_APPSEARCH_WRITE_TIMEOUT_MS);
+
+ int phOverridingValue = DEFAULT_APPSEARCH_WRITE_TIMEOUT_MS + 1000;
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_ADSERVICES,
+ FlagsConstants.KEY_APPSEARCH_WRITE_TIMEOUT_MS,
+ Integer.toString(phOverridingValue),
+ /* makeDefault */ false);
+
+ assertThat(mPhFlags.getAppSearchWriteTimeout()).isEqualTo(phOverridingValue);
+ }
+
+ @Test
+ public void testGetAppSearchReadTimeout() {
+ // Without any overriding, the value is the hard coded constant.
+ assertThat(mPhFlags.getAppSearchReadTimeout()).isEqualTo(DEFAULT_APPSEARCH_READ_TIMEOUT_MS);
+
+ int phOverridingValue = DEFAULT_APPSEARCH_READ_TIMEOUT_MS + 500;
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_ADSERVICES,
+ FlagsConstants.KEY_APPSEARCH_READ_TIMEOUT_MS,
+ Integer.toString(phOverridingValue),
+ /* makeDefault */ false);
+
+ assertThat(mPhFlags.getAppSearchReadTimeout()).isEqualTo(phOverridingValue);
+ }
+
private void overrideBackgroundJobSamplingLoggingRate(int phOverridingValue) {
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_ADSERVICES,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererImplTest.java
index 490e585d4..ef9ba9f17 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererImplTest.java
@@ -92,7 +92,7 @@ public class AdFiltererImplTest {
.build();
private static final SignedContextualAds.Builder CONTEXTUAL_ADS_BUILDER =
- SignedContextualAdsFixture.aSignedContextualAdBuilder()
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder()
.setAdsWithBid(ImmutableList.of(new AdWithBid(AD_DATA, 1.0)))
.setBuyer(CommonFixture.VALID_BUYER_1)
.setDecisionLogicUri(
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererNoOpImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererNoOpImplTest.java
index 7e3e358d9..cc7aed1ef 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererNoOpImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdFiltererNoOpImplTest.java
@@ -48,7 +48,7 @@ public class AdFiltererNoOpImplTest {
AdDataFixture.getValidFilterAdDataBuilderByBuyer(CommonFixture.VALID_BUYER_1, 0);
private static final SignedContextualAds.Builder CONTEXTUAL_ADS_BUILDER =
- SignedContextualAdsFixture.aSignedContextualAdBuilder()
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder()
.setAdsWithBid(ImmutableList.of(new AdWithBid(AD_DATA_BUILDER.build(), 1.0)))
.setBuyer(CommonFixture.VALID_BUYER_1)
.setDecisionLogicUri(
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionConfigValidatorTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionConfigValidatorTest.java
index a66caecaf..074da6b50 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionConfigValidatorTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionConfigValidatorTest.java
@@ -16,8 +16,6 @@
package com.android.adservices.service.adselection;
-import static android.adservices.adselection.SignedContextualAdsFixture.PLACEHOLDER_SIGNATURE;
-
import static com.android.adservices.service.adselection.AdSelectionConfigValidator.DECISION_LOGIC_URI_TYPE;
import static com.android.adservices.service.adselection.AdSelectionConfigValidator.TRUSTED_SCORING_SIGNALS_URI_TYPE;
@@ -351,7 +349,7 @@ public class AdSelectionConfigValidatorTest {
Map<AdTechIdentifier, SignedContextualAds> buyerContextualAds = new HashMap<>();
AdTechIdentifier buyer2 = CommonFixture.VALID_BUYER_2;
SignedContextualAds contextualAds2 =
- SignedContextualAdsFixture.generateSignedContextualAds(
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder(
buyer2, ImmutableList.of(100.0, 200.0))
.setDecisionLogicUri(
CommonFixture.getUri(
@@ -380,7 +378,7 @@ public class AdSelectionConfigValidatorTest {
AdTechIdentifier buyer2 = CommonFixture.VALID_BUYER_2;
ImmutableList<Double> bids = ImmutableList.of(100.0, 200.0);
SignedContextualAds contextualAds2 =
- SignedContextualAdsFixture.generateSignedContextualAds(buyer2, bids)
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder(buyer2, bids)
.setDecisionLogicUri(
CommonFixture.getUri(buyer2, BUYER_BIDDING_LOGIC_URI_PATH))
.setAdsWithBid(
@@ -446,14 +444,9 @@ public class AdSelectionConfigValidatorTest {
Map<AdTechIdentifier, SignedContextualAds> buyerContextualAds = new HashMap<>();
buyerContextualAds.put(
CommonFixture.VALID_BUYER_1,
- new SignedContextualAds.Builder()
- .setBuyer(CommonFixture.VALID_BUYER_1)
- .setDecisionLogicUri(
- CommonFixture.getUri(
- CommonFixture.VALID_BUYER_1,
- SignedContextualAdsFixture.DECISION_LOGIC_FRAGMENT))
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder(
+ CommonFixture.VALID_BUYER_1)
.setAdsWithBid(adsWithBids)
- .setSignature(PLACEHOLDER_SIGNATURE)
.build());
AdSelectionConfig adSelectionConfig =
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionE2ETest.java
index 229eca16b..bbef9eb67 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionE2ETest.java
@@ -28,6 +28,8 @@ import static android.adservices.common.AdServicesStatusUtils.STATUS_UNAUTHORIZE
import static android.adservices.common.AdServicesStatusUtils.STATUS_USER_CONSENT_REVOKED;
import static com.android.adservices.data.adselection.AdSelectionDatabase.DATABASE_NAME;
+import static com.android.adservices.data.encryptionkey.EncryptionKeyDaoTest.ENCRYPTION_KEY1;
+import static com.android.adservices.data.enrollment.EnrollmentDaoTest.ENROLLMENT_DATA1;
import static com.android.adservices.service.PhFlagsFixture.EXTENDED_FLEDGE_AD_SELECTION_BIDDING_TIMEOUT_PER_CA_MS;
import static com.android.adservices.service.PhFlagsFixture.EXTENDED_FLEDGE_AD_SELECTION_FROM_OUTCOMES_OVERALL_TIMEOUT_MS;
import static com.android.adservices.service.PhFlagsFixture.EXTENDED_FLEDGE_AD_SELECTION_OVERALL_TIMEOUT_MS;
@@ -51,6 +53,7 @@ import static com.android.adservices.service.adselection.PrebuiltLogicGenerator.
import static com.android.adservices.service.adselection.PrebuiltLogicGenerator.AD_SELECTION_PREBUILT_SCHEMA;
import static com.android.adservices.service.adselection.PrebuiltLogicGenerator.AD_SELECTION_USE_CASE;
import static com.android.adservices.service.adselection.PrebuiltLogicGenerator.PREBUILT_FEATURE_IS_DISABLED;
+import static com.android.adservices.service.adselection.signature.ProtectedAudienceSignatureManager.PUBLIC_TEST_KEY_STRING;
import static com.android.adservices.service.stats.AdSelectionExecutionLoggerTest.DB_AD_SELECTION_FILE_SIZE;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
@@ -119,12 +122,9 @@ import com.android.adservices.data.adselection.AdSelectionDatabase;
import com.android.adservices.data.adselection.AdSelectionDebugReportDao;
import com.android.adservices.data.adselection.AdSelectionDebugReportingDatabase;
import com.android.adservices.data.adselection.AdSelectionEntryDao;
-import com.android.adservices.data.adselection.AdSelectionServerDatabase;
import com.android.adservices.data.adselection.AppInstallDao;
import com.android.adservices.data.adselection.DBAdSelectionOverride;
import com.android.adservices.data.adselection.DBBuyerDecisionOverride;
-import com.android.adservices.data.adselection.EncryptionContextDao;
-import com.android.adservices.data.adselection.EncryptionKeyDao;
import com.android.adservices.data.adselection.FrequencyCapDao;
import com.android.adservices.data.adselection.SharedStorageDatabase;
import com.android.adservices.data.common.DBAdData;
@@ -133,6 +133,7 @@ import com.android.adservices.data.customaudience.CustomAudienceDatabase;
import com.android.adservices.data.customaudience.DBCustomAudience;
import com.android.adservices.data.customaudience.DBCustomAudienceOverride;
import com.android.adservices.data.customaudience.DBTrustedBiddingData;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.data.signals.EncodedPayloadDao;
import com.android.adservices.data.signals.ProtectedSignalsDatabase;
@@ -151,6 +152,7 @@ import com.android.adservices.service.consent.ConsentManager;
import com.android.adservices.service.devapi.AdSelectionDevOverridesHelper;
import com.android.adservices.service.devapi.DevContext;
import com.android.adservices.service.devapi.DevContextFilter;
+import com.android.adservices.service.encryptionkey.EncryptionKey;
import com.android.adservices.service.exception.FilterException;
import com.android.adservices.service.js.JSScriptEngine;
import com.android.adservices.service.stats.AdServicesLogger;
@@ -636,8 +638,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
private EncodedPayloadDao mEncodedPayloadDao;
private AppInstallDao mAppInstallDao;
private FrequencyCapDao mFrequencyCapDao;
+ private EnrollmentDao mEnrollmentDao;
private EncryptionKeyDao mEncryptionKeyDao;
- private EncryptionContextDao mEncryptionContextDao;
@Spy private AdSelectionEntryDao mAdSelectionEntryDaoSpy;
private AdServicesHttpsClient mAdServicesHttpsClient;
private AdSelectionConfig mAdSelectionConfig;
@@ -655,6 +657,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Before
public void setUp() throws Exception {
+ doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
+
mAdSelectionEntryDaoSpy =
Room.inMemoryDatabaseBuilder(mContext, AdSelectionDatabase.class)
.build()
@@ -667,10 +671,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
Room.inMemoryDatabaseBuilder(mContext, SharedStorageDatabase.class)
.build()
.frequencyCapDao();
- AdSelectionServerDatabase serverDb =
- Room.inMemoryDatabaseBuilder(mContext, AdSelectionServerDatabase.class).build();
- mEncryptionContextDao = serverDb.encryptionContextDao();
- mEncryptionKeyDao = serverDb.encryptionKeyDao();
+ mEncryptionKeyDao = EncryptionKeyDao.getInstance(mContext);
+ mEnrollmentDao = EnrollmentDao.getInstance(mContext);
mAdFilteringFeatureFactory =
new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDao, mFlags);
@@ -711,8 +713,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -867,7 +869,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionSuccess_preV3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -963,8 +964,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -1089,8 +1090,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -1235,8 +1236,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -1377,8 +1378,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -1500,8 +1501,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -1607,7 +1608,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionSuccess_prebuiltScoringLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -1703,7 +1703,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionSuccess_prebuiltFeatureDisabled_failure() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
Flags prebuiltDisabledFlags =
new AdSelectionE2ETestFlags() {
@Override
@@ -1719,8 +1718,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -1818,8 +1817,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -1913,7 +1912,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionSuccess_v3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -2007,8 +2005,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -2131,8 +2129,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -2276,8 +2274,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -2417,8 +2415,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -2539,8 +2537,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -2645,7 +2643,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionSuccess_preV3BiddingLogicWithV3Header_scriptFail()
throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -2714,7 +2711,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelection_getTooHighHeader_failWithError() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -2783,7 +2779,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionWithOverride_getTooHighHeader_failWithError() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -2879,7 +2874,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionContextualAds_Success() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -2905,7 +2899,7 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
.logRunAdSelectionProcessReportedStats(any());
AdSelectionConfig adSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setCustomAudienceBuyers(ImmutableList.of(BUYER_1, BUYER_2, BUYER_3))
.setSeller(mSeller)
.setDecisionLogicUri(
@@ -2976,7 +2970,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@FlakyTest(bugId = 304764127)
@Test
public void testRunAdSelectionContextualAds_UseOverrides_Success() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -3002,7 +2995,7 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
.logRunAdSelectionProcessReportedStats(any());
AdSelectionConfig adSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setCustomAudienceBuyers(ImmutableList.of(BUYER_1, BUYER_2, BUYER_3))
.setSeller(mSeller)
.setDecisionLogicUri(
@@ -3091,8 +3084,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -3152,7 +3145,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionContextualAds_Disabled_Success() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -3178,7 +3170,7 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
.logRunAdSelectionProcessReportedStats(any());
AdSelectionConfig adSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setCustomAudienceBuyers(ImmutableList.of(BUYER_1, BUYER_2, BUYER_3))
.setSeller(mSeller)
.setDecisionLogicUri(
@@ -3230,8 +3222,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -3277,7 +3269,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionOnlyContextualAds_NoBuyers_Success() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -3296,7 +3287,7 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
.logRunAdSelectionProcessReportedStats(any());
AdSelectionConfig adSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setCustomAudienceBuyers(ImmutableList.of())
.setSeller(mSeller)
.setDecisionLogicUri(
@@ -3338,8 +3329,45 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
}
@Test
+ public void testRunAdSelectionOnlyContextualAds_unauthenticatedContextualAdsRemoved_Success()
+ throws Exception {
+ // Logger calls come after the callback is returned
+ CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(1);
+ doAnswer(
+ unusedInvocation -> {
+ runAdSelectionProcessLoggerLatch.countDown();
+ return null;
+ })
+ .when(mAdServicesLoggerMock)
+ .logRunAdSelectionProcessReportedStats(any());
+
+ AdSelectionConfig adSelectionConfig =
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
+ .setCustomAudienceBuyers(ImmutableList.of())
+ .setSeller(mSeller)
+ .setDecisionLogicUri(
+ mMockWebServerRule.uriForPath(SELLER_DECISION_LOGIC_URI_PATH))
+ .setTrustedScoringSignalsUri(
+ mMockWebServerRule.uriForPath(SELLER_TRUSTED_SIGNAL_URI_PATH))
+ .setBuyerSignedContextualAds(createUnauthenticatedContextualAds())
+ .build();
+
+ mMockWebServerRule.startMockWebServer(mDispatcher);
+
+ AdSelectionTestCallback resultsCallback =
+ invokeSelectAds(mAdSelectionService, adSelectionConfig, CALLER_PACKAGE_NAME);
+ runAdSelectionProcessLoggerLatch.await();
+ assertCallbackFailed(resultsCallback);
+ assertTrue(
+ resultsCallback
+ .mFledgeErrorResponse
+ .getErrorMessage()
+ .contains(ERROR_NO_BUYERS_OR_CONTEXTUAL_ADS_AVAILABLE));
+ assertEquals(STATUS_INVALID_ARGUMENT, resultsCallback.mFledgeErrorResponse.getStatusCode());
+ }
+
+ @Test
public void testRunAdSelectionOnlyContextualAds_NoCAs_Success() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -3365,7 +3393,7 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
.logRunAdSelectionProcessReportedStats(any());
AdSelectionConfig adSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setCustomAudienceBuyers(ImmutableList.of(BUYER_1, BUYER_2, BUYER_3))
.setSeller(mSeller)
.setDecisionLogicUri(
@@ -3417,7 +3445,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
@FlakyTest(bugId = 304764127)
public void testRunAdSelectionOnlyContextualAds_NoCAsNoNetworkCall_Success() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -3457,7 +3484,7 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
paramKey,
paramValue));
AdSelectionConfig adSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setCustomAudienceBuyers(Collections.emptyList())
.setSeller(mSeller)
.setDecisionLogicUri(prebuiltUri)
@@ -3508,7 +3535,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
@FlakyTest(bugId = 315521295)
public void testRunAdSelectionNoContextualAds_NoCAs_Failure() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -3534,7 +3560,7 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
.logRunAdSelectionProcessReportedStats(any());
AdSelectionConfig adSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setCustomAudienceBuyers(ImmutableList.of(BUYER_1, BUYER_2, BUYER_3))
.setSeller(mSeller)
.setDecisionLogicUri(
@@ -3577,8 +3603,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionWithRevokedUserConsentSuccess() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
-
doThrow(new FilterException(new ConsentManager.RevokedConsentException()))
.when(mAdSelectionServiceFilter)
.filterRequest(
@@ -3653,7 +3677,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionMultipleCAsSuccess_preV3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -3767,7 +3790,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionMultipleCAsSuccess_v3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -3881,8 +3903,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionMultipleCAsNoCachingSuccess_preV3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
-
MockWebServer server = mMockWebServerRule.startMockWebServer(mDispatcher);
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -3962,8 +3982,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
httpClientWithNoCaching,
mDevContextFilter,
mLightweightExecutorService,
@@ -4002,8 +4022,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
@FlakyTest(bugId = 304764127)
public void testRunAdSelectionMultipleCAsNoCachingSuccess_v3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
-
MockWebServer server = mMockWebServerRule.startMockWebServer(DISPATCHER_V3_BIDDING_LOGIC);
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -4083,8 +4101,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
httpClientWithNoCaching,
mDevContextFilter,
mLightweightExecutorService,
@@ -4122,8 +4140,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionMultipleCAsJSCachedSuccess_preV3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
-
MockWebServer server = mMockWebServerRule.startMockWebServer(mDispatcher);
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -4205,8 +4221,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
httpClientWithCaching,
mDevContextFilter,
mLightweightExecutorService,
@@ -4247,8 +4263,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionMultipleCAsJSCachedSuccess_v3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
-
MockWebServer server = mMockWebServerRule.startMockWebServer(DISPATCHER_V3_BIDDING_LOGIC);
List<Double> bidsForBuyer1 = ImmutableList.of(1.1, 2.2);
List<Double> bidsForBuyer2 = ImmutableList.of(4.5, 6.7, 10.0);
@@ -4330,8 +4344,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
httpClientWithCaching,
mDevContextFilter,
mLightweightExecutorService,
@@ -4373,7 +4387,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
@FlakyTest(bugId = 304764127)
public void testRunAdSelectionSucceedsWithOverride_preV3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -4455,8 +4468,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -4511,7 +4524,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
@FlakyTest(bugId = 304764127)
public void testRunAdSelectionSucceedsWithOverride_v3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -4595,8 +4607,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -4650,7 +4662,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionActiveCAs() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -4743,7 +4754,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionNoCAsActive() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -4926,7 +4936,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionPartialAdsExcludedBidding() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -5034,7 +5043,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionMissingBiddingLogicFailure() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -5140,7 +5148,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionMissingScoringLogicFailure() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -5254,7 +5261,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionErrorFetchingScoringLogicFailure() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -5367,7 +5373,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionPartialMissingBiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -5485,7 +5490,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionPartialNonPositiveScoring() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -5608,7 +5612,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionNonPositiveScoringFailure() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -5728,7 +5731,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionBiddingTimesOutForCA() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -5786,8 +5788,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -5907,7 +5909,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionImposesPerBuyerBiddingTimeout_preV3BiddingLogic()
throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(6);
doAnswer(
@@ -6039,8 +6040,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -6115,8 +6116,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -6177,7 +6178,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@FlakyTest(bugId = 304764127)
@Test
public void testRunAdSelectionImposesPerBuyerBiddingTimeout_v3BiddingLogic() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(6);
doAnswer(
@@ -6309,8 +6309,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -6385,8 +6385,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -6446,7 +6446,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionScoringTimesOut() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -6504,8 +6503,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -6677,7 +6676,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionMissingBiddingSignalsFailure() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(2);
doAnswer(
@@ -6770,7 +6768,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
@FlakyTest(bugId = 315521295)
public void testRunAdSelectionMissingScoringSignalsFailure() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -6872,7 +6869,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionMissingPartialBiddingSignalsSuccess() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
// Logger calls come after the callback is returned
CountDownLatch runAdSelectionProcessLoggerLatch = new CountDownLatch(3);
doAnswer(
@@ -6988,8 +6984,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
@Test
public void testRunAdSelectionFailsWithInvalidPackageName() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
-
String invalidPackageName = CALLER_PACKAGE_NAME + "invalidPackageName";
doThrow(new FilterException(new FledgeAuthorizationFilter.CallerMismatchException()))
@@ -7007,7 +7001,7 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
// Bypass the permission check since it's enforced before the package name check
doNothing()
.when(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
mContext, invalidPackageName, AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS);
// Logger calls come after the callback is returned
@@ -7075,13 +7069,12 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
geq(0));
verify(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
mContext, invalidPackageName, AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS);
}
@Test
public void testRunAdSelectionFailsWhenAppCannotUsePPApi() throws Exception {
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
doThrow(new FilterException(new FledgeAuthorizationFilter.AdTechNotAllowedException()))
.when(mAdSelectionServiceFilter)
.filterRequest(
@@ -7193,8 +7186,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -7327,8 +7320,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -7462,8 +7455,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -7561,8 +7554,6 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
// A null package means WebView is not installed
doReturn(null).when(WebView::getCurrentWebViewPackage);
- doReturn(new AdSelectionE2ETestFlags()).when(FlagsFactory::getFlags);
-
// Shut down any running JSScriptEngine to ensure the new singleton gets picked up
JSScriptEngine.getInstance(mContext, LoggerFactory.getFledgeLogger()).shutdown();
@@ -7575,8 +7566,8 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -7803,6 +7794,21 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
adCost);
}
+ private Map<AdTechIdentifier, SignedContextualAds> createUnauthenticatedContextualAds() {
+ Map<AdTechIdentifier, SignedContextualAds> authenticatedContextualAds =
+ createContextualAds();
+ Map<AdTechIdentifier, SignedContextualAds> unauthenticatedContextualAds = new HashMap<>();
+ byte[] invalidSignatures = new byte[] {1, 2, 3};
+ for (Map.Entry<AdTechIdentifier, SignedContextualAds> buyersBundle :
+ authenticatedContextualAds.entrySet()) {
+ AdTechIdentifier buyer = buyersBundle.getKey();
+ SignedContextualAds ads = buyersBundle.getValue();
+ unauthenticatedContextualAds.put(
+ buyer, ads.cloneToBuilder().setSignature(invalidSignatures).build());
+ }
+ return unauthenticatedContextualAds;
+ }
+
private Map<AdTechIdentifier, SignedContextualAds> createContextualAds() {
Map<AdTechIdentifier, SignedContextualAds> buyerContextualAds = new HashMap<>();
@@ -7813,17 +7819,50 @@ public final class AdSelectionE2ETest extends AdServicesExtendedMockitoTestCase
.uriForPath(BUYER_BIDDING_LOGIC_URI_PATH + BUYER_2)
.getHost());
SignedContextualAds contextualAds2 =
- SignedContextualAdsFixture.generateSignedContextualAds(
- buyer2, ImmutableList.of(100.0, 200.0, 300.0, 400.0, 500.0))
- .setDecisionLogicUri(
- mMockWebServerRule.uriForPath(
- BUYER_BIDDING_LOGIC_URI_PATH + BUYER_2))
- .build();
+ SignedContextualAdsFixture.signContextualAds(
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder(
+ buyer2, ImmutableList.of(100.0, 200.0, 300.0, 400.0, 500.0))
+ .setDecisionLogicUri(
+ mMockWebServerRule.uriForPath(
+ BUYER_BIDDING_LOGIC_URI_PATH + BUYER_2)));
buyerContextualAds.put(buyer2, contextualAds2);
-
+ persistEncryptionKeyInDb(buyerContextualAds);
return buyerContextualAds;
}
+ private void persistEncryptionKeyInDb(
+ Map<AdTechIdentifier, SignedContextualAds> buyerContextualAds) {
+ for (AdTechIdentifier adTech : buyerContextualAds.keySet()) {
+ String enrollmentId = adTech + "-enrollment-id";
+ String sourceRegistration = CommonFixture.getUri(adTech, "/source").toString();
+ String triggerRegistration = CommonFixture.getUri(adTech, "/trigger").toString();
+ String attributionReporting = CommonFixture.getUri(adTech, "/attrReport").toString();
+ String responseBasedRegistration = CommonFixture.getUri(adTech, "/response").toString();
+ String encryptionKeyUrl = CommonFixture.getUri(adTech, "/keys").toString();
+ mEnrollmentDao.insert(
+ ENROLLMENT_DATA1
+ .cloneToBuilder()
+ .setEnrollmentId(enrollmentId)
+ .setAttributionSourceRegistrationUrl(sourceRegistration)
+ .setAttributionTriggerRegistrationUrl(triggerRegistration)
+ .setAttributionReportingUrl(attributionReporting)
+ .setRemarketingResponseBasedRegistrationUrl(responseBasedRegistration)
+ .setEncryptionKeyUrl(encryptionKeyUrl)
+ .build());
+ Uri reportingOriginUrl = CommonFixture.getUri(adTech, "/reportingOriginUrl");
+ mEncryptionKeyDao.insert(
+ ENCRYPTION_KEY1
+ .cloneToBuilder()
+ .setEnrollmentId(enrollmentId)
+ .setKeyType(EncryptionKey.KeyType.SIGNING)
+ .setEncryptionKeyUrl(encryptionKeyUrl)
+ .setProtocolType(EncryptionKey.ProtocolType.ECDSA)
+ .setBody(PUBLIC_TEST_KEY_STRING)
+ .setReportingOrigin(reportingOriginUrl)
+ .build());
+ }
+ }
+
private void verifyErrorMessageIsCorrect(
final String actualErrorMassage, final String expectedErrorReason) {
assertTrue(
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionFromOutcomesE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionFromOutcomesE2ETest.java
index 47e2550af..b82d2b0a2 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionFromOutcomesE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionFromOutcomesE2ETest.java
@@ -76,8 +76,6 @@ import com.android.adservices.data.adselection.AdSelectionServerDatabase;
import com.android.adservices.data.adselection.AppInstallDao;
import com.android.adservices.data.adselection.CustomAudienceSignals;
import com.android.adservices.data.adselection.DBAdSelection;
-import com.android.adservices.data.adselection.EncryptionContextDao;
-import com.android.adservices.data.adselection.EncryptionKeyDao;
import com.android.adservices.data.adselection.FrequencyCapDao;
import com.android.adservices.data.adselection.SharedStorageDatabase;
import com.android.adservices.data.adselection.datahandlers.AdSelectionInitialization;
@@ -86,6 +84,7 @@ import com.android.adservices.data.adselection.datahandlers.WinningCustomAudienc
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.CustomAudienceDatabase;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.data.signals.EncodedPayloadDao;
import com.android.adservices.data.signals.ProtectedSignalsDatabase;
@@ -212,9 +211,9 @@ public class AdSelectionFromOutcomesE2ETest {
private EncodedPayloadDao mEncodedPayloadDao;
private AppInstallDao mAppInstallDao;
private FrequencyCapDao mFrequencyCapDao;
- private EncryptionKeyDao mEncryptionKeyDao;
- private EncryptionContextDao mEncryptionContextDao;
@Spy private AdSelectionEntryDao mAdSelectionEntryDaoSpy;
+ private EnrollmentDao mEnrollmentDao;
+ private EncryptionKeyDao mEncryptionKeyDao;
private AdServicesHttpsClient mAdServicesHttpsClient;
private AdSelectionService mAdSelectionService;
private Dispatcher mDispatcher;
@@ -259,8 +258,8 @@ public class AdSelectionFromOutcomesE2ETest {
mFrequencyCapDao = sharedDb.frequencyCapDao();
AdSelectionServerDatabase serverDb =
Room.inMemoryDatabaseBuilder(mContextSpy, AdSelectionServerDatabase.class).build();
- mEncryptionContextDao = serverDb.encryptionContextDao();
- mEncryptionKeyDao = serverDb.encryptionKeyDao();
+ mEnrollmentDao = EnrollmentDao.getInstance(mContextSpy);
+ mEncryptionKeyDao = EncryptionKeyDao.getInstance(mContextSpy);
mAdFilteringFeatureFactory =
new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDao, mFlags);
mAdServicesHttpsClient =
@@ -280,8 +279,8 @@ public class AdSelectionFromOutcomesE2ETest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -411,8 +410,8 @@ public class AdSelectionFromOutcomesE2ETest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
@@ -468,8 +467,8 @@ public class AdSelectionFromOutcomesE2ETest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilter,
mLightweightExecutorService,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionServiceImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionServiceImplTest.java
index 48cd9327d..b3ceaa5be 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionServiceImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdSelectionServiceImplTest.java
@@ -114,7 +114,6 @@ import com.android.adservices.concurrency.AdServicesExecutors;
import com.android.adservices.data.adselection.AdSelectionDatabase;
import com.android.adservices.data.adselection.AdSelectionDebugReportDao;
import com.android.adservices.data.adselection.AdSelectionEntryDao;
-import com.android.adservices.data.adselection.AdSelectionServerDatabase;
import com.android.adservices.data.adselection.AppInstallDao;
import com.android.adservices.data.adselection.CustomAudienceSignals;
import com.android.adservices.data.adselection.DBAdSelection;
@@ -122,17 +121,18 @@ import com.android.adservices.data.adselection.DBAdSelectionFromOutcomesOverride
import com.android.adservices.data.adselection.DBAdSelectionOverride;
import com.android.adservices.data.adselection.DBBuyerDecisionLogic;
import com.android.adservices.data.adselection.DBReportingComputationInfo;
-import com.android.adservices.data.adselection.EncryptionContextDao;
-import com.android.adservices.data.adselection.EncryptionKeyDao;
import com.android.adservices.data.adselection.FrequencyCapDao;
import com.android.adservices.data.adselection.SharedStorageDatabase;
import com.android.adservices.data.adselection.datahandlers.AdSelectionInitialization;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.CustomAudienceDatabase;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
+import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.data.signals.EncodedPayloadDao;
import com.android.adservices.data.signals.ProtectedSignalsDatabase;
import com.android.adservices.service.Flags;
+import com.android.adservices.service.FlagsFactory;
import com.android.adservices.service.adselection.AppInstallAdvertisersSetterTest.SetAppInstallAdvertisersTestCallback;
import com.android.adservices.service.adselection.encryption.ObliviousHttpEncryptor;
import com.android.adservices.service.common.AdSelectionServiceFilter;
@@ -300,7 +300,7 @@ public class AdSelectionServiceImplTest {
private AppInstallDao mAppInstallDao;
private FrequencyCapDao mFrequencyCapDao;
private EncryptionKeyDao mEncryptionKeyDao;
- private EncryptionContextDao mEncryptionContextDao;
+ private EnrollmentDao mEnrollmentDao;
private AdSelectionConfig.Builder mAdSelectionConfigBuilder;
private Uri mBiddingLogicUri;
private CustomAudienceSignals mCustomAudienceSignals;
@@ -323,13 +323,14 @@ public class AdSelectionServiceImplTest {
.spyStatic(JSScriptEngine.class)
.spyStatic(WebView.class)
.mockStatic(ConsentManager.class)
+ .mockStatic(FlagsFactory.class)
.mockStatic(MeasurementImpl.class)
.mockStatic(AppImportanceFilter.class)
// mAdServicesLoggerMock is not referenced in many tests
.strictness(Strictness.LENIENT)
.initMocks(this)
.startMocking();
-
+ doReturn(mFlags).when(FlagsFactory::getFlags);
mCustomAudienceDao =
Room.inMemoryDatabaseBuilder(CONTEXT, CustomAudienceDatabase.class)
.addTypeConverter(new DBCustomAudience.Converters(true, true))
@@ -354,13 +355,8 @@ public class AdSelectionServiceImplTest {
mAppInstallDao = sharedDb.appInstallDao();
mFrequencyCapDao = sharedDb.frequencyCapDao();
- AdSelectionServerDatabase serverDb =
- Room.inMemoryDatabaseBuilder(
- ApplicationProvider.getApplicationContext(),
- AdSelectionServerDatabase.class)
- .build();
- mEncryptionContextDao = serverDb.encryptionContextDao();
- mEncryptionKeyDao = serverDb.encryptionKeyDao();
+ mEncryptionKeyDao = EncryptionKeyDao.getInstance(CONTEXT);
+ mEnrollmentDao = EnrollmentDao.getInstance(CONTEXT);
mAdFilteringFeatureFactory =
new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDao, mFlags);
@@ -498,8 +494,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -619,8 +615,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -750,8 +746,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -882,8 +878,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1002,8 +998,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1125,8 +1121,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1240,8 +1236,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1341,8 +1337,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1449,8 +1445,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1572,8 +1568,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1693,8 +1689,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1819,8 +1815,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1993,8 +1989,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -2137,8 +2133,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -2299,8 +2295,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -2467,8 +2463,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -2626,8 +2622,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -2774,8 +2770,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -2926,8 +2922,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -3094,8 +3090,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -3269,8 +3265,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -3413,8 +3409,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -3520,8 +3516,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -3626,8 +3622,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -3738,8 +3734,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -3845,8 +3841,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -3947,8 +3943,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4048,8 +4044,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4150,8 +4146,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4272,8 +4268,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4419,8 +4415,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4516,8 +4512,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4578,8 +4574,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4635,8 +4631,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4697,8 +4693,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4770,8 +4766,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4839,8 +4835,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4912,8 +4908,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4986,8 +4982,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5101,8 +5097,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5218,8 +5214,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5331,8 +5327,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5439,8 +5435,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5476,8 +5472,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5527,8 +5523,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5594,8 +5590,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5662,8 +5658,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5721,8 +5717,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5782,8 +5778,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5837,8 +5833,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5896,8 +5892,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -5996,8 +5992,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -6112,8 +6108,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -6230,8 +6226,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -6354,8 +6350,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -6459,8 +6455,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -6565,8 +6561,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -6699,8 +6695,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -6813,8 +6809,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -6929,8 +6925,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7067,8 +7063,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7198,8 +7194,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7314,8 +7310,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7443,8 +7439,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7510,8 +7506,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7575,8 +7571,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7634,8 +7630,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7699,8 +7695,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7776,8 +7772,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7847,8 +7843,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7922,8 +7918,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -7996,8 +7992,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -8119,8 +8115,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -8236,8 +8232,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -8358,8 +8354,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -8498,8 +8494,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -9172,8 +9168,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -9234,8 +9230,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -9277,8 +9273,8 @@ public class AdSelectionServiceImplTest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdsScoreGeneratorImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdsScoreGeneratorImplTest.java
index 7a4088a37..342db92c0 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdsScoreGeneratorImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AdsScoreGeneratorImplTest.java
@@ -817,7 +817,7 @@ public class AdsScoreGeneratorImplTest {
Map<AdTechIdentifier, SignedContextualAds> contextualAdsMap = createContextualAds();
mAdSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setDecisionLogicUri(decisionLogicUri)
.setTrustedScoringSignalsUri(
mMockWebServerRule.uriForPath(mTrustedScoringSignalsPath))
@@ -938,7 +938,7 @@ public class AdsScoreGeneratorImplTest {
Map<AdTechIdentifier, SignedContextualAds> contextualAdsMap = createContextualAds();
mAdSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setDecisionLogicUri(decisionLogicUri)
.setTrustedScoringSignalsUri(
mMockWebServerRule.uriForPath(mTrustedScoringSignalsPath))
@@ -1086,7 +1086,7 @@ public class AdsScoreGeneratorImplTest {
Map<AdTechIdentifier, SignedContextualAds> contextualAdsMap = createContextualAds();
mAdSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setDecisionLogicUri(decisionLogicUri)
.setTrustedScoringSignalsUri(
mMockWebServerRule.uriForPath(mTrustedScoringSignalsPath))
@@ -1257,7 +1257,7 @@ public class AdsScoreGeneratorImplTest {
Map<AdTechIdentifier, SignedContextualAds> contextualAdsMap = createContextualAds();
mAdSelectionConfig =
- AdSelectionConfigFixture.anAdSelectionConfigWithContextualAdsBuilder()
+ AdSelectionConfigFixture.anAdSelectionConfigWithSignedContextualAdsBuilder()
.setDecisionLogicUri(decisionLogicUri)
.setTrustedScoringSignalsUri(
mMockWebServerRule.uriForPath(mTrustedScoringSignalsPath))
@@ -1904,13 +1904,13 @@ public class AdsScoreGeneratorImplTest {
AdTechIdentifier buyer1 = BUYER_1;
SignedContextualAds contextualAds1 =
- SignedContextualAdsFixture.generateSignedContextualAds(
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder(
buyer1, ImmutableList.of(100.0, 200.0, 300.0))
.build();
AdTechIdentifier buyer2 = CommonFixture.VALID_BUYER_2;
SignedContextualAds contextualAds2 =
- SignedContextualAdsFixture.generateSignedContextualAds(
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder(
buyer2, ImmutableList.of(400.0, 500.0))
.build();
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AuctionServerE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AuctionServerE2ETest.java
index 8a36e3ee4..f29355fda 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AuctionServerE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/AuctionServerE2ETest.java
@@ -104,6 +104,7 @@ import com.android.adservices.data.common.DBAdData;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.CustomAudienceDatabase;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.data.signals.EncodedPayloadDao;
import com.android.adservices.data.signals.ProtectedSignalsDatabase;
import com.android.adservices.service.Flags;
@@ -254,7 +255,9 @@ public class AuctionServerE2ETest {
private AdSelectionEntryDao mAdSelectionEntryDao;
private AppInstallDao mAppInstallDao;
private FrequencyCapDao mFrequencyCapDaoSpy;
- private EncryptionKeyDao mEncryptionKeyDao;
+ private com.android.adservices.data.encryptionkey.EncryptionKeyDao mEncryptionKeyDao;
+ private EncryptionKeyDao mAuctionServerEncryptionKeyDao;
+ private EnrollmentDao mEnrollmentDao;
private EncryptionContextDao mEncryptionContextDao;
@Mock private ObliviousHttpEncryptor mObliviousHttpEncryptorMock;
@Mock private AdSelectionServiceFilter mAdSelectionServiceFilterMock;
@@ -305,8 +308,11 @@ public class AuctionServerE2ETest {
mFrequencyCapDaoSpy = spy(sharedDb.frequencyCapDao());
AdSelectionServerDatabase serverDb =
Room.inMemoryDatabaseBuilder(mContext, AdSelectionServerDatabase.class).build();
+ mEncryptionKeyDao =
+ com.android.adservices.data.encryptionkey.EncryptionKeyDao.getInstance(mContext);
+ mEnrollmentDao = EnrollmentDao.getInstance(mContext);
+ mAuctionServerEncryptionKeyDao = serverDb.encryptionKeyDao();
mEncryptionContextDao = serverDb.encryptionContextDao();
- mEncryptionKeyDao = serverDb.encryptionKeyDao();
mAdFilteringFeatureFactory =
new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDaoSpy, mFlags);
when(ConsentManager.getInstance(mContext)).thenReturn(mConsentManagerMock);
@@ -820,7 +826,7 @@ public class AuctionServerE2ETest {
.setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION)
.setExpiryTtlSeconds(TimeUnit.DAYS.toSeconds(7))
.build();
- mEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey));
+ mAuctionServerEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey));
String seed = "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";
byte[] seedBytes = seed.getBytes(StandardCharsets.US_ASCII);
@@ -831,8 +837,8 @@ public class AuctionServerE2ETest {
mCustomAudienceDaoSpy,
mEncodedPayloadDaoSpy,
mFrequencyCapDaoSpy,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -848,7 +854,7 @@ public class AuctionServerE2ETest {
mConsentManagerMock,
new ObliviousHttpEncryptorWithSeedImpl(
new AdSelectionEncryptionKeyManager(
- mEncryptionKeyDao,
+ mAuctionServerEncryptionKeyDao,
mFlags,
mAdServicesHttpsClientSpy,
mLightweightExecutorService),
@@ -1455,7 +1461,7 @@ public class AuctionServerE2ETest {
.setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION)
.setExpiryTtlSeconds(TimeUnit.DAYS.toSeconds(7))
.build();
- mEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey));
+ mAuctionServerEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey));
String seed = "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";
byte[] seedBytes = seed.getBytes(StandardCharsets.US_ASCII);
@@ -1466,8 +1472,8 @@ public class AuctionServerE2ETest {
mCustomAudienceDaoSpy,
mEncodedPayloadDaoSpy,
mFrequencyCapDaoSpy,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1483,7 +1489,7 @@ public class AuctionServerE2ETest {
mConsentManagerMock,
new ObliviousHttpEncryptorWithSeedImpl(
new AdSelectionEncryptionKeyManager(
- mEncryptionKeyDao,
+ mAuctionServerEncryptionKeyDao,
mFlags,
mAdServicesHttpsClientSpy,
mLightweightExecutorService),
@@ -1537,8 +1543,8 @@ public class AuctionServerE2ETest {
mCustomAudienceDaoSpy,
mEncodedPayloadDaoSpy,
mFrequencyCapDaoSpy,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/FrequencyCapFilteringE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/FrequencyCapFilteringE2ETest.java
index a18905bbe..76d93ab08 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/FrequencyCapFilteringE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/FrequencyCapFilteringE2ETest.java
@@ -57,18 +57,16 @@ import com.android.adservices.data.DbTestUtil;
import com.android.adservices.data.adselection.AdSelectionDatabase;
import com.android.adservices.data.adselection.AdSelectionDebugReportDao;
import com.android.adservices.data.adselection.AdSelectionEntryDao;
-import com.android.adservices.data.adselection.AdSelectionServerDatabase;
import com.android.adservices.data.adselection.AppInstallDao;
import com.android.adservices.data.adselection.DBAdSelection;
import com.android.adservices.data.adselection.DBAdSelectionHistogramInfo;
-import com.android.adservices.data.adselection.EncryptionContextDao;
-import com.android.adservices.data.adselection.EncryptionKeyDao;
import com.android.adservices.data.adselection.FrequencyCapDao;
import com.android.adservices.data.adselection.SharedStorageDatabase;
import com.android.adservices.data.common.DBAdData;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.CustomAudienceDatabase;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.data.signals.EncodedPayloadDao;
import com.android.adservices.data.signals.ProtectedSignalsDatabase;
@@ -118,7 +116,6 @@ import java.util.concurrent.TimeUnit;
@SpyStatic(FlagsFactory.class)
public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockitoTestCase {
-
private static final int CALLBACK_WAIT_MS = 500;
private static final int SELECT_ADS_CALLBACK_WAIT_MS = 10_000;
private static final long AD_SELECTION_ID_BUYER_1 = 20;
@@ -196,7 +193,7 @@ public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockit
private AppInstallDao mAppInstallDao;
private FrequencyCapDao mFrequencyCapDaoSpy;
private EncryptionKeyDao mEncryptionKeyDao;
- private EncryptionContextDao mEncryptionContextDao;
+ private EnrollmentDao mEnrollmentDao;
private ExecutorService mLightweightExecutorService;
private ExecutorService mBackgroundExecutorService;
private ScheduledThreadPoolExecutor mScheduledExecutor;
@@ -234,16 +231,16 @@ public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockit
Room.inMemoryDatabaseBuilder(mContextSpy, SharedStorageDatabase.class)
.build()
.frequencyCapDao());
- AdSelectionServerDatabase serverDb =
- Room.inMemoryDatabaseBuilder(mContextSpy, AdSelectionServerDatabase.class).build();
- mEncryptionContextDao = serverDb.encryptionContextDao();
- mEncryptionKeyDao = serverDb.encryptionKeyDao();
+
+ Flags flagsEnablingAdFiltering = new FlagsOverridingAdFiltering(true);
+ doReturn(flagsEnablingAdFiltering).when(FlagsFactory::getFlags);
+
+ mEncryptionKeyDao = EncryptionKeyDao.getInstance(mContextSpy);
+ mEnrollmentDao = EnrollmentDao.getInstance(mContextSpy);
mLightweightExecutorService = AdServicesExecutors.getLightWeightExecutor();
mBackgroundExecutorService = AdServicesExecutors.getBackgroundExecutor();
mScheduledExecutor = AdServicesExecutors.getScheduler();
- Flags flagsEnablingAdFiltering = new FlagsOverridingAdFiltering(true);
-
mFledgeAuthorizationFilterSpy =
ExtendedMockito.spy(
new FledgeAuthorizationFilter(
@@ -265,8 +262,8 @@ public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockit
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDaoSpy,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClientMock,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -380,7 +377,7 @@ public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockit
// Bypass the permission check since it's enforced before the package name check
doNothing()
.when(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
mContextSpy,
CommonFixture.TEST_PACKAGE_NAME_1,
AD_SERVICES_API_CALLED__API_NAME__UPDATE_AD_COUNTER_HISTOGRAM);
@@ -404,7 +401,7 @@ public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockit
verifyNoMoreInteractions(mFrequencyCapDaoSpy);
verify(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
mContextSpy,
CommonFixture.TEST_PACKAGE_NAME_1,
AD_SERVICES_API_CALLED__API_NAME__UPDATE_AD_COUNTER_HISTOGRAM);
@@ -425,8 +422,8 @@ public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockit
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDaoSpy,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClientMock,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -488,8 +485,8 @@ public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockit
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDaoSpy,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClientMock,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -746,8 +743,8 @@ public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockit
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDaoSpy,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClientMock,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -862,8 +859,8 @@ public final class FrequencyCapFilteringE2ETest extends AdServicesExtendedMockit
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDaoSpy,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClientMock,
mDevContextFilterMock,
mLightweightExecutorService,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OnDeviceAdSelectionRunnerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OnDeviceAdSelectionRunnerTest.java
index 56f4e55ae..ce83b09c8 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OnDeviceAdSelectionRunnerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/OnDeviceAdSelectionRunnerTest.java
@@ -18,6 +18,7 @@ package com.android.adservices.service.adselection;
import static android.adservices.adselection.CustomAudienceBiddingInfoFixture.DATA_VERSION_1;
import static android.adservices.adselection.CustomAudienceBiddingInfoFixture.DATA_VERSION_2;
+import static android.adservices.adselection.SignedContextualAdsFixture.signContextualAds;
import static android.adservices.common.AdServicesStatusUtils.ILLEGAL_STATE_BACKGROUND_CALLER_ERROR_MESSAGE;
import static android.adservices.common.AdServicesStatusUtils.RATE_LIMIT_REACHED_ERROR_MESSAGE;
import static android.adservices.common.AdServicesStatusUtils.STATUS_BACKGROUND_CALLER;
@@ -44,6 +45,7 @@ import static com.android.adservices.service.adselection.AdSelectionRunner.ERROR
import static com.android.adservices.service.adselection.AdSelectionRunner.ERROR_NO_WINNING_AD_FOUND;
import static com.android.adservices.service.adselection.AdSelectionRunner.ON_DEVICE_AUCTION_KILL_SWITCH_ENABLED;
import static com.android.adservices.service.adselection.AdSelectionScriptEngine.NUM_BITS_STOCHASTIC_ROUNDING;
+import static com.android.adservices.service.adselection.signature.ProtectedAudienceSignatureManager.PUBLIC_TEST_KEY_STRING;
import static com.android.adservices.service.stats.AdSelectionExecutionLoggerTest.BIDDING_STAGE_END_TIMESTAMP;
import static com.android.adservices.service.stats.AdSelectionExecutionLoggerTest.BIDDING_STAGE_START_TIMESTAMP;
import static com.android.adservices.service.stats.AdSelectionExecutionLoggerTest.DB_AD_SELECTION_FILE_SIZE;
@@ -128,6 +130,8 @@ import com.android.adservices.data.common.DBAdData;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.CustomAudienceDatabase;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
+import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.service.Flags;
import com.android.adservices.service.FlagsFactory;
import com.android.adservices.service.common.AdSelectionServiceFilter;
@@ -141,6 +145,8 @@ import com.android.adservices.service.common.httpclient.AdServicesHttpClientResp
import com.android.adservices.service.common.httpclient.AdServicesHttpsClient;
import com.android.adservices.service.consent.ConsentManager;
import com.android.adservices.service.devapi.DevContext;
+import com.android.adservices.service.encryptionkey.EncryptionKey;
+import com.android.adservices.service.enrollment.EnrollmentData;
import com.android.adservices.service.exception.FilterException;
import com.android.adservices.service.stats.AdSelectionExecutionLogger;
import com.android.adservices.service.stats.AdServicesLogger;
@@ -194,8 +200,6 @@ import java.util.stream.Collectors;
* mocked and provide expected mock responses when invoked with desired input
*/
public class OnDeviceAdSelectionRunnerTest {
- private static final String TAG = OnDeviceAdSelectionRunnerTest.class.getName();
-
private static final AdTechIdentifier BUYER_1 = AdSelectionConfigFixture.BUYER_1;
private static final AdTechIdentifier BUYER_2 = AdSelectionConfigFixture.BUYER_2;
private static final Long AD_SELECTION_ID = 1234L;
@@ -234,6 +238,8 @@ public class OnDeviceAdSelectionRunnerTest {
@Mock private AdCounterHistogramUpdater mAdCounterHistogramUpdaterMock;
@Mock private DebugReporting mDebugReportingMock;
@Mock private DebugReportSenderStrategy mDebugReportSenderMock;
+ @Mock private EnrollmentDao mEnrollmentDaoMock;
+ @Mock private EncryptionKeyDao mEncryptionKeyDaoMock;
@Captor
ArgumentCaptor<RunAdSelectionProcessReportedStats>
@@ -396,6 +402,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -501,6 +509,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -673,6 +683,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -798,6 +810,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -945,6 +959,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1145,6 +1161,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1245,6 +1263,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1359,6 +1379,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1434,6 +1456,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1500,6 +1524,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1563,6 +1589,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1617,6 +1645,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1767,6 +1797,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1886,6 +1918,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -1974,7 +2008,7 @@ public class OnDeviceAdSelectionRunnerTest {
// Getting ScoringOutcome-ForBuyerX corresponding to each BiddingOutcome-forBuyerX
// In this case assuming we get an empty result
when(mMockAdsScoreGenerator.runAdScoring(mAdBiddingOutcomeList, adSelectionConfig))
- .thenReturn((FluentFuture.from(Futures.immediateFuture(Collections.EMPTY_LIST))));
+ .thenReturn((FluentFuture.from(Futures.immediateFuture(Collections.emptyList()))));
mockAdSelectionExecutionLoggerSpyWithFailedAdSelectionDuringScoring();
@@ -1983,6 +2017,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2085,6 +2121,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2190,6 +2228,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2317,6 +2357,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2387,6 +2429,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2482,6 +2526,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2628,6 +2674,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2715,6 +2763,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2765,6 +2815,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2849,6 +2901,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2926,6 +2980,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -2981,6 +3037,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mMockHttpClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -3022,7 +3080,7 @@ public class OnDeviceAdSelectionRunnerTest {
mAdSelectionConfigBuilder
.build()
.cloneToBuilder()
- .setCustomAudienceBuyers(Collections.EMPTY_LIST)
+ .setCustomAudienceBuyers(Collections.emptyList())
.setBuyerSignedContextualAds(signedContextualAdsMap)
.build();
@@ -3055,6 +3113,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -3093,7 +3153,7 @@ public class OnDeviceAdSelectionRunnerTest {
mAdSelectionConfigBuilder
.build()
.cloneToBuilder()
- .setCustomAudienceBuyers(Collections.EMPTY_LIST)
+ .setCustomAudienceBuyers(Collections.emptyList())
// Despite populating Contextual Ads, they will be removed
.setBuyerSignedContextualAds(createContextualAds())
.build();
@@ -3121,6 +3181,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -3163,7 +3225,7 @@ public class OnDeviceAdSelectionRunnerTest {
mAdSelectionConfigBuilder
.build()
.cloneToBuilder()
- .setCustomAudienceBuyers(Collections.EMPTY_LIST)
+ .setCustomAudienceBuyers(Collections.emptyList())
.setBuyerSignedContextualAds(contextualAdsMap)
.build();
@@ -3191,6 +3253,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -3215,14 +3279,14 @@ public class OnDeviceAdSelectionRunnerTest {
.thenReturn(contextualAdsMap.get(CommonFixture.VALID_BUYER_1));
when(mMockAdFilterer.filterContextualAds(contextualAdsMap.get(CommonFixture.VALID_BUYER_2)))
.thenReturn(
- SignedContextualAdsFixture.aSignedContextualAdBuilder()
- .setBuyer(CommonFixture.VALID_BUYER_2)
- .setDecisionLogicUri(
- contextualAdsMap
- .get(CommonFixture.VALID_BUYER_2)
- .getDecisionLogicUri())
- .setAdsWithBid(Collections.EMPTY_LIST)
- .build());
+ signContextualAds(
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder()
+ .setBuyer(CommonFixture.VALID_BUYER_2)
+ .setDecisionLogicUri(
+ contextualAdsMap
+ .get(CommonFixture.VALID_BUYER_2)
+ .getDecisionLogicUri())
+ .setAdsWithBid(Collections.emptyList())));
invokeRunAdSelection(mAdSelectionRunner, adSelectionConfig, MY_APP_PACKAGE_NAME);
verify(mMockAdsScoreGenerator)
.runAdScoring(
@@ -3237,7 +3301,7 @@ public class OnDeviceAdSelectionRunnerTest {
.getAdsWithBid());
assertEquals(
"The contextual ads should have been filtered for Buyer 2",
- Collections.EMPTY_LIST,
+ Collections.emptyList(),
mAdSelectionConfigArgumentCaptor
.getValue()
.getBuyerSignedContextualAds()
@@ -3254,6 +3318,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -3343,6 +3409,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -3425,6 +3493,8 @@ public class OnDeviceAdSelectionRunnerTest {
mContextSpy,
mCustomAudienceDao,
mAdSelectionEntryDaoSpy,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
mAdServicesHttpsClient,
mLightweightExecutorService,
mBackgroundExecutorService,
@@ -3881,23 +3951,39 @@ public class OnDeviceAdSelectionRunnerTest {
AdTechIdentifier buyer1 = CommonFixture.VALID_BUYER_1;
SignedContextualAds contextualAds1 =
- SignedContextualAdsFixture.generateSignedContextualAds(
- buyer1, ImmutableList.of(100.0, 200.0, 300.0))
- .setDecisionLogicUri(
- CommonFixture.getUri(BUYER_1, BUYER_BIDDING_LOGIC_URI_PATH))
- .build();
+ signContextualAds(
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder(
+ buyer1, ImmutableList.of(100.0, 200.0, 300.0))
+ .setDecisionLogicUri(
+ CommonFixture.getUri(
+ BUYER_1, BUYER_BIDDING_LOGIC_URI_PATH)));
AdTechIdentifier buyer2 = CommonFixture.VALID_BUYER_2;
SignedContextualAds contextualAds2 =
- SignedContextualAdsFixture.generateSignedContextualAds(
- buyer2, ImmutableList.of(400.0, 500.0))
- .setDecisionLogicUri(
- CommonFixture.getUri(BUYER_2, BUYER_BIDDING_LOGIC_URI_PATH))
- .build();
+ signContextualAds(
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder(
+ buyer2, ImmutableList.of(400.0, 500.0))
+ .setDecisionLogicUri(
+ CommonFixture.getUri(
+ BUYER_2, BUYER_BIDDING_LOGIC_URI_PATH)));
buyerContextualAds.put(buyer1, contextualAds1);
buyerContextualAds.put(buyer2, contextualAds2);
+ for (AdTechIdentifier adTech : buyerContextualAds.keySet()) {
+ doReturn(new EnrollmentData.Builder().setEnrollmentId(adTech.toString()).build())
+ .when(mEnrollmentDaoMock)
+ .getEnrollmentDataForFledgeByAdTechIdentifier(adTech);
+ doReturn(
+ Collections.singletonList(
+ new EncryptionKey.Builder()
+ .setBody(PUBLIC_TEST_KEY_STRING)
+ .build()))
+ .when(mEncryptionKeyDaoMock)
+ .getEncryptionKeyFromEnrollmentIdAndKeyType(
+ adTech.toString(), EncryptionKey.KeyType.SIGNING);
+ }
+
return buyerContextualAds;
}
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportAndRegisterEventE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportAndRegisterEventE2ETest.java
index f564af8ec..d1b3cd9dc 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportAndRegisterEventE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportAndRegisterEventE2ETest.java
@@ -66,18 +66,16 @@ import com.android.adservices.data.DbTestUtil;
import com.android.adservices.data.adselection.AdSelectionDatabase;
import com.android.adservices.data.adselection.AdSelectionDebugReportDao;
import com.android.adservices.data.adselection.AdSelectionEntryDao;
-import com.android.adservices.data.adselection.AdSelectionServerDatabase;
import com.android.adservices.data.adselection.AppInstallDao;
import com.android.adservices.data.adselection.CustomAudienceSignals;
import com.android.adservices.data.adselection.DBAdSelection;
import com.android.adservices.data.adselection.DBRegisteredAdInteraction;
-import com.android.adservices.data.adselection.EncryptionContextDao;
-import com.android.adservices.data.adselection.EncryptionKeyDao;
import com.android.adservices.data.adselection.FrequencyCapDao;
import com.android.adservices.data.adselection.SharedStorageDatabase;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.CustomAudienceDatabase;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.data.measurement.DatastoreException;
import com.android.adservices.data.measurement.DatastoreManager;
@@ -163,7 +161,7 @@ public class ReportAndRegisterEventE2ETest {
private AppInstallDao mAppInstallDao;
private FrequencyCapDao mFrequencyCapDao;
private EncryptionKeyDao mEncryptionKeyDao;
- private EncryptionContextDao mEncryptionContextDao;
+ private EnrollmentDao mEnrollmentDao;
private AdFilteringFeatureFactory mAdFilteringFeatureFactory;
@Mock private AdSelectionServiceFilter mAdSelectionServiceFilterMock;
@Mock private ObliviousHttpEncryptor mObliviousHttpEncryptorMock;
@@ -284,13 +282,8 @@ public class ReportAndRegisterEventE2ETest {
mAppInstallDao = sharedDb.appInstallDao();
mFrequencyCapDao = sharedDb.frequencyCapDao();
- AdSelectionServerDatabase serverDb =
- Room.inMemoryDatabaseBuilder(
- ApplicationProvider.getApplicationContext(),
- AdSelectionServerDatabase.class)
- .build();
- mEncryptionContextDao = serverDb.encryptionContextDao();
- mEncryptionKeyDao = serverDb.encryptionKeyDao();
+ mEncryptionKeyDao = EncryptionKeyDao.getInstance(CONTEXT);
+ mEnrollmentDao = EnrollmentDao.getInstance(CONTEXT);
mAdFilteringFeatureFactory =
new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDao, mFlags);
@@ -986,8 +979,8 @@ public class ReportAndRegisterEventE2ETest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mHttpsClientSpy,
mDevContextFilterMock,
mLightweightExecutorService,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportImpressionScriptEngineTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportImpressionScriptEngineTest.java
index 9e2771e10..9ebccfd10 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportImpressionScriptEngineTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/ReportImpressionScriptEngineTest.java
@@ -267,6 +267,7 @@ public class ReportImpressionScriptEngineTest {
}
@Test
+ @FlakyTest(bugId = 317817375)
public void testReportResultSuccessfulCaseWithCallingRegisterAdBeacon() throws Exception {
String jsScript =
"function reportResult(ad_selection_config, render_uri, bid, contextual_signals) "
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/TrustedServerAdSelectionRunnerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/TrustedServerAdSelectionRunnerTest.java
index f0cfbaa60..d3385c13e 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/TrustedServerAdSelectionRunnerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/TrustedServerAdSelectionRunnerTest.java
@@ -50,6 +50,8 @@ import com.android.adservices.data.adselection.AdSelectionEntryDao;
import com.android.adservices.data.adselection.DBAdSelection;
import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.DBCustomAudience;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
+import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.service.Flags;
import com.android.adservices.service.FlagsFactory;
import com.android.adservices.service.adselection.AdSelectionRunner.AdSelectionOrchestrationResult;
@@ -150,6 +152,8 @@ public class TrustedServerAdSelectionRunnerTest {
@Mock private AdServicesLogger mAdServicesLoggerSpy;
@Mock private CustomAudienceDao mCustomAudienceDao;
@Mock private AdSelectionEntryDao mAdSelectionEntryDao;
+ @Mock private EnrollmentDao mEnrollmentDaoMock;
+ @Mock private EncryptionKeyDao mEncryptionKeyDaoMock;
@Mock private JsFetcher mJsFetcher;
@Mock private CustomAudienceDevOverridesHelper mCustomAudienceDevOverridesHelper;
@Mock private AdSelectionIdGenerator mMockAdSelectionIdGenerator;
@@ -215,6 +219,8 @@ public class TrustedServerAdSelectionRunnerTest {
mContext,
mCustomAudienceDao,
mAdSelectionEntryDao,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
sLightweightExecutorService,
sBackgroundExecutorService,
sScheduledExecutor,
@@ -276,6 +282,8 @@ public class TrustedServerAdSelectionRunnerTest {
mContext,
mCustomAudienceDao,
mAdSelectionEntryDao,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
sLightweightExecutorService,
sBackgroundExecutorService,
sScheduledExecutor,
@@ -339,6 +347,8 @@ public class TrustedServerAdSelectionRunnerTest {
mContext,
mCustomAudienceDao,
mAdSelectionEntryDao,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
sLightweightExecutorService,
sBackgroundExecutorService,
sScheduledExecutor,
@@ -408,6 +418,8 @@ public class TrustedServerAdSelectionRunnerTest {
mContext,
mCustomAudienceDao,
mAdSelectionEntryDao,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
sLightweightExecutorService,
sBackgroundExecutorService,
sScheduledExecutor,
@@ -461,6 +473,8 @@ public class TrustedServerAdSelectionRunnerTest {
mContext,
mCustomAudienceDao,
mAdSelectionEntryDao,
+ mEncryptionKeyDaoMock,
+ mEnrollmentDaoMock,
sLightweightExecutorService,
sBackgroundExecutorService,
sScheduledExecutor,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/BinarySerializerSignedContextualAdsTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/BinarySerializerSignedContextualAdsTest.java
index ad751d71d..1533ff53a 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/BinarySerializerSignedContextualAdsTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/BinarySerializerSignedContextualAdsTest.java
@@ -16,8 +16,6 @@
package com.android.adservices.service.adselection.signature;
-import static android.adservices.adselection.SignedContextualAdsFixture.PLACEHOLDER_SIGNATURE;
-
import static com.google.common.truth.Truth.assertThat;
import android.adservices.adselection.AdWithBid;
@@ -42,6 +40,8 @@ import java.util.Set;
import java.util.stream.Collectors;
public class BinarySerializerSignedContextualAdsTest {
+ public static final byte[] TEST_SIGNATURE = new byte[] {0, 1, 2};
+
private SignedContextualAdsHashUtil mSerializer;
@Before
@@ -131,7 +131,7 @@ public class BinarySerializerSignedContextualAdsTest {
.setRenderUri(Uri.parse(adRenderUri))
.build(),
Double.parseDouble(bid))))
- .setSignature(PLACEHOLDER_SIGNATURE)
+ .setSignature(TEST_SIGNATURE)
.build();
byte[] serialized = new SignedContextualAdsHashUtil().serialize(contextualAds);
@@ -203,7 +203,7 @@ public class BinarySerializerSignedContextualAdsTest {
.setRenderUri(Uri.parse(adRenderUri))
.build(),
Double.parseDouble(bid))))
- .setSignature(PLACEHOLDER_SIGNATURE)
+ .setSignature(TEST_SIGNATURE)
.build();
byte[] serialized = new SignedContextualAdsHashUtil().serialize(contextualAds);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManagerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManagerTest.java
index 774da48a8..a44359664 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManagerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/ProtectedAudienceSignatureManagerTest.java
@@ -16,14 +16,17 @@
package com.android.adservices.service.adselection.signature;
+import static android.adservices.adselection.SignedContextualAdsFixture.aSignedContextualAds;
+
+import static com.android.adservices.service.adselection.signature.ProtectedAudienceSignatureManager.PUBLIC_TEST_KEY_STRING;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
+import android.adservices.adselection.SignedContextualAds;
import android.adservices.common.AdTechIdentifier;
-import android.content.Context;
-import androidx.test.core.app.ApplicationProvider;
import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
import com.android.adservices.data.enrollment.EnrollmentDao;
@@ -35,39 +38,102 @@ import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Base64;
import java.util.Collections;
import java.util.List;
public class ProtectedAudienceSignatureManagerTest {
- private Context mContext = ApplicationProvider.getApplicationContext();
- @Mock private EnrollmentDao mEnrollmentDao;
- @Mock private EncryptionKeyDao mEncryptionKeyDao;
+ @Mock private EnrollmentDao mEnrollmentDaoMock;
+ @Mock private EncryptionKeyDao mEncryptionKeyDaoMock;
+ private ProtectedAudienceSignatureManager mNoOpSignatureManager;
+ private ProtectedAudienceSignatureManager mSignatureManager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ SignatureVerifier noOpSignatureVerifier =
+ new SignatureVerifier() {
+ @Override
+ public boolean verify(byte[] publicKey, byte[] data, byte[] signature) {
+ return true;
+ }
+ };
+ boolean enrollmentEnabled = false;
+ mSignatureManager =
+ new ProtectedAudienceSignatureManager(
+ mEnrollmentDaoMock, mEncryptionKeyDaoMock, enrollmentEnabled);
+ mNoOpSignatureManager =
+ new ProtectedAudienceSignatureManager(
+ mEnrollmentDaoMock, mEncryptionKeyDaoMock, noOpSignatureVerifier);
+ }
+
+ @Test
+ public void testVerifySignature_validSignature_returnTrue() {
+ SignedContextualAds signedContextualAds = aSignedContextualAds();
+ String enrollmentId = "enrollment1";
+ AdTechIdentifier buyer = signedContextualAds.getBuyer();
+
+ doReturn(new EnrollmentData.Builder().setEnrollmentId(enrollmentId).build())
+ .when(mEnrollmentDaoMock)
+ .getEnrollmentDataForFledgeByAdTechIdentifier(buyer);
+ doReturn(
+ Collections.singletonList(
+ new EncryptionKey.Builder()
+ .setBody(PUBLIC_TEST_KEY_STRING)
+ .build()))
+ .when(mEncryptionKeyDaoMock)
+ .getEncryptionKeyFromEnrollmentIdAndKeyType(
+ enrollmentId, EncryptionKey.KeyType.SIGNING);
+
+ boolean isVerified = mSignatureManager.isVerified(buyer, signedContextualAds);
+
+ assertThat(isVerified).isTrue();
+ }
+
+ @Test
+ public void testVerifySignature_invalidSignature_returnFalse() {
+ byte[] invalidSignature = new byte[] {1, 2, 3};
+ SignedContextualAds signedContextualAds =
+ aSignedContextualAds().cloneToBuilder().setSignature(invalidSignature).build();
+ String enrollmentId = "enrollment1";
+ AdTechIdentifier buyer = signedContextualAds.getBuyer();
+
+ doReturn(new EnrollmentData.Builder().setEnrollmentId(enrollmentId).build())
+ .when(mEnrollmentDaoMock)
+ .getEnrollmentDataForFledgeByAdTechIdentifier(buyer);
+ doReturn(
+ Collections.singletonList(
+ new EncryptionKey.Builder()
+ .setBody(PUBLIC_TEST_KEY_STRING)
+ .build()))
+ .when(mEncryptionKeyDaoMock)
+ .getEncryptionKeyFromEnrollmentIdAndKeyType(
+ enrollmentId, EncryptionKey.KeyType.SIGNING);
+
+ boolean isVerified = mSignatureManager.isVerified(buyer, signedContextualAds);
+
+ assertThat(isVerified).isFalse();
}
@Test
public void testFetchKeys_validAdTech_success() {
AdTechIdentifier adTech = AdTechIdentifier.fromString("example.com");
- String publicKey = "test-key";
+ byte[] publicKeyBytes = new byte[] {1, 2, 3, 4, 5};
+ String publicKey = Base64.getEncoder().encodeToString(publicKeyBytes);
String enrollmentId = "enrollment1";
doReturn(new EnrollmentData.Builder().setEnrollmentId(enrollmentId).build())
- .when(mEnrollmentDao)
+ .when(mEnrollmentDaoMock)
.getEnrollmentDataForFledgeByAdTechIdentifier(adTech);
doReturn(Collections.singletonList(new EncryptionKey.Builder().setBody(publicKey).build()))
- .when(mEncryptionKeyDao)
+ .when(mEncryptionKeyDaoMock)
.getEncryptionKeyFromEnrollmentIdAndKeyType(
enrollmentId, EncryptionKey.KeyType.SIGNING);
- ProtectedAudienceSignatureManager signatureManager =
- new ProtectedAudienceSignatureManager(mContext, mEnrollmentDao, mEncryptionKeyDao);
-
- List<String> signingKeys = signatureManager.fetchPublicKeyForAdTech(adTech);
+ List<byte[]> signingKeys = mNoOpSignatureManager.fetchPublicKeyForAdTech(adTech);
- assertThat(signingKeys).isEqualTo(Collections.singletonList(publicKey));
+ assertThat(signingKeys.size()).isEqualTo(1);
+ assertThat(signingKeys.get(0)).isEqualTo(publicKeyBytes);
}
@Test
@@ -77,8 +143,10 @@ public class ProtectedAudienceSignatureManagerTest {
EnrollmentData enrollment =
new EnrollmentData.Builder().setEnrollmentId(enrollmentId).build();
- String publicKey1 = "test-key1";
- String publicKey2 = "test-key2";
+ byte[] publicKeyBytes1 = new byte[] {1, 2, 3, 4, 5};
+ String publicKey1 = Base64.getEncoder().encodeToString(publicKeyBytes1);
+ byte[] publicKeyBytes2 = new byte[] {6, 7, 8, 9, 10};
+ String publicKey2 = Base64.getEncoder().encodeToString(publicKeyBytes2);
long expiration1 = 0L;
long expiration2 = 1L;
EncryptionKey encKey1 =
@@ -88,32 +156,28 @@ public class ProtectedAudienceSignatureManagerTest {
List<EncryptionKey> encKeysToPersistInReverseOrder = List.of(encKey2, encKey1);
doReturn(enrollment)
- .when(mEnrollmentDao)
+ .when(mEnrollmentDaoMock)
.getEnrollmentDataForFledgeByAdTechIdentifier(adTech);
doReturn(encKeysToPersistInReverseOrder)
- .when(mEncryptionKeyDao)
+ .when(mEncryptionKeyDaoMock)
.getEncryptionKeyFromEnrollmentIdAndKeyType(
enrollmentId, EncryptionKey.KeyType.SIGNING);
- ProtectedAudienceSignatureManager signatureManager =
- new ProtectedAudienceSignatureManager(mContext, mEnrollmentDao, mEncryptionKeyDao);
-
- List<String> signingKeys = signatureManager.fetchPublicKeyForAdTech(adTech);
+ List<byte[]> signingKeys = mNoOpSignatureManager.fetchPublicKeyForAdTech(adTech);
assertThat(signingKeys.size()).isEqualTo(2);
- assertThat(signingKeys.get(0)).isEqualTo(publicKey1);
- assertThat(signingKeys.get(1)).isEqualTo(publicKey2);
+ assertThat(signingKeys.get(0)).isEqualTo(publicKeyBytes1);
+ assertThat(signingKeys.get(1)).isEqualTo(publicKeyBytes2);
}
@Test
public void testFetchKeys_notEnrolledAdTech_returnsEmptyList() {
AdTechIdentifier adTech = AdTechIdentifier.fromString("example.com");
- doReturn(null).when(mEnrollmentDao).getEnrollmentDataForFledgeByAdTechIdentifier(adTech);
-
- ProtectedAudienceSignatureManager signatureManager =
- new ProtectedAudienceSignatureManager(mContext, mEnrollmentDao, mEncryptionKeyDao);
+ doReturn(null)
+ .when(mEnrollmentDaoMock)
+ .getEnrollmentDataForFledgeByAdTechIdentifier(adTech);
- List<String> signingKeys = signatureManager.fetchPublicKeyForAdTech(adTech);
+ List<byte[]> signingKeys = mNoOpSignatureManager.fetchPublicKeyForAdTech(adTech);
assertThat(signingKeys).isEqualTo(Collections.emptyList());
}
@@ -122,13 +186,10 @@ public class ProtectedAudienceSignatureManagerTest {
public void testFetchKeys_enrolledAdTechWithNullId_returnsEmptyList() {
AdTechIdentifier adTech = AdTechIdentifier.fromString("example.com");
doReturn(new EnrollmentData.Builder().build())
- .when(mEnrollmentDao)
+ .when(mEnrollmentDaoMock)
.getEnrollmentDataForFledgeByAdTechIdentifier(adTech);
- ProtectedAudienceSignatureManager signatureManager =
- new ProtectedAudienceSignatureManager(mContext, mEnrollmentDao, mEncryptionKeyDao);
-
- List<String> signingKeys = signatureManager.fetchPublicKeyForAdTech(adTech);
+ List<byte[]> signingKeys = mNoOpSignatureManager.fetchPublicKeyForAdTech(adTech);
assertThat(signingKeys).isEqualTo(Collections.emptyList());
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/SafeNoCopyByteArrayOutputStreamTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/ThreadUnsafeByteArrayOutputStreamTest.java
index 2c10dbb66..8f7622fce 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/SafeNoCopyByteArrayOutputStreamTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/adselection/signature/ThreadUnsafeByteArrayOutputStreamTest.java
@@ -21,7 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import org.junit.Before;
import org.junit.Test;
-public class SafeNoCopyByteArrayOutputStreamTest {
+public class ThreadUnsafeByteArrayOutputStreamTest {
private ThreadUnsafeByteArrayOutputStream mOutputStream;
@Before
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigCallTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigCallTest.java
new file mode 100644
index 000000000..495b5c3c8
--- /dev/null
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigCallTest.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2023 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.service.common;
+
+import static com.android.adservices.service.common.AppManifestConfigCall.API_ATTRIBUTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_CUSTOM_AUDIENCES;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_TOPICS;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_UNSPECIFIED;
+import static com.android.adservices.service.common.AppManifestConfigCall.INVALID_API_TEMPLATE;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_APP_ALLOWS_ALL;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_DOES_NOT_EXIST;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_BY_APP;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_GENERIC_ERROR;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_UNSPECIFIED;
+import static com.android.adservices.service.common.AppManifestConfigCall.isAllowed;
+import static com.android.adservices.service.common.AppManifestConfigCall.resultToString;
+import static com.android.adservices.service.common.AppManifestConfigCall.apiToString;
+
+import static org.junit.Assert.assertThrows;
+
+import com.android.adservices.common.AdServicesUnitTestCase;
+
+import org.junit.Test;
+
+public final class AppManifestConfigCallTest extends AdServicesUnitTestCase {
+
+ private static final String PKG_NAME = "pkg.I.am";
+ private static final String PKG_NAME2 = "or.not";
+
+ @Test
+ public void testInvalidConstructor() {
+ assertThrows(
+ NullPointerException.class,
+ () -> new AppManifestConfigCall(/* packageName= */ null, API_TOPICS));
+
+ IllegalArgumentException e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new AppManifestConfigCall(PKG_NAME, API_UNSPECIFIED));
+ expect.withMessage("e.getMessage()")
+ .that(e)
+ .hasMessageThat()
+ .isEqualTo(String.format(INVALID_API_TEMPLATE, API_UNSPECIFIED));
+
+ e =
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new AppManifestConfigCall(PKG_NAME, -42));
+ expect.withMessage("e.getMessage()")
+ .that(e)
+ .hasMessageThat()
+ .isEqualTo(String.format(INVALID_API_TEMPLATE, -42));
+ }
+
+ @Test
+ public void testValidConstructors() {
+ AppManifestConfigCall topics = new AppManifestConfigCall(PKG_NAME, API_TOPICS);
+ expect.withMessage("pkg on %s", topics).that(topics.packageName).isEqualTo(PKG_NAME);
+ expect.withMessage("api on %s", topics).that(topics.api).isEqualTo(API_TOPICS);
+
+ AppManifestConfigCall customAudience =
+ new AppManifestConfigCall(PKG_NAME, API_CUSTOM_AUDIENCES);
+ expect.withMessage("pkg on %s", customAudience)
+ .that(customAudience.packageName)
+ .isEqualTo(PKG_NAME);
+ expect.withMessage("api on %s", customAudience)
+ .that(customAudience.api)
+ .isEqualTo(API_CUSTOM_AUDIENCES);
+
+ AppManifestConfigCall attribution = new AppManifestConfigCall(PKG_NAME, API_ATTRIBUTION);
+ expect.withMessage("pkg on %s", attribution)
+ .that(attribution.packageName)
+ .isEqualTo(PKG_NAME);
+ expect.withMessage("api on %s", attribution)
+ .that(attribution.api)
+ .isEqualTo(API_ATTRIBUTION);
+ }
+
+ @Test
+ public void testEqualsHashCode() {
+ AppManifestConfigCall pkg1api1 = new AppManifestConfigCall(PKG_NAME, API_TOPICS);
+ AppManifestConfigCall pkg1api2 = new AppManifestConfigCall(PKG_NAME, API_ATTRIBUTION);
+ AppManifestConfigCall pkg2api1 = new AppManifestConfigCall(PKG_NAME2, API_TOPICS);
+ AppManifestConfigCall pkg2api2 = new AppManifestConfigCall(PKG_NAME2, API_ATTRIBUTION);
+
+ AppManifestConfigCall otherPkg1api1 = new AppManifestConfigCall(PKG_NAME, API_TOPICS);
+ AppManifestConfigCall otherPkg1api2 = new AppManifestConfigCall(PKG_NAME, API_ATTRIBUTION);
+ AppManifestConfigCall otherPkg2api1 = new AppManifestConfigCall(PKG_NAME2, API_TOPICS);
+ AppManifestConfigCall otherPkg2api2 = new AppManifestConfigCall(PKG_NAME2, API_ATTRIBUTION);
+
+ expectEquals(pkg1api1, pkg1api1);
+ expectEquals(pkg1api1, otherPkg1api1);
+ expectEquals(pkg1api2, pkg1api2);
+ expectEquals(pkg1api2, otherPkg1api2);
+ expectEquals(pkg2api1, pkg2api1);
+ expectEquals(pkg2api1, otherPkg2api1);
+ expectEquals(pkg2api2, pkg2api2);
+ expectEquals(pkg2api2, otherPkg2api2);
+
+ expectNotEquals(pkg1api1, pkg1api2);
+ expectNotEquals(pkg1api1, pkg2api1);
+ expectNotEquals(pkg1api1, pkg2api2);
+
+ // Adds result
+ otherPkg1api1.result = RESULT_ALLOWED_APP_ALLOWS_ALL;
+ expectNotEquals(pkg1api1, otherPkg1api1);
+ pkg1api1.result = RESULT_ALLOWED_APP_ALLOWS_ALL;
+ expectEquals(pkg1api1, otherPkg1api1);
+ }
+
+ private void expectEquals(AppManifestConfigCall call1, AppManifestConfigCall call2) {
+ expect.withMessage("equals()").that(call1).isEqualTo(call2);
+ expect.withMessage("equals()").that(call2).isEqualTo(call1);
+ expect.withMessage("hashcode(%s, %s)", call1, call2)
+ .that(call1.hashCode())
+ .isEqualTo(call2.hashCode());
+ }
+
+ private void expectNotEquals(AppManifestConfigCall call1, AppManifestConfigCall call2) {
+ expect.withMessage("equals()").that(call1).isNotEqualTo(call2);
+ expect.withMessage("equals()").that(call2).isNotEqualTo(call1);
+ expect.withMessage("hashcode(%s, %s)", call1, call2)
+ .that(call1.hashCode())
+ .isNotEqualTo(call2.hashCode());
+ }
+
+ @Test
+ public void testResultToString() {
+ expect.withMessage("resultToString(%s)", RESULT_UNSPECIFIED)
+ .that(resultToString(RESULT_UNSPECIFIED))
+ .isEqualTo("UNSPECIFIED");
+ expect.withMessage("resultToString(%s)", RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG)
+ .that(resultToString(RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG))
+ .isEqualTo("ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG");
+ expect.withMessage(
+ "resultToString(%s)",
+ RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION)
+ .that(resultToString(RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION))
+ .isEqualTo("ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION");
+ expect.withMessage("resultToString(%s)", RESULT_ALLOWED_APP_ALLOWS_ALL)
+ .that(resultToString(RESULT_ALLOWED_APP_ALLOWS_ALL))
+ .isEqualTo("ALLOWED_APP_ALLOWS_ALL");
+ expect.withMessage("resultToString(%s)", RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID)
+ .that(resultToString(RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID))
+ .isEqualTo("ALLOWED_APP_ALLOWS_SPECIFIC_ID");
+ expect.withMessage("resultToString(%s)", RESULT_DISALLOWED_APP_DOES_NOT_EXIST)
+ .that(resultToString(RESULT_DISALLOWED_APP_DOES_NOT_EXIST))
+ .isEqualTo("DISALLOWED_APP_DOES_NOT_EXIST");
+ expect.withMessage("resultToString(%s)", RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR)
+ .that(resultToString(RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR))
+ .isEqualTo("DISALLOWED_APP_CONFIG_PARSING_ERROR");
+ expect.withMessage("resultToString(%s)", RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG)
+ .that(resultToString(RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG))
+ .isEqualTo("DISALLOWED_APP_DOES_NOT_HAVE_CONFIG");
+ expect.withMessage(
+ "resultToString(%s)", RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION)
+ .that(resultToString(RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION))
+ .isEqualTo("DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION");
+ expect.withMessage("resultToString(%s)", RESULT_DISALLOWED_BY_APP)
+ .that(resultToString(RESULT_DISALLOWED_BY_APP))
+ .isEqualTo("DISALLOWED_BY_APP");
+ expect.withMessage("resultToString(%s)", RESULT_DISALLOWED_GENERIC_ERROR)
+ .that(resultToString(RESULT_DISALLOWED_GENERIC_ERROR))
+ .isEqualTo("DISALLOWED_GENERIC_ERROR");
+ expect.withMessage("resultToString(42)").that(resultToString(42)).isEqualTo("INVALID-42");
+ }
+
+ @Test
+ public void testApiToString() {
+ expect.withMessage("apiToString(%s)", API_UNSPECIFIED)
+ .that(apiToString(API_UNSPECIFIED))
+ .isEqualTo("UNSPECIFIED");
+ expect.withMessage("apiToString(%s)", API_TOPICS)
+ .that(apiToString(API_TOPICS))
+ .isEqualTo("TOPICS");
+ expect.withMessage("apiToString(%s)", API_CUSTOM_AUDIENCES)
+ .that(apiToString(API_CUSTOM_AUDIENCES))
+ .isEqualTo("CUSTOM_AUDIENCES");
+ expect.withMessage("apiToString(%s)", API_ATTRIBUTION)
+ .that(apiToString(API_ATTRIBUTION))
+ .isEqualTo("ATTRIBUTION");
+ expect.withMessage("apiToString(42)").that(apiToString(42)).isEqualTo("INVALID-42");
+ }
+
+ @Test
+ public void testIsAllowed() {
+ expect.withMessage("isAllowed(%s)", resultToString(RESULT_UNSPECIFIED))
+ .that(isAllowed(RESULT_UNSPECIFIED))
+ .isFalse();
+ expect.withMessage(
+ "isAllowed(%s)",
+ resultToString(RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG))
+ .that(isAllowed(RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG))
+ .isTrue();
+ expect.withMessage(
+ "isAllowed(%s)",
+ resultToString(
+ RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION))
+ .that(isAllowed(RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION))
+ .isTrue();
+ expect.withMessage("isAllowed(%s)", resultToString(RESULT_ALLOWED_APP_ALLOWS_ALL))
+ .that(isAllowed(RESULT_ALLOWED_APP_ALLOWS_ALL))
+ .isTrue();
+ expect.withMessage("isAllowed(%s)", resultToString(RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID))
+ .that(isAllowed(RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID))
+ .isTrue();
+ expect.withMessage("isAllowed(%s)", resultToString(RESULT_DISALLOWED_APP_DOES_NOT_EXIST))
+ .that(isAllowed(RESULT_DISALLOWED_APP_DOES_NOT_EXIST))
+ .isFalse();
+ expect.withMessage(
+ "isAllowed(%s)", resultToString(RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR))
+ .that(isAllowed(RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR))
+ .isFalse();
+ expect.withMessage(
+ "isAllowed(%s)", resultToString(RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG))
+ .that(isAllowed(RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG))
+ .isFalse();
+ expect.withMessage(
+ "isAllowed(%s)",
+ resultToString(RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION))
+ .that(isAllowed(RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION))
+ .isFalse();
+ expect.withMessage("isAllowed(%s)", resultToString(RESULT_DISALLOWED_BY_APP))
+ .that(isAllowed(RESULT_DISALLOWED_BY_APP))
+ .isFalse();
+ expect.withMessage("isAllowed(%s)", resultToString(RESULT_DISALLOWED_GENERIC_ERROR))
+ .that(isAllowed(RESULT_DISALLOWED_GENERIC_ERROR))
+ .isFalse();
+ }
+}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigHelperTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigHelperTest.java
index b9adf151e..592635a9f 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigHelperTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigHelperTest.java
@@ -19,13 +19,16 @@ package com.android.adservices.service.common;
import static com.android.adservices.mockito.ExtendedMockitoExpectations.mockIsAtLeastS;
import static com.android.adservices.mockito.ExtendedMockitoExpectations.doNothingOnErrorLogUtilError;
import static com.android.adservices.mockito.ExtendedMockitoExpectations.verifyErrorLogUtilError;
-import static com.android.adservices.service.common.AppManifestConfigMetricsLoggerTest.appManifestConfigCall;
-import static com.android.adservices.service.common.AppManifestConfigMetricsLoggerTest.APP_DOES_NOT_EXIST;
-import static com.android.adservices.service.common.AppManifestConfigMetricsLoggerTest.APP_DOES_NOT_HAVE_CONFIG;
-import static com.android.adservices.service.common.AppManifestConfigMetricsLoggerTest.APP_EXISTS;
-import static com.android.adservices.service.common.AppManifestConfigMetricsLoggerTest.APP_HAS_CONFIG;
-import static com.android.adservices.service.common.AppManifestConfigMetricsLoggerTest.ENABLED_BY_DEFAULT;
-import static com.android.adservices.service.common.AppManifestConfigMetricsLoggerTest.NOT_ENABLED_BY_DEFAULT;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_ATTRIBUTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_CUSTOM_AUDIENCES;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_TOPICS;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_APP_ALLOWS_ALL;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_DOES_NOT_EXIST;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_BY_APP;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__APP_MANIFEST_CONFIG_PARSING_ERROR;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -82,6 +85,9 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
private static final String PACKAGE_NAME = "TEST_PACKAGE";
private static final String ENROLLMENT_ID = "ENROLLMENT_ID";
+ // Constants for generic allowed / disallowed calls - the "type" doesn't matter
+ private static final int RESULT_ALLOWED = RESULT_ALLOWED_APP_ALLOWS_ALL;
+
@Mock private AppManifestConfig mMockAppManifestConfig;
@Mock private AppManifestIncludesSdkLibraryConfig mMockSdkLibraryConfig;
@Mock private Context mMockContext;
@@ -106,14 +112,14 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
public void testIsAllowedAttributionAccess_sPlus() throws Exception {
mockGetPropertySucceeds(PACKAGE_NAME, AD_SERVICES_CONFIG_PROPERTY, RESOURCE_ID);
mockAppManifestConfigParserGetConfigSucceeds();
- mockIsAllowedAttributionAccess(ENROLLMENT_ID, true);
+ mockIsAllowedAttributionAccess(ENROLLMENT_ID, RESULT_ALLOWED);
assertWithMessage("isAllowedAttributionAccess(ctx, %s, %s)", PACKAGE_NAME, ENROLLMENT_ID)
.that(
AppManifestConfigHelper.isAllowedAttributionAccess(
PACKAGE_NAME, ENROLLMENT_ID))
.isTrue();
- verifyLogUsage(APP_EXISTS, APP_HAS_CONFIG, NOT_ENABLED_BY_DEFAULT);
+ verifyLogUsage(API_ATTRIBUTION, RESULT_ALLOWED);
}
@Test
@@ -121,14 +127,14 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
mockSdkLevelR();
mockGetAssetSucceeds(PACKAGE_NAME, RESOURCE_ID);
mockAppManifestConfigParserGetConfigSucceeds();
- mockIsAllowedAttributionAccess(ENROLLMENT_ID, true);
+ mockIsAllowedAttributionAccess(ENROLLMENT_ID, RESULT_ALLOWED);
assertWithMessage("isAllowedAttributionAccess(ctx, %s, %s)", PACKAGE_NAME, ENROLLMENT_ID)
.that(
AppManifestConfigHelper.isAllowedAttributionAccess(
PACKAGE_NAME, ENROLLMENT_ID))
.isTrue();
- verifyLogUsage(APP_EXISTS, APP_HAS_CONFIG, NOT_ENABLED_BY_DEFAULT);
+ verifyLogUsage(API_ATTRIBUTION, RESULT_ALLOWED);
}
@Test
@@ -136,7 +142,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
public void testIsAllowedCustomAudiencesAccess_sPlus() throws Exception {
mockGetPropertySucceeds(PACKAGE_NAME, AD_SERVICES_CONFIG_PROPERTY, RESOURCE_ID);
mockAppManifestConfigParserGetConfigSucceeds();
- mockIsAllowedCustomAudiencesAccess(ENROLLMENT_ID, true);
+ mockIsAllowedCustomAudiencesAccess(ENROLLMENT_ID, RESULT_ALLOWED);
assertWithMessage(
"isAllowedCustomAudiencesAccess(ctx, %s, %s)", PACKAGE_NAME, ENROLLMENT_ID)
.that(
@@ -144,7 +150,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
PACKAGE_NAME, ENROLLMENT_ID))
.isTrue();
- verifyLogUsage(APP_EXISTS, APP_HAS_CONFIG, NOT_ENABLED_BY_DEFAULT);
+ verifyLogUsage(API_CUSTOM_AUDIENCES, RESULT_ALLOWED);
}
@Test
@@ -152,7 +158,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
mockSdkLevelR();
mockGetAssetSucceeds(PACKAGE_NAME, RESOURCE_ID);
mockAppManifestConfigParserGetConfigSucceeds();
- mockIsAllowedCustomAudiencesAccess(ENROLLMENT_ID, true);
+ mockIsAllowedCustomAudiencesAccess(ENROLLMENT_ID, RESULT_ALLOWED);
assertWithMessage(
"isAllowedCustomAudiencesAccess(ctx, %s, %s)", PACKAGE_NAME, ENROLLMENT_ID)
.that(
@@ -160,7 +166,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
PACKAGE_NAME, ENROLLMENT_ID))
.isTrue();
- verifyLogUsage(APP_EXISTS, APP_HAS_CONFIG, NOT_ENABLED_BY_DEFAULT);
+ verifyLogUsage(API_CUSTOM_AUDIENCES, RESULT_ALLOWED);
}
@Test
@@ -285,7 +291,9 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
}
mockAppManifestConfigParserGetConfigSucceeds();
mockContainsSdk(ENROLLMENT_ID, containsSdk);
- mockIsAllowedTopicsAccess(ENROLLMENT_ID, topicsAllowed);
+ int result =
+ expectedAllowed ? RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID : RESULT_DISALLOWED_BY_APP;
+ mockIsAllowedTopicsAccess(ENROLLMENT_ID, result);
assertWithMessage("isAllowedTopicsAccess(ctx, %s, %s)", PACKAGE_NAME, ENROLLMENT_ID)
.that(
AppManifestConfigHelper.isAllowedTopicsAccess(
@@ -294,7 +302,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
ENROLLMENT_ID))
.isEqualTo(expectedAllowed);
- verifyLogUsage(APP_EXISTS, APP_HAS_CONFIG, NOT_ENABLED_BY_DEFAULT);
+ verifyLogUsage(API_TOPICS, result);
}
@Test
@@ -306,7 +314,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertNoAccessAllowed();
verifyErrorLogUtilErrorLogged(e, times(4)); // Called once for each API
- verifyLogUsage(APP_EXISTS, APP_HAS_CONFIG, NOT_ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR);
}
@Test
@@ -318,7 +326,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertNoAccessAllowed();
verifyErrorLogUtilErrorLogged(e, times(4)); // Called once for each API
- verifyLogUsage(APP_EXISTS, APP_HAS_CONFIG, NOT_ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR);
}
@Test
@@ -332,7 +340,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertNoAccessAllowed();
verifyErrorLogUtilErrorLogged(e, times(4)); // Called once for each API
- verifyLogUsage(APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR);
}
@Test
@@ -346,7 +354,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertNoAccessAllowed();
verifyErrorLogUtilErrorLogged(e, times(4)); // Called once for each API
- verifyLogUsage(APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_DISALLOWED_APP_CONFIG_PARSING_ERROR);
}
@Test
@@ -355,8 +363,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertNoAccessAllowed();
- verifyLogUsage(
- APP_DOES_NOT_EXIST, APP_DOES_NOT_HAVE_CONFIG, NOT_ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_DISALLOWED_APP_DOES_NOT_EXIST);
}
@Test
@@ -366,7 +373,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertNoAccessAllowed();
- verifyLogUsage(APP_DOES_NOT_EXIST, APP_DOES_NOT_HAVE_CONFIG, ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_DISALLOWED_APP_DOES_NOT_EXIST);
}
@Test
@@ -377,7 +384,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertNoAccessAllowed();
- verifyLogUsage(APP_EXISTS, APP_DOES_NOT_HAVE_CONFIG, NOT_ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG);
}
@Test
@@ -388,7 +395,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertNoAccessAllowed();
- verifyLogUsage(APP_EXISTS, APP_DOES_NOT_HAVE_CONFIG, NOT_ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_DISALLOWED_APP_DOES_NOT_HAVE_CONFIG);
}
@Test
@@ -401,7 +408,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertAllAccessAllowed();
- verifyLogUsage(APP_EXISTS, APP_DOES_NOT_HAVE_CONFIG, ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG);
}
@Test
@@ -414,7 +421,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
assertAllAccessAllowed();
- verifyLogUsage(APP_EXISTS, APP_DOES_NOT_HAVE_CONFIG, ENABLED_BY_DEFAULT, times(4));
+ verifyLogUsageForAllApis(RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG);
}
private void mockSdkLevelR() {
@@ -485,16 +492,16 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
return e;
}
- private void mockIsAllowedAttributionAccess(String partnerId, boolean value) {
- when(mMockAppManifestConfig.isAllowedAttributionAccess(partnerId)).thenReturn(value);
+ private void mockIsAllowedAttributionAccess(String partnerId, int result) {
+ when(mMockAppManifestConfig.isAllowedAttributionAccess(partnerId)).thenReturn(result);
}
- private void mockIsAllowedCustomAudiencesAccess(String partnerId, boolean value) {
- when(mMockAppManifestConfig.isAllowedCustomAudiencesAccess(partnerId)).thenReturn(value);
+ private void mockIsAllowedCustomAudiencesAccess(String partnerId, int result) {
+ when(mMockAppManifestConfig.isAllowedCustomAudiencesAccess(partnerId)).thenReturn(result);
}
- private void mockIsAllowedTopicsAccess(String partnerId, boolean value) {
- when(mMockAppManifestConfig.isAllowedTopicsAccess(partnerId)).thenReturn(value);
+ private void mockIsAllowedTopicsAccess(String partnerId, int result) {
+ when(mMockAppManifestConfig.isAllowedTopicsAccess(partnerId)).thenReturn(result);
}
private void mockContainsSdk(String partnerId, boolean value) {
@@ -549,9 +556,7 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
expect.withMessage("isAllowedTopicsAccess(ctx, %s, %s)", PACKAGE_NAME, ENROLLMENT_ID)
.that(
AppManifestConfigHelper.isAllowedTopicsAccess(
- /* useSandboxCheck= */ false,
- PACKAGE_NAME,
- ENROLLMENT_ID))
+ /* useSandboxCheck= */ false, PACKAGE_NAME, ENROLLMENT_ID))
.isTrue();
verifyErrorLogUtilErrorLogged(any(), never());
@@ -567,21 +572,23 @@ public final class AppManifestConfigHelperTest extends AdServicesExtendedMockito
mode);
}
- private void verifyLogUsage(boolean appExists, boolean appHasConfig, boolean enabledByDefault) {
- verifyLogUsage(appExists, appHasConfig, enabledByDefault, times(1));
+ private void verifyLogUsage(int api, int result) {
+ verifyLogUsage(api, result, times(1));
}
- private void verifyLogUsage(
- boolean appExists,
- boolean appHasConfig,
- boolean enabledByDefault,
- VerificationMode mode) {
- verify(
- () ->
- AppManifestConfigMetricsLogger.logUsage(
- appManifestConfigCall(
- PACKAGE_NAME, appExists, appHasConfig, enabledByDefault)),
- mode);
+ private void verifyLogUsage(int api, int result, VerificationMode mode) {
+ AppManifestConfigCall call = new AppManifestConfigCall(PACKAGE_NAME, api);
+ call.result = result;
+
+ verify(() -> AppManifestConfigMetricsLogger.logUsage(call), mode);
+ }
+
+ private void verifyLogUsageForAllApis(int result) {
+ // Cannot use anyInt() for the APIs as logUsage() uses a custom object / matcher - it would
+ // be too coplicate to create a generic one for it
+ verifyLogUsage(API_TOPICS, result, times(2));
+ verifyLogUsage(API_ATTRIBUTION, result);
+ verifyLogUsage(API_CUSTOM_AUDIENCES, result);
}
private void setEnabledByDefault(boolean value) {
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigMetricsLoggerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigMetricsLoggerTest.java
index 0f4b2795a..800027b5d 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigMetricsLoggerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigMetricsLoggerTest.java
@@ -18,8 +18,20 @@ package com.android.adservices.service.common;
import static com.android.adservices.mockito.ExtendedMockitoExpectations.mockErrorLogUtilWithThrowable;
import static com.android.adservices.mockito.ExtendedMockitoExpectations.mockErrorLogUtilWithoutThrowable;
+import static com.android.adservices.mockito.ExtendedMockitoExpectations.verifyErrorLogUtilError;
+import static com.android.adservices.mockito.ExtendedMockitoExpectations.verifyErrorLogUtilErrorWithAnyException;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_ATTRIBUTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.API_TOPICS;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_APP_ALLOWS_ALL;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_BY_APP;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_UNSPECIFIED;
+import static com.android.adservices.service.common.AppManifestConfigCall.apiToString;
+import static com.android.adservices.service.common.AppManifestConfigCall.resultToString;
import static com.android.adservices.service.common.AppManifestConfigMetricsLogger.dump;
+import static com.android.adservices.service.common.AppManifestConfigMetricsLogger.PREFS_KEY_TEMPLATE;
import static com.android.adservices.service.common.AppManifestConfigMetricsLogger.PREFS_NAME;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__APP_MANIFEST_CONFIG_LOGGING_ERROR;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_UPDATE_FAILURE;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_EXCEPTION;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON;
@@ -29,7 +41,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -37,8 +49,6 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.util.Log;
-import androidx.test.filters.FlakyTest;
-
import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
import com.android.adservices.common.Nullable;
import com.android.adservices.common.SyncCallback;
@@ -46,12 +56,13 @@ import com.android.adservices.errorlogging.ErrorLogUtil;
import com.android.adservices.mockito.ExtendedMockitoExpectations.ErrorLogUtilCallback;
import com.android.adservices.service.Flags;
import com.android.adservices.service.FlagsFactory;
+import com.android.adservices.service.common.AppManifestConfigCall.ApiType;
+import com.android.adservices.service.common.AppManifestConfigCall.Result;
import com.android.adservices.shared.testing.common.DumpHelper;
import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import java.io.File;
@@ -59,6 +70,7 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
@@ -71,14 +83,11 @@ public final class AppManifestConfigMetricsLoggerTest extends AdServicesExtended
private static final String PKG_NAME = "pkg.I.am";
private static final String PKG_NAME2 = "or.not";
- static final boolean APP_EXISTS = true;
- static final boolean APP_DOES_NOT_EXIST = false;
-
- static final boolean APP_HAS_CONFIG = true;
- static final boolean APP_DOES_NOT_HAVE_CONFIG = false;
+ // Generic API - exact value doesn't matter
+ private static final @ApiType int API = API_TOPICS;
- static final boolean ENABLED_BY_DEFAULT = true;
- static final boolean NOT_ENABLED_BY_DEFAULT = false;
+ private static final String KEY_PKG_NAME_API =
+ String.format(Locale.US, PREFS_KEY_TEMPLATE, PKG_NAME, API);
@Mock private Context mMockContext;
@Mock private Flags mMockFlags;
@@ -101,119 +110,79 @@ public final class AppManifestConfigMetricsLoggerTest extends AdServicesExtended
public void testLogUsage_nullArgs() throws Exception {
assertThrows(
NullPointerException.class,
- () ->
- logUsageAndDontWait(
- /* packageName= */ null,
- APP_EXISTS,
- APP_HAS_CONFIG,
- ENABLED_BY_DEFAULT));
+ () -> logUsageAndDontWait(/* packageName= */ null, RESULT_ALLOWED_APP_ALLOWS_ALL));
+ }
+
+ @Test
+ public void testLogUsage_callWithInvalidResult() throws Exception {
+ AppManifestConfigCall call = new AppManifestConfigCall(PKG_NAME, API);
+ call.result = RESULT_UNSPECIFIED;
+ mPrefs.onEditThrows(); // will throw if edit() is called
+
+ AppManifestConfigMetricsLogger.logUsage(call);
+
+ verifyErrorLogUtilError(
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__APP_MANIFEST_CONFIG_LOGGING_ERROR,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON);
+ assertEditNotCalled();
}
@Test
public void testLogUsage_firstTime() throws Exception {
- logUsageAndWait(APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT);
+ logUsageAndWait(PKG_NAME, RESULT_ALLOWED_APP_ALLOWS_ALL);
Map<String, ?> allProps = mPrefs.getAll();
assertWithMessage("allProps").that(allProps).hasSize(1);
- assertWithMessage("properties keys").that(allProps.keySet()).containsExactly(PKG_NAME);
+ assertWithMessage("properties keys")
+ .that(allProps.keySet())
+ .containsExactly(KEY_PKG_NAME_API);
}
@Test
- public void testLogUsage_secondTimeSameArgs() throws Exception {
+ public void testLogUsage_secondTimeSameResult() throws Exception {
// 1st time is fine
- logUsageAndWait(APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT);
+ logUsageAndWait(PKG_NAME, RESULT_ALLOWED_APP_ALLOWS_ALL);
// 2nd time should not call edit
mPrefs.onEditThrows(); // will throw if edit() is called
- logUsageAndDontWait(PKG_NAME, APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT);
+ logUsageAndDontWait(PKG_NAME, RESULT_ALLOWED_APP_ALLOWS_ALL);
Map<String, ?> allProps = mPrefs.getAll();
assertWithMessage("allProps").that(allProps).hasSize(1);
- assertWithMessage("properties keys").that(allProps.keySet()).containsExactly(PKG_NAME);
- }
+ assertWithMessage("properties keys")
+ .that(allProps.keySet())
+ .containsExactly(KEY_PKG_NAME_API);
- @FlakyTest(bugId = 315979774, detail = "Might need to split it into multiple tests")
- @Test
- public void testLogUsage_secondTimeDifferentArgs() throws Exception {
- callOnceWithAllTrueThenSecondWith(APP_EXISTS, APP_HAS_CONFIG, NOT_ENABLED_BY_DEFAULT);
- callOnceWithAllTrueThenSecondWith(APP_EXISTS, APP_DOES_NOT_HAVE_CONFIG, ENABLED_BY_DEFAULT);
- callOnceWithAllTrueThenSecondWith(
- APP_EXISTS, APP_DOES_NOT_HAVE_CONFIG, NOT_ENABLED_BY_DEFAULT);
- callOnceWithAllTrueThenSecondWith(APP_DOES_NOT_EXIST, APP_HAS_CONFIG, ENABLED_BY_DEFAULT);
- callOnceWithAllTrueThenSecondWith(
- APP_DOES_NOT_EXIST, APP_HAS_CONFIG, NOT_ENABLED_BY_DEFAULT);
- callOnceWithAllTrueThenSecondWith(
- APP_DOES_NOT_EXIST, APP_DOES_NOT_HAVE_CONFIG, ENABLED_BY_DEFAULT);
- callOnceWithAllTrueThenSecondWith(
- APP_DOES_NOT_EXIST, APP_DOES_NOT_HAVE_CONFIG, NOT_ENABLED_BY_DEFAULT);
+ assertEditNotCalled();
}
- private void callOnceWithAllTrueThenSecondWith(
- boolean appExists, boolean appHasConfig, boolean enabledByDefault) throws Exception {
- Log.i(
- mTag,
- "callOnceWithAllTrueThenSecondWith(appExists="
- + appExists
- + ", appHasConfig="
- + appHasConfig
- + ", enabledByDefault="
- + enabledByDefault
- + ")");
- // Need to use a new prefs because it's called multiple times (so it starts in a clean
- // state) - life would be so much easier if JUnit provided an easy way to run parameterized
- // tests per method (not class)
- FakeSharedPreferences prefs = new FakeSharedPreferences();
- when(mMockContext.getSharedPreferences(any(String.class), anyInt())).thenReturn(prefs);
-
+ @Test
+ public void testLogUsage_secondTimeDifferentResult() throws Exception {
+ int result = RESULT_ALLOWED_APP_ALLOWS_ALL;
// 1st call
- Log.d(
- mTag,
- "1st call: appExists="
- + APP_EXISTS
- + ", appHasConfig="
- + APP_HAS_CONFIG
- + ", enabledByDefault="
- + ENABLED_BY_DEFAULT
- + ")");
- logUsageAndWait(prefs, PKG_NAME, APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT);
-
- int valueBefore = prefs.getInt(PKG_NAME, -1);
- expect.withMessage(
- "stored value of %s after 1st call (appExists=%s, appHasConfig=%s,"
- + " enabledByDefault=%s)",
- PKG_NAME, APP_EXISTS, APP_EXISTS, ENABLED_BY_DEFAULT)
+ Log.d(mTag, "1st call: result=" + result);
+ logUsageAndWait(PKG_NAME, result);
+
+ int valueBefore = mPrefs.getInt(KEY_PKG_NAME_API, RESULT_UNSPECIFIED);
+ expect.withMessage("stored value of %s after 1st call (result=%s)", PKG_NAME, result)
.that(valueBefore)
- .isNotEqualTo(-1);
+ .isEqualTo(RESULT_ALLOWED_APP_ALLOWS_ALL);
// 2nd call
- Log.d(
- mTag,
- "2nd call: appExists="
- + appExists
- + ", appHasConfig="
- + appHasConfig
- + ", enabledByDefault="
- + enabledByDefault
- + ")");
- logUsageAndWait(prefs, PKG_NAME, appExists, appHasConfig, enabledByDefault);
-
- Map<String, ?> allProps = prefs.getAll();
+ result = RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG;
+ Log.d(mTag, "2nd call: result=" + result);
+ logUsageAndWait(PKG_NAME, result);
+
+ Map<String, ?> allProps = mPrefs.getAll();
expect.withMessage("allProps").that(allProps).hasSize(1);
- expect.withMessage("properties keys").that(allProps.keySet()).containsExactly(PKG_NAME);
+ expect.withMessage("properties keys")
+ .that(allProps.keySet())
+ .containsExactly(KEY_PKG_NAME_API);
- int valueAfter = prefs.getInt(PKG_NAME, -1);
- expect.withMessage(
- "stored value of %s after 2nd call (appExists=%s, appHasConfig=%s,"
- + " enabledByDefault=%s)",
- PKG_NAME, appExists, appHasConfig, enabledByDefault)
+ int valueAfter = mPrefs.getInt(KEY_PKG_NAME_API, RESULT_UNSPECIFIED);
+ expect.withMessage("stored value of %s after 2nd call (result=%s)", PKG_NAME, result)
.that(valueAfter)
- .isNotEqualTo(-1);
- expect.withMessage(
- "stored value of %s after 2nd call (appExists=%s, appHasConfig=%s,"
- + " enabledByDefault=%s)",
- PKG_NAME, appExists, appHasConfig, enabledByDefault)
- .that(valueAfter)
- .isNotEqualTo(valueBefore);
+ .isEqualTo(RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG);
}
@Test
@@ -222,7 +191,7 @@ public final class AppManifestConfigMetricsLoggerTest extends AdServicesExtended
when(mMockContext.getSharedPreferences(any(String.class), anyInt())).thenThrow(exception);
- logUsageAndDontWait(PKG_NAME, APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT);
+ logUsageAndDontWait(PKG_NAME, RESULT_ALLOWED_APP_ALLOWS_ALL);
mErrorLogUtilWithThrowableCallback.assertReceived(
expect,
@@ -235,7 +204,7 @@ public final class AppManifestConfigMetricsLoggerTest extends AdServicesExtended
public void testLogUsage_commitFailed() throws Exception {
mPrefs.onCommitReturns(/* result= */ false);
- logUsageAndDontWait(PKG_NAME, APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT);
+ logUsageAndDontWait(PKG_NAME, RESULT_ALLOWED_APP_ALLOWS_ALL);
Map<String, ?> allProps = mPrefs.getAll();
assertWithMessage("allProps").that(allProps).isEmpty();
@@ -258,7 +227,7 @@ public final class AppManifestConfigMetricsLoggerTest extends AdServicesExtended
return mPrefs;
});
- logUsageAndWait(mPrefs, PKG_NAME, APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT);
+ logUsageAndWait(PKG_NAME, RESULT_ALLOWED_APP_ALLOWS_ALL);
assertWithMessage("execution thread")
.that(executionThread.get())
@@ -288,63 +257,58 @@ public final class AppManifestConfigMetricsLoggerTest extends AdServicesExtended
@Test
public void testDump_multipleEntries() throws Exception {
- logUsageAndWait(mPrefs, PKG_NAME, APP_EXISTS, APP_HAS_CONFIG, ENABLED_BY_DEFAULT);
+ logUsageAndWait(PKG_NAME, API_TOPICS, RESULT_ALLOWED_APP_ALLOWS_ALL);
+ logUsageAndWait(PKG_NAME, API_ATTRIBUTION, RESULT_DISALLOWED_BY_APP);
logUsageAndWait(
- mPrefs,
- PKG_NAME2,
- APP_DOES_NOT_EXIST,
- APP_DOES_NOT_HAVE_CONFIG,
- NOT_ENABLED_BY_DEFAULT);
+ PKG_NAME2, API_ATTRIBUTION, RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG);
String dump = DumpHelper.dump(pw -> AppManifestConfigMetricsLogger.dump(mMockContext, pw));
+ String entry1 =
+ ".*"
+ + PKG_NAME
+ + "-"
+ + apiToString(API_TOPICS)
+ + ": "
+ + resultToString(RESULT_ALLOWED_APP_ALLOWS_ALL)
+ + ".*\n";
+ String entry2 =
+ ".*"
+ + PKG_NAME
+ + "-"
+ + apiToString(API_ATTRIBUTION)
+ + ": "
+ + resultToString(RESULT_DISALLOWED_BY_APP)
+ + ".*\n";
+ String entry3 =
+ ".*"
+ + PKG_NAME2
+ + "-"
+ + apiToString(API_ATTRIBUTION)
+ + ": "
+ + resultToString(RESULT_ALLOWED_BY_DEFAULT_APP_DOES_NOT_HAVE_CONFIG)
+ + ".*\n";
expect.withMessage("dump")
.that(dump)
.matches(
Pattern.compile(
- ".*2 entries.*\n"
- + ".*"
- + PKG_NAME
- + ":.*appExists="
- + APP_EXISTS
- + ".*appHasConfig="
- + APP_HAS_CONFIG
- + ".*enabledByDefault="
- + ENABLED_BY_DEFAULT
- + "\n"
- + ".*"
- + PKG_NAME2
- + ":.*appExists="
- + APP_DOES_NOT_EXIST
- + ".*appHasConfig="
- + APP_DOES_NOT_HAVE_CONFIG
- + ".*enabledByDefault="
- + NOT_ENABLED_BY_DEFAULT
- + "\n",
- Pattern.DOTALL));
+ ".*3 entries.*\n" + entry1 + entry2 + entry3, Pattern.DOTALL));
}
// Needs to wait until the shared prefs is committed() as it happens in a separated thread
- private void logUsageAndWait(boolean appExists, boolean appHasConfig, boolean enabledByDefault)
+ private void logUsageAndWait(String appName, @Result int callResult)
throws InterruptedException {
- logUsageAndWait(mPrefs, PKG_NAME, appExists, appHasConfig, enabledByDefault);
+ logUsageAndWait(appName, API, callResult);
}
// Needs to wait until the shared prefs is committed() as it happens in a separated thread
- private void logUsageAndWait(
- SharedPreferences prefs,
- String appName,
- boolean appExists,
- boolean appHasConfig,
- boolean enabledByDefault)
+ private void logUsageAndWait(String appName, @ApiType int api, @Result int callResult)
throws InterruptedException {
SyncOnSharedPreferenceChangeListener listener = new SyncOnSharedPreferenceChangeListener();
- prefs.registerOnSharedPreferenceChangeListener(listener);
+ mPrefs.registerOnSharedPreferenceChangeListener(listener);
try {
- AppManifestConfigCall call = new AppManifestConfigCall(appName);
- call.appExists = appExists;
- call.appHasConfig = appHasConfig;
- call.enabledByDefault = enabledByDefault;
+ AppManifestConfigCall call = new AppManifestConfigCall(appName, api);
+ call.result = callResult;
Log.v(mTag, "logUsageAndWait(call=" + call + ", listener=" + listener + ")");
AppManifestConfigMetricsLogger.logUsage(call);
@@ -357,61 +321,24 @@ public final class AppManifestConfigMetricsLoggerTest extends AdServicesExtended
// Should only be used in cases where the call is expect to not change the shared preferences
// (in which case a listener would not be called)
- private void logUsageAndDontWait(
- String appName, boolean appExists, boolean appHasConfig, boolean enabledByDefault) {
- AppManifestConfigCall call = new AppManifestConfigCall(appName);
- call.appExists = appExists;
- call.appHasConfig = appHasConfig;
- call.enabledByDefault = enabledByDefault;
+ private void logUsageAndDontWait(String appName, @Result int callResult) {
+ AppManifestConfigCall call = new AppManifestConfigCall(appName, API);
+ call.result = callResult;
Log.v(mTag, "logUsageAndDontWait(call=" + call + ")");
AppManifestConfigMetricsLogger.logUsage(call);
}
- /** Gets a custom Mockito matcher for a {@link AppManifestConfigCall}, without the result. */
- static AppManifestConfigCall appManifestConfigCall(
- String packageName, boolean appExists, boolean appHasConfig, boolean enabledByDefault) {
- return argThat(
- new AppManifestConfigCallMatcher(
- packageName, appExists, appHasConfig, enabledByDefault));
- }
-
- private static final class AppManifestConfigCallMatcher
- implements ArgumentMatcher<AppManifestConfigCall> {
-
- private final String mPackageName;
- private final boolean mAppExists;
- private final boolean mAppHasConfig;
- private final boolean mEnabledByDefault;
-
- private AppManifestConfigCallMatcher(
- String packageName,
- boolean appExists,
- boolean appHasConfig,
- boolean enabledByDefault) {
- mPackageName = packageName;
- mAppExists = appExists;
- mAppHasConfig = appHasConfig;
- mEnabledByDefault = enabledByDefault;
- }
-
- @Override
- public boolean matches(AppManifestConfigCall arg) {
- return arg != null
- && arg.packageName.equals(mPackageName)
- && arg.appExists == mAppExists
- && arg.appHasConfig == mAppHasConfig
- && arg.enabledByDefault == mEnabledByDefault;
- }
+ // Must call mPrefs.onEditThrows() first
+ private void assertEditNotCalled() {
+ sleep(
+ 1_000,
+ "waiting to make sure edit() was not called in the background (which would "
+ + "have thrown an exception)");
- @Override
- public String toString() {
- AppManifestConfigCall call = new AppManifestConfigCall(mPackageName);
- call.appExists = mAppExists;
- call.appHasConfig = mAppHasConfig;
- call.enabledByDefault = mEnabledByDefault;
-
- return call.toString() + " {NOT CHECING RESULT}";
- }
+ verifyErrorLogUtilErrorWithAnyException(
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__SHARED_PREF_EXCEPTION,
+ AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__COMMON,
+ never());
}
// TODO(b/309857141): move to its own class / common package (it will be done in a later CL so
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigParserTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigParserTest.java
index 10fd81c8a..724b1087c 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigParserTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/AppManifestConfigParserTest.java
@@ -16,6 +16,12 @@
package com.android.adservices.service.common;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION;
+import static com.android.adservices.service.common.AppManifestConfigCall.RESULT_DISALLOWED_BY_APP;
+import static com.android.adservices.service.common.AppManifestConfigCall.resultToString;
+
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
@@ -82,10 +88,10 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
// Verify Attribution tags.
expect.withMessage("getAttributionConfig().getAllowAdPartnersToAccess()")
.that(appManifestConfig.isAllowedAttributionAccess("1234"))
- .isTrue();
+ .isEqualTo(RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID);
expect.withMessage("isAllowedAttributionAccess()")
.that(appManifestConfig.isAllowedAttributionAccess("108"))
- .isFalse();
+ .isEqualTo(RESULT_DISALLOWED_BY_APP);
AppManifestAttributionConfig attributionConfig = appManifestConfig.getAttributionConfig();
expect.withMessage("getAttributionConfig()").that(attributionConfig).isNotNull();
if (attributionConfig != null) {
@@ -100,7 +106,7 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
// Verify Custom Audience tags.
expect.withMessage("isAllowedCustomAudiencesAccess()")
.that(appManifestConfig.isAllowedCustomAudiencesAccess("108"))
- .isFalse();
+ .isEqualTo(RESULT_DISALLOWED_BY_APP);
AppManifestCustomAudiencesConfig customAudiencesConfig =
appManifestConfig.getCustomAudiencesConfig();
expect.withMessage("getCustomAudiencesConfig()").that(customAudiencesConfig).isNotNull();
@@ -119,10 +125,10 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
// Verify Topics tags.
expect.withMessage("1234567()")
.that(appManifestConfig.isAllowedTopicsAccess("1234567"))
- .isTrue();
+ .isEqualTo(RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID);
expect.withMessage("isAllowedTopicsAccess()")
.that(appManifestConfig.isAllowedTopicsAccess("108"))
- .isFalse();
+ .isEqualTo(RESULT_DISALLOWED_BY_APP);
AppManifestTopicsConfig topicsConfig = appManifestConfig.getTopicsConfig();
expect.withMessage("getTopicsConfig()").that(topicsConfig).isNotNull();
if (topicsConfig != null) {
@@ -137,10 +143,10 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
// Verify AppId tags.
expect.withMessage("isAllowedAdIdAccess()")
.that(appManifestConfig.isAllowedAdIdAccess("42"))
- .isTrue();
+ .isEqualTo(RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID);
expect.withMessage("isAllowedAdIdAccess()")
.that(appManifestConfig.isAllowedAdIdAccess("108"))
- .isFalse();
+ .isEqualTo(RESULT_DISALLOWED_BY_APP);
AppManifestAdIdConfig adIdConfig = appManifestConfig.getAdIdConfig();
expect.withMessage("getAdIdConfig()").that(adIdConfig).isNotNull();
if (adIdConfig != null) {
@@ -155,10 +161,10 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
// Verify AppSetId tags.
expect.withMessage("isAllowedAppSetIdAccess()")
.that(appManifestConfig.isAllowedAppSetIdAccess("42"))
- .isTrue();
+ .isEqualTo(RESULT_ALLOWED_APP_ALLOWS_SPECIFIC_ID);
expect.withMessage("isAllowedAppSetIdAccess()")
.that(appManifestConfig.isAllowedAppSetIdAccess("108"))
- .isFalse();
+ .isEqualTo(RESULT_DISALLOWED_BY_APP);
AppManifestAppSetIdConfig appSetIdConfig = appManifestConfig.getAppSetIdConfig();
expect.withMessage("getAppSetIdConfig()").that(appSetIdConfig).isNotNull();
if (appSetIdConfig != null) {
@@ -216,34 +222,39 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
AppManifestAttributionConfig attributionConfig = appManifestConfig.getAttributionConfig();
expect.withMessage("getAttributionConfig()").that(attributionConfig).isNull();
- expect.withMessage("isAllowedAttributionAccess()")
- .that(appManifestConfig.isAllowedAttributionAccess("not actually there"))
- .isFalse();
+ assertResult(
+ "isAllowedAttributionAccess()",
+ appManifestConfig.isAllowedAttributionAccess("not actually there"),
+ RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION);
AppManifestCustomAudiencesConfig customAudiencesConfig =
appManifestConfig.getCustomAudiencesConfig();
expect.withMessage("getCustomAudiencesConfig()").that(attributionConfig).isNull();
- expect.withMessage("isAllowedCustomAudiencesAccess()")
- .that(appManifestConfig.isAllowedCustomAudiencesAccess("not actually there"))
- .isFalse();
+ assertResult(
+ "isAllowedCustomAudiencesAccess()",
+ appManifestConfig.isAllowedCustomAudiencesAccess("not actually there"),
+ RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION);
AppManifestTopicsConfig topicsConfig = appManifestConfig.getTopicsConfig();
expect.withMessage("getTopicsConfig()").that(topicsConfig).isNull();
- expect.withMessage("isAllowedTopicsAccess()")
- .that(appManifestConfig.isAllowedTopicsAccess("not actually there"))
- .isFalse();
+ assertResult(
+ "isAllowedTopicsAccess()",
+ appManifestConfig.isAllowedTopicsAccess("not actually there"),
+ RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION);
AppManifestAdIdConfig adIdConfig = appManifestConfig.getAdIdConfig();
expect.withMessage("getAdIdConfig()").that(adIdConfig).isNull();
- expect.withMessage("isAllowedAdIdAccess()")
- .that(appManifestConfig.isAllowedAdIdAccess("not actually there"))
- .isFalse();
+ assertResult(
+ "isAllowedAdIdAccess()",
+ appManifestConfig.isAllowedTopicsAccess("not actually there"),
+ RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION);
AppManifestAppSetIdConfig appSetIdConfig = appManifestConfig.getAppSetIdConfig();
expect.withMessage("getAppSetIdConfig()").that(appSetIdConfig).isNull();
- expect.withMessage("isAllowedAppSetIdAccess()")
- .that(appManifestConfig.isAllowedAppSetIdAccess("not actually there"))
- .isFalse();
+ assertResult(
+ "isAllowedAppSetIdAccess()",
+ appManifestConfig.isAllowedAppSetIdAccess("not actually there"),
+ RESULT_DISALLOWED_APP_HAS_CONFIG_WITHOUT_API_SECTION);
}
@Test
@@ -254,16 +265,21 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
.getXml(R.xml.ad_services_config_missing_tags);
AppManifestConfig appManifestConfig =
AppManifestConfigParser.getConfig(parser, /* enabledByDefault= */ true);
- assertWithMessage("manifest for ad_services_config_all_false_missing_attribution")
+ assertWithMessage("manifest for ad_services_config_missing_tags")
.that(appManifestConfig)
.isNotNull();
assertSdkLibraryConfigIsEmpty(appManifestConfig, /* containsByDefault= */ true);
- assertAttributionConfigIsDefault(appManifestConfig);
- assertCustomAudiencesConfigIsDefault(appManifestConfig);
- assertTopicsConfigIsDefault(appManifestConfig);
- assertAdIdConfigIsDefault(appManifestConfig);
- assertAppSetIdConfigIsDefault(appManifestConfig);
+ assertAttributionConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
+ assertCustomAudienceConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
+ assertTopicsConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
+ assertAdIdConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
+ assertAppSetIdConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
}
@Test
@@ -279,11 +295,12 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
.isNotNull();
assertSdkLibraryConfigIsEmpty(appManifestConfig, /* containsByDefault= */ true);
- assertAttributionConfigIsDefault(appManifestConfig);
- assertCustomAudiencesConfigIsFalse(appManifestConfig);
- assertTopicsConfigIsFalse(appManifestConfig);
- assertAdIdConfigIsFalse(appManifestConfig);
- assertAppSetIdConfigIsFalse(appManifestConfig);
+ assertAttributionConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
+ assertCustomAudienceConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertTopicsConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAdIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAppSetIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
}
@Test
@@ -299,11 +316,12 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
.isNotNull();
assertSdkLibraryConfigIsEmpty(appManifestConfig, /* containsByDefault= */ true);
- assertAttributionConfigIsFalse(appManifestConfig);
- assertCustomAudiencesConfigIsDefault(appManifestConfig);
- assertTopicsConfigIsFalse(appManifestConfig);
- assertAdIdConfigIsFalse(appManifestConfig);
- assertAppSetIdConfigIsFalse(appManifestConfig);
+ assertAttributionConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertCustomAudienceConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
+ assertTopicsConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAdIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAppSetIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
}
@Test
@@ -319,11 +337,12 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
.isNotNull();
assertSdkLibraryConfigIsEmpty(appManifestConfig, /* containsByDefault= */ true);
- assertAttributionConfigIsFalse(appManifestConfig);
- assertCustomAudiencesConfigIsFalse(appManifestConfig);
- assertTopicsConfigIsDefault(appManifestConfig);
- assertAdIdConfigIsFalse(appManifestConfig);
- assertAppSetIdConfigIsFalse(appManifestConfig);
+ assertAttributionConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertCustomAudienceConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertTopicsConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
+ assertAdIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAppSetIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
}
@Test
@@ -339,11 +358,13 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
.isNotNull();
assertSdkLibraryConfigIsEmpty(appManifestConfig, /* containsByDefault= */ true);
- assertAttributionConfigIsFalse(appManifestConfig);
- assertCustomAudiencesConfigIsFalse(appManifestConfig);
- assertTopicsConfigIsFalse(appManifestConfig);
- assertAdIdConfigIsDefault(appManifestConfig);
- assertAppSetIdConfigIsFalse(appManifestConfig);
+ assertAttributionConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertCustomAudienceConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertTopicsConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertTopicsConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAdIdConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
+ assertAppSetIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
}
@Test
@@ -359,11 +380,12 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
.isNotNull();
assertSdkLibraryConfigIsEmpty(appManifestConfig, /* containsByDefault= */ true);
- assertAttributionConfigIsFalse(appManifestConfig);
- assertCustomAudiencesConfigIsFalse(appManifestConfig);
- assertTopicsConfigIsFalse(appManifestConfig);
- assertAdIdConfigIsFalse(appManifestConfig);
- assertAppSetIdConfigIsDefault(appManifestConfig);
+ assertAttributionConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertCustomAudienceConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertTopicsConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAdIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAppSetIdConfigIsAllowed(
+ appManifestConfig, RESULT_ALLOWED_BY_DEFAULT_APP_HAS_CONFIG_WITHOUT_API_SECTION);
}
@Test
@@ -379,11 +401,11 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
.isNotNull();
assertSdkLibraryConfigIsEmpty(appManifestConfig, /* containsByDefault= */ true);
- assertAttributionConfigIsFalse(appManifestConfig);
- assertCustomAudiencesConfigIsFalse(appManifestConfig);
- assertTopicsConfigIsFalse(appManifestConfig);
- assertAdIdConfigIsFalse(appManifestConfig);
- assertAppSetIdConfigIsFalse(appManifestConfig);
+ assertAttributionConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertCustomAudienceConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertTopicsConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAdIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAppSetIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
}
@Test
@@ -415,11 +437,11 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
.that(sdkLibrary.contains("4815162342"))
.isFalse();
- assertAttributionConfigIsFalse(appManifestConfig);
- assertCustomAudiencesConfigIsFalse(appManifestConfig);
- assertTopicsConfigIsFalse(appManifestConfig);
- assertAdIdConfigIsFalse(appManifestConfig);
- assertAppSetIdConfigIsFalse(appManifestConfig);
+ assertAttributionConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertCustomAudienceConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertTopicsConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAdIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAppSetIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
}
@Test
@@ -434,11 +456,11 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
.isNotNull();
assertSdkLibraryConfigIsEmpty(appManifestConfig, /* containsByDefault= */ false);
- assertAttributionConfigIsFalse(appManifestConfig);
- assertCustomAudiencesConfigIsFalse(appManifestConfig);
- assertTopicsConfigIsFalse(appManifestConfig);
- assertAdIdConfigIsFalse(appManifestConfig);
- assertAppSetIdConfigIsFalse(appManifestConfig);
+ assertAttributionConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertCustomAudienceConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertTopicsConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAdIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
+ assertAppSetIdConfigIsAllowed(appManifestConfig, RESULT_DISALLOWED_BY_APP);
}
@Test
@@ -517,86 +539,46 @@ public final class AppManifestConfigParserTest extends AdServicesUnitTestCase {
}
}
- private void assertAttributionConfigIsDefault(AppManifestConfig appManifestConfig) {
- AppManifestAttributionConfig attributionConfig = appManifestConfig.getAttributionConfig();
- assertApiConfigIsDefault("getAttributionConfig()", attributionConfig);
- expect.withMessage("isAllowedAttributionAccess()")
- .that(appManifestConfig.isAllowedAttributionAccess("not actually there"))
- .isTrue();
- }
-
- private void assertAttributionConfigIsFalse(AppManifestConfig appManifestConfig) {
- AppManifestAttributionConfig attributionConfig = appManifestConfig.getAttributionConfig();
- assertApiConfigIsFalse("getAttributionConfig()", attributionConfig);
- expect.withMessage("isAllowedAttributionAccess()")
- .that(appManifestConfig.isAllowedAttributionAccess("not actually there"))
- .isFalse();
- }
-
- private void assertCustomAudiencesConfigIsDefault(AppManifestConfig appManifestConfig) {
- AppManifestCustomAudiencesConfig customAudiencesConfig =
- appManifestConfig.getCustomAudiencesConfig();
- assertApiConfigIsDefault("getCustomAudiencesConfig()", customAudiencesConfig);
- expect.withMessage("isAllowedCustomAudiencesAccess()")
- .that(appManifestConfig.isAllowedCustomAudiencesAccess("not actually there"))
- .isTrue();
+ private void assertResult(String method, int actualResult, int expectedResult) {
+ expect.withMessage(
+ "%s (where %s=%s and %s=%s)",
+ method,
+ actualResult,
+ resultToString(actualResult),
+ expectedResult,
+ resultToString(expectedResult))
+ .that(actualResult)
+ .isEqualTo(expectedResult);
}
- private void assertCustomAudiencesConfigIsFalse(AppManifestConfig appManifestConfig) {
- AppManifestCustomAudiencesConfig customAudiencesConfig =
- appManifestConfig.getCustomAudiencesConfig();
- assertApiConfigIsFalse("getCustomAudiencesConfig()", customAudiencesConfig);
- expect.withMessage("isAllowedCustomAudiencesAccess()")
- .that(appManifestConfig.isAllowedCustomAudiencesAccess("not actually there"))
- .isFalse();
+ private void assertAttributionConfigIsAllowed(
+ AppManifestConfig appManifestConfig, int expectedResult) {
+ int actualResult = appManifestConfig.isAllowedAttributionAccess("not actually there");
+ assertResult("getAttributionConfig()", actualResult, expectedResult);
}
- private void assertTopicsConfigIsDefault(AppManifestConfig appManifestConfig) {
- AppManifestTopicsConfig topicsConfig = appManifestConfig.getTopicsConfig();
- assertApiConfigIsDefault("getTopicsConfig()", topicsConfig);
- expect.withMessage("isAllowedTopicsAccess()")
- .that(appManifestConfig.isAllowedTopicsAccess("not actually there"))
- .isTrue();
+ private void assertCustomAudienceConfigIsAllowed(
+ AppManifestConfig appManifestConfig, int expectedResult) {
+ int actualResult = appManifestConfig.isAllowedCustomAudiencesAccess("not actually there");
+ assertResult("getCustomAudiencesConfig()", actualResult, expectedResult);
}
- private void assertTopicsConfigIsFalse(AppManifestConfig appManifestConfig) {
- AppManifestTopicsConfig topicsConfig = appManifestConfig.getTopicsConfig();
- assertApiConfigIsFalse("getTopicsConfig()", topicsConfig);
- expect.withMessage("isAllowedTopicsAccess()")
- .that(appManifestConfig.isAllowedTopicsAccess("not actually there"))
- .isFalse();
+ private void assertTopicsConfigIsAllowed(
+ AppManifestConfig appManifestConfig, int expectedResult) {
+ int actualResult = appManifestConfig.isAllowedTopicsAccess("not actually there");
+ assertResult("getTopicsConfig()", actualResult, expectedResult);
}
- private void assertAdIdConfigIsDefault(AppManifestConfig appManifestConfig) {
- AppManifestAdIdConfig adIdConfig = appManifestConfig.getAdIdConfig();
- assertApiConfigIsDefault("getAdIdConfig()", adIdConfig);
- expect.withMessage("isAllowedAdIdAccess()")
- .that(appManifestConfig.isAllowedAdIdAccess("not actually there"))
- .isTrue();
- }
-
- private void assertAdIdConfigIsFalse(AppManifestConfig appManifestConfig) {
- AppManifestAdIdConfig adIdConfig = appManifestConfig.getAdIdConfig();
- assertApiConfigIsFalse("getAdIdConfig()", adIdConfig);
- expect.withMessage("isAllowedAdIdAccess()")
- .that(appManifestConfig.isAllowedAdIdAccess("not actually there"))
- .isFalse();
+ private void assertAdIdConfigIsAllowed(
+ AppManifestConfig appManifestConfig, int expectedResult) {
+ int actualResult = appManifestConfig.isAllowedAdIdAccess("not actually there");
+ assertResult("getAdIdConfig()", actualResult, expectedResult);
}
- private void assertAppSetIdConfigIsDefault(AppManifestConfig appManifestConfig) {
- AppManifestAppSetIdConfig appSetIdConfig = appManifestConfig.getAppSetIdConfig();
- assertApiConfigIsDefault("getAppSetIdConfig()", appSetIdConfig);
- expect.withMessage("isAllowedAppSetIdAccess()")
- .that(appManifestConfig.isAllowedAppSetIdAccess("not actually there"))
- .isTrue();
- }
-
- private void assertAppSetIdConfigIsFalse(AppManifestConfig appManifestConfig) {
- AppManifestAppSetIdConfig appSetIdConfig = appManifestConfig.getAppSetIdConfig();
- assertApiConfigIsFalse("getAppSetIdConfig()", appSetIdConfig);
- expect.withMessage("isAllowedAppSetIdAccess()")
- .that(appManifestConfig.isAllowedAppSetIdAccess("not actually there"))
- .isFalse();
+ private void assertAppSetIdConfigIsAllowed(
+ AppManifestConfig appManifestConfig, int expectedResult) {
+ int actualResult = appManifestConfig.isAllowedAppSetIdAccess("not actually there");
+ assertResult("getAppSetIdConfig()", actualResult, expectedResult);
}
private void assertApiConfigIsDefault(String name, AppManifestApiConfig config) {
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeAuthorizationFilterTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeAuthorizationFilterTest.java
index c4c187946..5460b2273 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeAuthorizationFilterTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeAuthorizationFilterTest.java
@@ -17,7 +17,6 @@
package com.android.adservices.service.common;
import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE;
-import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS;
import static android.adservices.common.AdServicesStatusUtils.STATUS_CALLER_NOT_ALLOWED;
import static android.adservices.common.AdServicesStatusUtils.STATUS_PERMISSION_NOT_REQUESTED;
import static android.adservices.common.AdServicesStatusUtils.STATUS_UNAUTHORIZED;
@@ -165,7 +164,7 @@ public final class FledgeAuthorizationFilterTest extends AdServicesExtendedMocki
}
@Test
- public void testAssertAppHasCaPermission_appHasPermission()
+ public void testAssertAppHasPermission_appHasPermission()
throws PackageManager.NameNotFoundException {
PackageInfo packageInfoGrant = new PackageInfo();
packageInfoGrant.requestedPermissions = new String[] {ACCESS_ADSERVICES_CUSTOM_AUDIENCE};
@@ -177,26 +176,7 @@ public final class FledgeAuthorizationFilterTest extends AdServicesExtendedMocki
when(PermissionHelper.hasCustomAudiencesPermission(CONTEXT, CONTEXT.getPackageName()))
.thenReturn(true);
- mChecker.assertAppDeclaredCustomAudiencePermission(
- CONTEXT, CustomAudienceFixture.VALID_OWNER, API_NAME_LOGGING_ID);
-
- verifyZeroInteractions(mPackageManagerMock, mEnrollmentDaoMock, mAdServicesLoggerMock);
- }
-
- @Test
- public void testAssertAppHasPasPermission_appHasPermission()
- throws PackageManager.NameNotFoundException {
- PackageInfo packageInfoGrant = new PackageInfo();
- packageInfoGrant.requestedPermissions = new String[] {ACCESS_ADSERVICES_PROTECTED_SIGNALS};
- doReturn(packageInfoGrant)
- .when(mPackageManagerMock)
- .getPackageInfo(
- eq(CustomAudienceFixture.VALID_OWNER), eq(PackageManager.GET_PERMISSIONS));
-
- when(PermissionHelper.hasProtectedSignalsPermission(CONTEXT, CONTEXT.getPackageName()))
- .thenReturn(true);
-
- mChecker.assertAppDeclaredProtectedSignalsPermission(
+ mChecker.assertAppDeclaredPermission(
CONTEXT, CustomAudienceFixture.VALID_OWNER, API_NAME_LOGGING_ID);
verifyZeroInteractions(mPackageManagerMock, mEnrollmentDaoMock, mAdServicesLoggerMock);
@@ -216,7 +196,7 @@ public final class FledgeAuthorizationFilterTest extends AdServicesExtendedMocki
assertThrows(
SecurityException.class,
() ->
- mChecker.assertAppDeclaredCustomAudiencePermission(
+ mChecker.assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
API_NAME_LOGGING_ID));
@@ -232,7 +212,7 @@ public final class FledgeAuthorizationFilterTest extends AdServicesExtendedMocki
}
@Test
- public void testAssertAppHasCaPermission_mismatchedAppPackageName_throwSecurityException()
+ public void testAssertAppHasPermission_mismatchedAppPackageName_throwSecurityException()
throws PackageManager.NameNotFoundException {
doReturn(new PackageInfo())
.when(mPackageManagerMock)
@@ -245,34 +225,7 @@ public final class FledgeAuthorizationFilterTest extends AdServicesExtendedMocki
assertThrows(
SecurityException.class,
() ->
- mChecker.assertAppDeclaredCustomAudiencePermission(
- CONTEXT, "mismatchedAppPackageName", API_NAME_LOGGING_ID));
-
- assertEquals(
- AdServicesStatusUtils.SECURITY_EXCEPTION_PERMISSION_NOT_REQUESTED_ERROR_MESSAGE,
- exception.getMessage());
- verify(mAdServicesLoggerMock)
- .logFledgeApiCallStats(
- eq(API_NAME_LOGGING_ID), eq(STATUS_PERMISSION_NOT_REQUESTED), anyInt());
- verifyNoMoreInteractions(mAdServicesLoggerMock);
- verifyZeroInteractions(mPackageManagerMock, mEnrollmentDaoMock);
- }
-
- @Test
- public void testAssertAppHasPasPermission_mismatchedAppPackageName_throwSecurityException()
- throws PackageManager.NameNotFoundException {
- doReturn(new PackageInfo())
- .when(mPackageManagerMock)
- .getPackageInfo(
- eq(CustomAudienceFixture.VALID_OWNER), eq(PackageManager.GET_PERMISSIONS));
- when(PermissionHelper.hasProtectedSignalsPermission(CONTEXT, CONTEXT.getPackageName()))
- .thenReturn(false);
-
- SecurityException exception =
- assertThrows(
- SecurityException.class,
- () ->
- mChecker.assertAppDeclaredProtectedSignalsPermission(
+ mChecker.assertAppDeclaredPermission(
CONTEXT, "mismatchedAppPackageName", API_NAME_LOGGING_ID));
assertEquals(
@@ -286,22 +239,11 @@ public final class FledgeAuthorizationFilterTest extends AdServicesExtendedMocki
}
@Test
- public void testAssertAppHasCaPermission_nullContext_throwNpe() {
- assertThrows(
- NullPointerException.class,
- () ->
- mChecker.assertAppDeclaredCustomAudiencePermission(
- null, CustomAudienceFixture.VALID_OWNER, API_NAME_LOGGING_ID));
-
- verifyZeroInteractions(mPackageManagerMock, mEnrollmentDaoMock, mAdServicesLoggerMock);
- }
-
- @Test
- public void testAssertAppHasPasPermission_nullContext_throwNpe() {
+ public void testAssertAppHasPermission_nullContext_throwNpe() {
assertThrows(
NullPointerException.class,
() ->
- mChecker.assertAppDeclaredProtectedSignalsPermission(
+ mChecker.assertAppDeclaredPermission(
null, CustomAudienceFixture.VALID_OWNER, API_NAME_LOGGING_ID));
verifyZeroInteractions(mPackageManagerMock, mEnrollmentDaoMock, mAdServicesLoggerMock);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeE2ETest.java
index e0cd17846..8e77cfdc3 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/FledgeE2ETest.java
@@ -122,7 +122,6 @@ import com.android.adservices.data.adselection.AdSelectionServerDatabase;
import com.android.adservices.data.adselection.AppInstallDao;
import com.android.adservices.data.adselection.DBAdSelectionDebugReport;
import com.android.adservices.data.adselection.EncryptionContextDao;
-import com.android.adservices.data.adselection.EncryptionKeyDao;
import com.android.adservices.data.adselection.FrequencyCapDao;
import com.android.adservices.data.adselection.SharedStorageDatabase;
import com.android.adservices.data.common.DBAdData;
@@ -132,6 +131,8 @@ import com.android.adservices.data.customaudience.CustomAudienceDao;
import com.android.adservices.data.customaudience.CustomAudienceDatabase;
import com.android.adservices.data.customaudience.DBCustomAudience;
import com.android.adservices.data.customaudience.DBTrustedBiddingData;
+import com.android.adservices.data.encryptionkey.EncryptionKeyDao;
+import com.android.adservices.data.enrollment.EnrollmentDao;
import com.android.adservices.data.signals.EncodedPayloadDao;
import com.android.adservices.data.signals.ProtectedSignalsDatabase;
import com.android.adservices.service.Flags;
@@ -323,6 +324,7 @@ public class FledgeE2ETest {
private AppInstallDao mAppInstallDao;
private FrequencyCapDao mFrequencyCapDao;
private EncryptionKeyDao mEncryptionKeyDao;
+ private EnrollmentDao mEnrollmentDao;
private EncryptionContextDao mEncryptionContextDao;
private ExecutorService mLightweightExecutorService;
private ExecutorService mBackgroundExecutorService;
@@ -389,8 +391,8 @@ public class FledgeE2ETest {
mFrequencyCapDao = sharedDb.frequencyCapDao();
AdSelectionServerDatabase serverDb =
Room.inMemoryDatabaseBuilder(CONTEXT_SPY, AdSelectionServerDatabase.class).build();
- mEncryptionContextDao = serverDb.encryptionContextDao();
- mEncryptionKeyDao = serverDb.encryptionKeyDao();
+ mEncryptionKeyDao = EncryptionKeyDao.getInstance(CONTEXT_SPY);
+ mEnrollmentDao = EnrollmentDao.getInstance(CONTEXT_SPY);
mAdFilteringFeatureFactory =
new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDao, DEFAULT_FLAGS);
@@ -1232,8 +1234,8 @@ public class FledgeE2ETest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -1393,8 +1395,8 @@ public class FledgeE2ETest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -2990,6 +2992,35 @@ public class FledgeE2ETest {
@Test
public void testFledgeFlowSuccessWithMockServer_ContextualAdsFlow() throws Exception {
+ // Reinitializing service so default flags are used
+ // Create an instance of AdSelection Service with real dependencies
+ mAdSelectionService =
+ new AdSelectionServiceImpl(
+ mAdSelectionEntryDao,
+ mAppInstallDao,
+ mCustomAudienceDao,
+ mEncodedPayloadDao,
+ mFrequencyCapDao,
+ mEncryptionKeyDao,
+ mEnrollmentDao,
+ mAdServicesHttpsClient,
+ mDevContextFilterMock,
+ mLightweightExecutorService,
+ mBackgroundExecutorService,
+ mScheduledExecutor,
+ CONTEXT_SPY,
+ mAdServicesLogger,
+ DEFAULT_FLAGS,
+ CallingAppUidSupplierProcessImpl.create(),
+ mFledgeAuthorizationFilterMock,
+ mAdSelectionServiceFilterMock,
+ mAdFilteringFeatureFactory,
+ mConsentManagerMock,
+ mObliviousHttpEncryptorMock,
+ mAdSelectionDebugReportDao,
+ mAdIdFetcher,
+ false);
+
doReturn(AdServicesApiConsent.GIVEN)
.when(mConsentManagerMock)
.getConsent(AdServicesApiType.FLEDGE);
@@ -4335,8 +4366,8 @@ public class FledgeE2ETest {
mCustomAudienceDao,
mEncodedPayloadDao,
mFrequencyCapDao,
- mEncryptionContextDao,
mEncryptionKeyDao,
+ mEnrollmentDao,
mAdServicesHttpsClient,
mDevContextFilterMock,
mLightweightExecutorService,
@@ -4955,11 +4986,12 @@ public class FledgeE2ETest {
AdTechIdentifier.fromString(
mockWebServerRule.uriForPath(BUYER_BIDDING_LOGIC_URI_PATH).getHost());
SignedContextualAds contextualAds =
- SignedContextualAdsFixture.generateSignedContextualAds(
- buyer, ImmutableList.of(100.0, 200.0, 300.0, 400.0, 500.0))
- .setDecisionLogicUri(
- mockWebServerRule.uriForPath(BUYER_BIDDING_LOGIC_URI_PATH))
- .build();
+ SignedContextualAdsFixture.signContextualAds(
+ SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder(
+ buyer, ImmutableList.of(100.0, 200.0, 300.0, 400.0, 500.0))
+ .setDecisionLogicUri(
+ mockWebServerRule.uriForPath(
+ BUYER_BIDDING_LOGIC_URI_PATH)));
buyerContextualAds.put(buyer, contextualAds);
return buyerContextualAds;
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PackageChangedReceiverTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PackageChangedReceiverTest.java
index 03635db38..7c4f4297c 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PackageChangedReceiverTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PackageChangedReceiverTest.java
@@ -16,6 +16,8 @@
package com.android.adservices.service.common;
+import static android.adservices.common.CommonFixture.doSleep;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyLong;
@@ -64,6 +66,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.modules.utils.build.SdkLevel;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -326,6 +329,7 @@ public class PackageChangedReceiverTest {
@Test
public void testReceivePackageFullyRemoved_consent_noPackageUid()
throws InterruptedException, IOException {
+ Assume.assumeTrue(SdkLevel.isAtLeastS());
Intent intent =
createIntentSentByAdServiceSystemService(
PackageChangedReceiver.PACKAGE_FULLY_REMOVED);
@@ -342,6 +346,7 @@ public class PackageChangedReceiverTest {
@Test
public void testReceivePackageFullyRemoved_consent_packageUidIsExplicitlyDefault()
throws InterruptedException, IOException {
+ Assume.assumeTrue(SdkLevel.isAtLeastS());
Intent intent =
createIntentSentByAdServiceSystemService(
PackageChangedReceiver.PACKAGE_FULLY_REMOVED);
@@ -354,6 +359,7 @@ public class PackageChangedReceiverTest {
@Test
public void testReceivePackageFullyRemoved_consent_noPackageUid_backCompat()
throws InterruptedException, IOException {
+ Assume.assumeTrue(SdkLevel.isAtLeastS());
Intent intent = createIntentSentBySystem(Intent.ACTION_PACKAGE_FULLY_REMOVED);
intent.removeExtra(Intent.EXTRA_UID);
@@ -364,6 +370,7 @@ public class PackageChangedReceiverTest {
@Test
public void testReceivePackageFullyRemoved_consent_packageUidIsExplicitlyDefault_backCompat()
throws InterruptedException, IOException {
+ Assume.assumeTrue(SdkLevel.isAtLeastS());
Intent intent = createIntentSentBySystem(Intent.ACTION_PACKAGE_FULLY_REMOVED);
intent.putExtra(Intent.EXTRA_UID, DEFAULT_PACKAGE_UID);
@@ -711,6 +718,7 @@ public class PackageChangedReceiverTest {
}
private void runPackageFullyRemovedForConsent(Intent intent) throws Exception {
+ Assume.assumeTrue(SdkLevel.isAtLeastS());
// Start a mockitoSession to mock static method
// Lenient added to allow easy disabling of other APIs' methods
MockitoSession session =
@@ -1159,4 +1167,35 @@ public class PackageChangedReceiverTest {
mMockitoSession.finishMocking();
}
}
+
+ @Test
+ public void testAppConsentDeletion_onR() throws Exception {
+ MockitoSession mMockitoSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(SdkLevel.class)
+ .mockStatic(ConsentManager.class)
+ .strictness(Strictness.LENIENT)
+ .initMocks(this)
+ .startMocking();
+ try {
+ ExtendedMockito.doReturn(false).when(SdkLevel::isAtLeastS);
+ doReturn(mConsentManager).when(() -> ConsentManager.getInstance(any()));
+ PackageChangedReceiver spyReceiver = createSpyPackageReceiverForConsent();
+ Intent intent =
+ createIntentSentByAdServiceSystemService(
+ PackageChangedReceiver.PACKAGE_FULLY_REMOVED);
+ doReturn(false).when(spyReceiver).isPackageStillInstalled(any(), anyString());
+
+ // Invoke the onReceive method to test the behavior
+ spyReceiver.onReceive(sContext, intent);
+
+ verify(spyReceiver).consentOnPackageFullyRemoved(any(), any(), anyInt());
+ doSleep(BACKGROUND_THREAD_TIMEOUT_MS);
+
+ // On R App consent clear should not be called as it is not supported
+ verify(mConsentManager, never()).clearConsentForUninstalledApp(any(), anyInt());
+ } finally {
+ mMockitoSession.finishMocking();
+ }
+ }
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PermissionHelperTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PermissionHelperTest.java
index e723d48ab..652ba36e6 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PermissionHelperTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/PermissionHelperTest.java
@@ -19,7 +19,6 @@ package com.android.adservices.service.common;
import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_AD_ID;
import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_ATTRIBUTION;
import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_CUSTOM_AUDIENCE;
-import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_PROTECTED_SIGNALS;
import static android.adservices.common.AdServicesPermissions.ACCESS_ADSERVICES_TOPICS;
import static com.google.common.truth.Truth.assertThat;
@@ -67,8 +66,7 @@ public class PermissionHelperTest {
ACCESS_ADSERVICES_TOPICS,
ACCESS_ADSERVICES_AD_ID,
ACCESS_ADSERVICES_ATTRIBUTION,
- ACCESS_ADSERVICES_CUSTOM_AUDIENCE,
- ACCESS_ADSERVICES_PROTECTED_SIGNALS
+ ACCESS_ADSERVICES_CUSTOM_AUDIENCE
};
doReturn(packageInfoGrant)
.when(mMockPackageManagerGrant)
@@ -170,10 +168,6 @@ public class PermissionHelperTest {
getMockContext(ACCESS_ADSERVICES_CUSTOM_AUDIENCE, mMockPackageManagerGrant);
assertThat(PermissionHelper.hasCustomAudiencesPermission(mockContext3, APP_PACKAGE_NAME))
.isTrue();
- Context mockContext4 =
- getMockContext(ACCESS_ADSERVICES_PROTECTED_SIGNALS, mMockPackageManagerGrant);
- assertThat(PermissionHelper.hasProtectedSignalsPermission(mockContext4, APP_PACKAGE_NAME))
- .isTrue();
}
@Test
@@ -191,8 +185,6 @@ public class PermissionHelperTest {
.isFalse();
assertThat(PermissionHelper.hasCustomAudiencesPermission(mockContext, APP_PACKAGE_NAME))
.isFalse();
- assertThat(PermissionHelper.hasProtectedSignalsPermission(mockContext, APP_PACKAGE_NAME))
- .isFalse();
assertThat(PermissionHelper.hasAccessAdServicesStatePermission(mockContext)).isFalse();
assertThat(PermissionHelper.hasModifyAdServicesStatePermission(mockContext)).isFalse();
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/consent/ConsentMigrationUtilsTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/consent/ConsentMigrationUtilsTest.java
index 3525f21ad..fd4e96d75 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/consent/ConsentMigrationUtilsTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/consent/ConsentMigrationUtilsTest.java
@@ -24,6 +24,7 @@ import static android.adservices.extdata.AdServicesExtDataParams.STATE_UNKNOWN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.never;
@@ -42,6 +43,8 @@ import com.android.adservices.data.common.BooleanFileDatastore;
import com.android.adservices.mockito.AdServicesExtendedMockitoRule;
import com.android.adservices.service.appsearch.AppSearchConsentManager;
import com.android.adservices.service.extdata.AdServicesExtDataStorageServiceManager;
+import com.android.adservices.service.stats.ConsentMigrationStats;
+import com.android.adservices.service.stats.StatsdAdServicesLogger;
import com.android.modules.utils.build.SdkLevel;
import org.junit.Rule;
@@ -68,9 +71,14 @@ public class ConsentMigrationUtilsTest {
.setManualInteractionWithConsentStatus(STATE_UNKNOWN)
.build();
+ private static final int REGION_ROW_CODE = 2;
+
@Rule
public final AdServicesExtendedMockitoRule mExtendedMockitoRule =
- new AdServicesExtendedMockitoRule.Builder(this).spyStatic(SdkLevel.class).build();
+ new AdServicesExtendedMockitoRule.Builder(this)
+ .spyStatic(SdkLevel.class)
+ .spyStatic(DeviceRegionProvider.class)
+ .build();
@Spy private final Context mContextSpy = ApplicationProvider.getApplicationContext();
@Mock private BooleanFileDatastore mDatastoreMock;
@@ -79,6 +87,7 @@ public class ConsentMigrationUtilsTest {
@Mock private SharedPreferences mSharedPreferencesMock;
@Mock private SharedPreferences.Editor mSharedPreferencesEditorMock;
@Mock private AdServicesExtDataParams mAdServicesExtDataParamsMock;
+ @Mock private StatsdAdServicesLogger mStatsdAdServicesLoggerMock;
@Test
public void testHandleConsentMigrationToAppSearchIfNeeded_onR_skipsMigration() {
@@ -89,10 +98,12 @@ public class ConsentMigrationUtilsTest {
mContextSpy,
mDatastoreMock,
mAppSearchConsentManagerMock,
- mAdServicesExtDataManagerMock);
+ mAdServicesExtDataManagerMock,
+ mStatsdAdServicesLoggerMock);
verifyZeroInteractions(mAppSearchConsentManagerMock);
verifyZeroInteractions(mAdServicesExtDataManagerMock);
+ verifyZeroInteractions(mStatsdAdServicesLoggerMock);
}
@Test
@@ -103,10 +114,12 @@ public class ConsentMigrationUtilsTest {
mContextSpy,
mDatastoreMock,
mAppSearchConsentManagerMock,
- mAdServicesExtDataManagerMock);
+ mAdServicesExtDataManagerMock,
+ mStatsdAdServicesLoggerMock);
verifyZeroInteractions(mAppSearchConsentManagerMock);
verifyZeroInteractions(mAdServicesExtDataManagerMock);
+ verifyZeroInteractions(mStatsdAdServicesLoggerMock);
}
@Test
@@ -115,10 +128,15 @@ public class ConsentMigrationUtilsTest {
mockSDevice();
ConsentMigrationUtils.handleConsentMigrationToAppSearchIfNeeded(
- mContextSpy, mDatastoreMock, mAppSearchConsentManagerMock, null);
+ mContextSpy,
+ mDatastoreMock,
+ mAppSearchConsentManagerMock,
+ null,
+ mStatsdAdServicesLoggerMock);
verifyZeroInteractions(mAdServicesExtDataManagerMock);
verifyZeroInteractions(mAppSearchConsentManagerMock);
+ verifyZeroInteractions(mStatsdAdServicesLoggerMock);
}
@Test
@@ -136,10 +154,12 @@ public class ConsentMigrationUtilsTest {
mContextSpy,
mDatastoreMock,
mAppSearchConsentManagerMock,
- mAdServicesExtDataManagerMock);
+ mAdServicesExtDataManagerMock,
+ mStatsdAdServicesLoggerMock);
verifyZeroInteractions(mAppSearchConsentManagerMock);
verifyZeroInteractions(mAdServicesExtDataManagerMock);
+ verifyZeroInteractions(mStatsdAdServicesLoggerMock);
}
@Test
@@ -157,12 +177,14 @@ public class ConsentMigrationUtilsTest {
mContextSpy,
mDatastoreMock,
mAppSearchConsentManagerMock,
- mAdServicesExtDataManagerMock);
+ mAdServicesExtDataManagerMock,
+ mStatsdAdServicesLoggerMock);
verify(mAppSearchConsentManagerMock).wasU18NotificationDisplayed();
verifyNoMoreInteractions(mAppSearchConsentManagerMock);
verifyZeroInteractions(mAdServicesExtDataManagerMock);
+ verifyZeroInteractions(mStatsdAdServicesLoggerMock);
}
@Test
@@ -183,7 +205,8 @@ public class ConsentMigrationUtilsTest {
mContextSpy,
mDatastoreMock,
mAppSearchConsentManagerMock,
- mAdServicesExtDataManagerMock);
+ mAdServicesExtDataManagerMock,
+ mStatsdAdServicesLoggerMock);
verify(mAppSearchConsentManagerMock).wasU18NotificationDisplayed();
verify(mAppSearchConsentManagerMock).wasGaUxNotificationDisplayed();
@@ -192,6 +215,7 @@ public class ConsentMigrationUtilsTest {
verify(mAdServicesExtDataManagerMock).getAdServicesExtData();
verifyNoMoreInteractions(mAdServicesExtDataManagerMock);
+ verifyZeroInteractions(mStatsdAdServicesLoggerMock);
}
@Test
@@ -211,11 +235,14 @@ public class ConsentMigrationUtilsTest {
when(mSharedPreferencesMock.edit()).thenReturn(mSharedPreferencesEditorMock);
when(mSharedPreferencesEditorMock.commit()).thenReturn(true);
+ doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any()));
+
ConsentMigrationUtils.handleConsentMigrationToAppSearchIfNeeded(
mContextSpy,
mDatastoreMock,
mAppSearchConsentManagerMock,
- mAdServicesExtDataManagerMock);
+ mAdServicesExtDataManagerMock,
+ mStatsdAdServicesLoggerMock);
verify(mAppSearchConsentManagerMock).wasU18NotificationDisplayed();
verify(mAppSearchConsentManagerMock).wasGaUxNotificationDisplayed();
@@ -241,6 +268,21 @@ public class ConsentMigrationUtilsTest {
verify(mAdServicesExtDataManagerMock).getAdServicesExtData();
verify(mAdServicesExtDataManagerMock).clearDataOnOtaAsync();
verifyNoMoreInteractions(mAdServicesExtDataManagerMock);
+
+ ConsentMigrationStats consentMigrationStats =
+ ConsentMigrationStats.builder()
+ .setTopicsConsent(false)
+ .setFledgeConsent(false)
+ .setMsmtConsent(false)
+ .setDefaultConsent(true)
+ .setMigrationStatus(
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_UPDATED)
+ .setMigrationType(
+ ConsentMigrationStats.MigrationType.ADEXT_SERVICE_TO_APPSEARCH)
+ .setRegion(REGION_ROW_CODE)
+ .build();
+ verify(mStatsdAdServicesLoggerMock).logConsentMigrationStats(consentMigrationStats);
}
@Test
@@ -260,11 +302,14 @@ public class ConsentMigrationUtilsTest {
when(mSharedPreferencesMock.edit()).thenReturn(mSharedPreferencesEditorMock);
when(mSharedPreferencesEditorMock.commit()).thenReturn(false);
+ doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any()));
+
ConsentMigrationUtils.handleConsentMigrationToAppSearchIfNeeded(
mContextSpy,
mDatastoreMock,
mAppSearchConsentManagerMock,
- mAdServicesExtDataManagerMock);
+ mAdServicesExtDataManagerMock,
+ mStatsdAdServicesLoggerMock);
verify(mAppSearchConsentManagerMock).wasU18NotificationDisplayed();
verify(mAppSearchConsentManagerMock).wasGaUxNotificationDisplayed();
@@ -291,6 +336,21 @@ public class ConsentMigrationUtilsTest {
verify(mAdServicesExtDataManagerMock).getAdServicesExtData();
verify(mAdServicesExtDataManagerMock).clearDataOnOtaAsync();
verifyNoMoreInteractions(mAdServicesExtDataManagerMock);
+
+ ConsentMigrationStats consentMigrationStats =
+ ConsentMigrationStats.builder()
+ .setTopicsConsent(false)
+ .setFledgeConsent(false)
+ .setMsmtConsent(true)
+ .setDefaultConsent(false)
+ .setMigrationStatus(
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_NOT_UPDATED)
+ .setMigrationType(
+ ConsentMigrationStats.MigrationType.ADEXT_SERVICE_TO_APPSEARCH)
+ .setRegion(REGION_ROW_CODE)
+ .build();
+ verify(mStatsdAdServicesLoggerMock).logConsentMigrationStats(consentMigrationStats);
}
private void mockNoNotifOnS() {
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceEndToEndTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceEndToEndTest.java
index a6b65749a..6652bb25f 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceEndToEndTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceEndToEndTest.java
@@ -359,7 +359,7 @@ public class CustomAudienceServiceEndToEndTest {
// Bypass the permission check since it's enforced before the package name check
doNothing()
.when(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
otherOwnerPackageName,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -381,7 +381,7 @@ public class CustomAudienceServiceEndToEndTest {
CommonFixture.VALID_BUYER_1,
VALID_NAME));
verify(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
otherOwnerPackageName,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -752,7 +752,7 @@ public class CustomAudienceServiceEndToEndTest {
// Bypass the permission check since it's enforced before the package name check
doNothing()
.when(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
otherOwnerPackageName,
AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE);
@@ -766,7 +766,7 @@ public class CustomAudienceServiceEndToEndTest {
AdServicesStatusUtils.SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ON_BEHALF_ERROR_MESSAGE,
callback.getException().getMessage());
verify(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
otherOwnerPackageName,
AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE);
@@ -971,7 +971,7 @@ public class CustomAudienceServiceEndToEndTest {
// Bypass the permission check since it's enforced before the package name check
doNothing()
.when(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
MY_APP_PACKAGE_NAME,
AD_SERVICES_API_CALLED__API_NAME__OVERRIDE_CUSTOM_AUDIENCE_REMOTE_INFO);
@@ -995,7 +995,7 @@ public class CustomAudienceServiceEndToEndTest {
mCustomAudienceDao.doesCustomAudienceOverrideExist(otherOwner, BUYER_1, NAME_1));
verify(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
MY_APP_PACKAGE_NAME,
AD_SERVICES_API_CALLED__API_NAME__OVERRIDE_CUSTOM_AUDIENCE_REMOTE_INFO);
@@ -1107,7 +1107,7 @@ public class CustomAudienceServiceEndToEndTest {
// Bypass the permission check since it's enforced before the package name check
doNothing()
.when(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
incorrectPackageName,
AD_SERVICES_API_CALLED__API_NAME__REMOVE_CUSTOM_AUDIENCE_REMOTE_INFO_OVERRIDE);
@@ -1135,7 +1135,7 @@ public class CustomAudienceServiceEndToEndTest {
mCustomAudienceDao.doesCustomAudienceOverrideExist(
MY_APP_PACKAGE_NAME, BUYER_1, NAME_1));
verify(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
incorrectPackageName,
AD_SERVICES_API_CALLED__API_NAME__REMOVE_CUSTOM_AUDIENCE_REMOTE_INFO_OVERRIDE);
@@ -1289,7 +1289,7 @@ public class CustomAudienceServiceEndToEndTest {
// Bypass the permission check since it's enforced before the package name check
doNothing()
.when(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
incorrectPackageName,
AD_SERVICES_API_CALLED__API_NAME__RESET_ALL_CUSTOM_AUDIENCE_OVERRIDES);
@@ -1334,7 +1334,7 @@ public class CustomAudienceServiceEndToEndTest {
mCustomAudienceDao.doesCustomAudienceOverrideExist(
MY_APP_PACKAGE_NAME, BUYER_2, NAME_2));
verify(mFledgeAuthorizationFilterSpy)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
incorrectPackageName,
AD_SERVICES_API_CALLED__API_NAME__RESET_ALL_CUSTOM_AUDIENCE_OVERRIDES);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceImplTest.java
index 1073c08da..709c6bd74 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/customaudience/CustomAudienceServiceImplTest.java
@@ -212,7 +212,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
CustomAudienceFixture.VALID_OWNER,
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -260,7 +260,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
CustomAudienceFixture.VALID_OWNER,
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
any(),
eq(CustomAudienceFixture.VALID_OWNER),
eq(AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE));
@@ -326,7 +326,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock));
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -349,7 +349,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -416,7 +416,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -464,7 +464,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -513,7 +513,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
CustomAudienceFixture.VALID_OWNER,
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -620,7 +620,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mFetchAndJoinCustomAudienceCallbackMock));
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__FETCH_AND_JOIN_CUSTOM_AUDIENCE);
@@ -638,7 +638,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
any(),
eq(CustomAudienceFixture.VALID_OWNER),
eq(AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE));
@@ -682,7 +682,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
any(),
eq(CustomAudienceFixture.VALID_OWNER),
eq(AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE));
@@ -749,7 +749,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock));
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
any(),
eq(CustomAudienceFixture.VALID_OWNER),
eq(AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE));
@@ -773,7 +773,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
any(),
eq(CustomAudienceFixture.VALID_OWNER),
eq(AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE));
@@ -862,7 +862,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
any(),
eq(CustomAudienceFixture.VALID_OWNER),
eq(AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE));
@@ -910,7 +910,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
.assertCallerIsInForeground(
MY_UID, AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE, null);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
any(),
eq(CustomAudienceFixture.VALID_OWNER),
eq(AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE));
@@ -954,7 +954,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -1003,7 +1003,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
CustomAudienceFixture.VALID_OWNER,
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -1050,7 +1050,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE);
@@ -1102,7 +1102,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE);
@@ -1158,7 +1158,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mCustomAudienceOverrideCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
"",
AD_SERVICES_API_CALLED__API_NAME__OVERRIDE_CUSTOM_AUDIENCE_REMOTE_INFO);
@@ -1222,7 +1222,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mCustomAudienceOverrideCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__OVERRIDE_CUSTOM_AUDIENCE_REMOTE_INFO);
@@ -1268,8 +1268,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
CustomAudienceFixture.VALID_NAME,
mCustomAudienceOverrideCallbackMock);
- verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(CONTEXT, "", apiName);
+ verify(mFledgeAuthorizationFilterMock).assertAppDeclaredPermission(CONTEXT, "", apiName);
verify(mDevContextFilterMock).createDevContext();
verify(mCustomAudienceImplMock).getCustomAudienceDao();
verify(mAppImportanceFilterMock)
@@ -1322,8 +1321,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mCustomAudienceOverrideCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
- CONTEXT, CustomAudienceFixture.VALID_OWNER, apiName);
+ .assertAppDeclaredPermission(CONTEXT, CustomAudienceFixture.VALID_OWNER, apiName);
verify(mDevContextFilterMock).createDevContext();
verify(mCustomAudienceImplMock).getCustomAudienceDao();
verify(mConsentManagerMock).isFledgeConsentRevokedForApp(CustomAudienceFixture.VALID_OWNER);
@@ -1352,8 +1350,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mService.resetAllCustomAudienceOverrides(mCustomAudienceOverrideCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
- CONTEXT, CustomAudienceFixture.VALID_OWNER, apiName);
+ .assertAppDeclaredPermission(CONTEXT, CustomAudienceFixture.VALID_OWNER, apiName);
verify(mDevContextFilterMock).createDevContext();
verify(mCustomAudienceImplMock).getCustomAudienceDao();
verify(mAppImportanceFilterMock).assertCallerIsInForeground(Process.myUid(), apiName, null);
@@ -1400,7 +1397,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mService.resetAllCustomAudienceOverrides(mCustomAudienceOverrideCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__RESET_ALL_CUSTOM_AUDIENCE_OVERRIDES);
@@ -1419,7 +1416,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
public void testAppManifestPermissionNotRequested_joinCustomAudience_fails() {
doThrow(SecurityException.class)
.when(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -1437,7 +1434,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
public void testAppManifestPermissionNotRequested_fetchCustomAudience_fails() {
doThrow(SecurityException.class)
.when(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__FETCH_AND_JOIN_CUSTOM_AUDIENCE);
@@ -1458,7 +1455,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
public void testAppManifestPermissionNotRequested_leaveCustomAudience_fails() {
doThrow(SecurityException.class)
.when(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE);
@@ -1483,7 +1480,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
.build());
doThrow(SecurityException.class)
.when(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__OVERRIDE_CUSTOM_AUDIENCE_REMOTE_INFO);
@@ -1513,8 +1510,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
int apiName = AD_SERVICES_API_CALLED__API_NAME__REMOVE_CUSTOM_AUDIENCE_REMOTE_INFO_OVERRIDE;
doThrow(SecurityException.class)
.when(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
- CONTEXT, CustomAudienceFixture.VALID_OWNER, apiName);
+ .assertAppDeclaredPermission(CONTEXT, CustomAudienceFixture.VALID_OWNER, apiName);
assertThrows(
SecurityException.class,
@@ -1536,7 +1532,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
.build());
doThrow(SecurityException.class)
.when(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__RESET_ALL_CUSTOM_AUDIENCE_OVERRIDES);
@@ -1565,7 +1561,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -1621,7 +1617,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
CustomAudienceFixture.VALID_OWNER,
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -1667,7 +1663,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE);
@@ -1725,7 +1721,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
mICustomAudienceCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
any(),
eq(CustomAudienceFixture.VALID_OWNER),
eq(AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE));
@@ -1771,7 +1767,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
CommonFixture.VALID_BUYER_1,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -1811,7 +1807,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
CommonFixture.VALID_BUYER_1,
AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE);
@@ -1850,7 +1846,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
RATE_LIMIT_REACHED_ERROR_MESSAGE,
actualResponseCaptor.getValue().getErrorMessage());
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__JOIN_CUSTOM_AUDIENCE);
@@ -1881,7 +1877,7 @@ public final class CustomAudienceServiceImplTest extends AdServicesExtendedMocki
RATE_LIMIT_REACHED_ERROR_MESSAGE,
actualResponseCaptor.getValue().getErrorMessage());
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredCustomAudiencePermission(
+ .assertAppDeclaredPermission(
CONTEXT,
CustomAudienceFixture.VALID_OWNER,
AD_SERVICES_API_CALLED__API_NAME__LEAVE_CUSTOM_AUDIENCE);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/E2EInteropMockTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/E2EInteropMockTest.java
index 0e5544e83..74f8761d6 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/E2EInteropMockTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/E2EInteropMockTest.java
@@ -21,7 +21,6 @@ import static java.util.Map.entry;
import android.adservices.measurement.RegistrationRequest;
import android.net.Uri;
import android.os.RemoteException;
-import android.provider.DeviceConfig;
import com.android.adservices.service.measurement.actions.Action;
import com.android.adservices.service.measurement.actions.RegisterSource;
@@ -35,7 +34,6 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Assert;
-import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -160,17 +158,6 @@ public class E2EInteropMockTest extends E2EMockTest {
mFlags);
}
- @Before
- public void setup() {
- // Chromium does not have a flag at dynamic noising based on expiry but Android does, so it
- // needs to be enabled.
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_ADSERVICES,
- "measurement_enable_configurable_event_reporting_windows",
- "true",
- false);
- }
-
@Override
void processAction(RegisterSource sourceRegistration) throws JSONException, IOException {
RegistrationRequest request = sourceRegistration.mRegistrationRequest;
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/EventReportTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/EventReportTest.java
index f0be0f676..ca528c9a3 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/EventReportTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/EventReportTest.java
@@ -15,11 +15,7 @@
*/
package com.android.adservices.service.measurement;
-import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY;
import static com.android.adservices.service.Flags.MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS;
-import static com.android.adservices.service.Flags.MEASUREMENT_NAVIGATION_NOISE_PROBABILITY;
import static com.android.adservices.service.measurement.PrivacyParams.INSTALL_ATTR_NAVIGATION_EARLY_REPORTING_WINDOW_MILLISECONDS;
import static com.android.adservices.service.measurement.PrivacyParams.NAVIGATION_EARLY_REPORTING_WINDOW_MILLISECONDS;
import static com.android.adservices.service.measurement.SourceFixture.ValidSourceParams;
@@ -67,6 +63,11 @@ public final class EventReportTest {
public final TestableDeviceConfig.TestableDeviceConfigRule mDeviceConfigRule =
new TestableDeviceConfig.TestableDeviceConfigRule();
+ private static final double EVENT_NOISE_PROBABILITY = 0.0000025D;
+ private static final double INSTALL_ATTR_EVENT_NOISE_PROBABILITY = 0.0000125D;
+ private static final double INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY = 0.0024263D;
+ private static final double NAVIGATION_NOISE_PROBABILITY = 0.0024263D;
+
private static final double DOUBLE_MAX_DELTA = 0.0000001D;
private static final long TRIGGER_PRIORITY = 345678L;
@@ -288,7 +289,7 @@ public final class EventReportTest {
assertEquals(source.getEventReportWindow() + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
report.getReportTime());
assertEquals(source.getSourceType(), report.getSourceType());
- assertEquals(MEASUREMENT_EVENT_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
+ assertEquals(EVENT_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
assertEquals(TRIGGER_ID, report.getTriggerId());
assertEquals(REGISTRATION_ORIGIN, report.getRegistrationOrigin());
@@ -297,7 +298,6 @@ public final class EventReportTest {
@Test
public void populate_eventSourceAppDestWithoutInstallConfigured() throws JSONException {
long baseTime = System.currentTimeMillis();
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
String earlyReportingWindows1h1d =
String.join(
",",
@@ -306,7 +306,6 @@ public final class EventReportTest {
doReturn(earlyReportingWindows1h1d)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(true).when(mFlags).getMeasurementEnableVtcConfigurableMaxEventReports();
doReturn(3).when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
Source source =
createSourceForTest(
@@ -390,7 +389,7 @@ public final class EventReportTest {
report.getReportTime());
assertEquals(Source.SourceType.NAVIGATION, report.getSourceType());
assertEquals(
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
+ NAVIGATION_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
assertEquals(TRIGGER_ID, report.getTriggerId());
assertEquals(REGISTRATION_ORIGIN, report.getRegistrationOrigin());
@@ -430,7 +429,7 @@ public final class EventReportTest {
assertEquals(source.getEventReportWindow() + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
report.getReportTime());
assertEquals(Source.SourceType.EVENT, report.getSourceType());
- assertEquals(MEASUREMENT_EVENT_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
+ assertEquals(EVENT_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
assertEquals(TRIGGER_ID, report.getTriggerId());
assertEquals(REGISTRATION_ORIGIN, report.getRegistrationOrigin());
@@ -468,7 +467,7 @@ public final class EventReportTest {
report.getReportTime());
assertEquals(Source.SourceType.EVENT, report.getSourceType());
assertEquals(
- MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY,
+ INSTALL_ATTR_EVENT_NOISE_PROBABILITY,
report.getRandomizedTriggerRate(),
DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
@@ -507,7 +506,7 @@ public final class EventReportTest {
assertEquals(source.getEventReportWindow() + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
report.getReportTime());
assertEquals(Source.SourceType.EVENT, report.getSourceType());
- assertEquals(MEASUREMENT_EVENT_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
+ assertEquals(EVENT_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
assertEquals(TRIGGER_ID, report.getTriggerId());
assertEquals(REGISTRATION_ORIGIN, report.getRegistrationOrigin());
@@ -548,7 +547,7 @@ public final class EventReportTest {
report.getReportTime());
assertEquals(Source.SourceType.NAVIGATION, report.getSourceType());
assertEquals(
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
+ NAVIGATION_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
assertEquals(TRIGGER_ID, report.getTriggerId());
assertEquals(REGISTRATION_ORIGIN, report.getRegistrationOrigin());
@@ -589,7 +588,7 @@ public final class EventReportTest {
report.getReportTime());
assertEquals(source.getSourceType(), report.getSourceType());
assertEquals(
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
+ NAVIGATION_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
assertEquals(TRIGGER_ID, report.getTriggerId());
assertEquals(REGISTRATION_ORIGIN, report.getRegistrationOrigin());
@@ -633,7 +632,7 @@ public final class EventReportTest {
report.getReportTime());
assertEquals(Source.SourceType.NAVIGATION, report.getSourceType());
assertEquals(
- MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY,
+ INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY,
report.getRandomizedTriggerRate(),
DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
@@ -679,7 +678,7 @@ public final class EventReportTest {
report.getReportTime());
assertEquals(source.getSourceType(), report.getSourceType());
assertEquals(
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
+ NAVIGATION_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
assertEquals(TRIGGER_ID, report.getTriggerId());
assertEquals(REGISTRATION_ORIGIN, report.getRegistrationOrigin());
@@ -698,6 +697,7 @@ public final class EventReportTest {
.setEnrollmentId("enrollment-id")
.setAppDestinations(Collections.singletonList(APP_DESTINATION))
.setWebDestinations(Collections.singletonList(WEB_DESTINATION))
+ .setExpiryTime(baseTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(baseTime + TimeUnit.DAYS.toMillis(10))
.setCoarseEventReportDestinations(true)
.build();
@@ -738,7 +738,7 @@ public final class EventReportTest {
assertEquals(source.getEventReportWindow() + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
report.getReportTime());
assertEquals(Source.SourceType.EVENT, report.getSourceType());
- assertEquals(MEASUREMENT_EVENT_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
+ assertEquals(EVENT_NOISE_PROBABILITY, report.getRandomizedTriggerRate(), DOUBLE_MAX_DELTA);
assertEquals(SOURCE_ID, report.getSourceId());
assertEquals(TRIGGER_ID, report.getTriggerId());
assertEquals(REGISTRATION_ORIGIN, report.getRegistrationOrigin());
@@ -855,6 +855,7 @@ public final class EventReportTest {
.setEnrollmentId("enrollment-id")
.setAppDestinations(getNullableUriList(appDestination))
.setWebDestinations(getNullableUriList(webDestination))
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(10))
.build();
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/SourceTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/SourceTest.java
index 458efd4f0..f75c65e24 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/SourceTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/SourceTest.java
@@ -1521,13 +1521,13 @@ public class SourceTest {
}
@Test
- public void getOrDefaultEventReportWindows() throws JSONException {
+ public void getOrDefaultEventReportWindowsForFlex() throws JSONException {
Flags flags = mock(Flags.class);
JSONObject windowsObj = new JSONObject("{'start_time': '2000000', 'end_times': "
+ "[3600000, 86400000, 172000000]}");
// Provided Windows
List<Pair<Long, Long>> eventReportWindows =
- Source.getOrDefaultEventReportWindows(
+ Source.getOrDefaultEventReportWindowsForFlex(
windowsObj,
Source.SourceType.EVENT,
8640000,
@@ -1543,7 +1543,7 @@ public class SourceTest {
when(flags.getMeasurementEventReportsCtcEarlyReportingWindows())
.thenReturn("172800,604800");
eventReportWindows =
- Source.getOrDefaultEventReportWindows(
+ Source.getOrDefaultEventReportWindowsForFlex(
null, Source.SourceType.EVENT, TimeUnit.DAYS.toMillis(15), flags);
assertNotNull(eventReportWindows);
assertEquals(2, eventReportWindows.size());
@@ -1552,7 +1552,7 @@ public class SourceTest {
// Default Windows - Navigation
eventReportWindows =
- Source.getOrDefaultEventReportWindows(
+ Source.getOrDefaultEventReportWindowsForFlex(
null, Source.SourceType.NAVIGATION, TimeUnit.DAYS.toMillis(15), flags);
assertNotNull(eventReportWindows);
assertEquals(3, eventReportWindows.size());
@@ -1608,29 +1608,31 @@ public class SourceTest {
}
@Test
- public void getProcessedEventReportWindow() {
+ public void getEffectiveEventReportWindow() {
+ long expiryTime = 7654321L;
// null eventReportWindow
Source sourceNullEventReportWindow =
SourceFixture.getMinimalValidSourceBuilder()
.setEventTime(10)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(null)
.build();
- assertNull(sourceNullEventReportWindow.getProcessedEventReportWindow());
+ assertEquals(expiryTime, sourceNullEventReportWindow.getEffectiveEventReportWindow());
// eventReportWindow Value < eventTime
Source sourceNewEventReportWindow =
SourceFixture.getMinimalValidSourceBuilder()
- .setEventTime(10)
+ .setEventTime(10L)
.setEventReportWindow(4L)
.build();
- assertEquals(Long.valueOf(14L), sourceNewEventReportWindow.getProcessedEventReportWindow());
+ assertEquals(14L, sourceNewEventReportWindow.getEffectiveEventReportWindow());
// eventReportWindow Value > eventTime
Source sourceOldEventReportWindow =
SourceFixture.getMinimalValidSourceBuilder()
- .setEventTime(10)
+ .setEventTime(10L)
.setEventReportWindow(15L)
.build();
- assertEquals(Long.valueOf(15L), sourceOldEventReportWindow.getProcessedEventReportWindow());
+ assertEquals(15L, sourceOldEventReportWindow.getEffectiveEventReportWindow());
}
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerIntegrationTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerIntegrationTest.java
index 6b8e4567a..39f46f31e 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerIntegrationTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerIntegrationTest.java
@@ -77,7 +77,7 @@ public class AttributionJobHandlerIntegrationTest extends AbstractDbIntegrationT
(new AttributionJobHandler(
datastoreManager,
FlagsFactory.getFlags(),
- new DebugReportApi(sContext, FlagsFactory.getFlagsForTest()),
+ new DebugReportApi(sContext, FlagsFactory.getFlags()),
new EventReportWindowCalcDelegate(FlagsFactory.getFlags()),
new SourceNoiseHandler(FlagsFactory.getFlags()),
mLogger,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerTest.java
index b34950e84..c1cbe2ba8 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/attribution/AttributionJobHandlerTest.java
@@ -218,6 +218,12 @@ public class AttributionJobHandlerTest {
when(mFlags.getMeasurementNullAggReportRateInclSourceRegistrationTime()).thenReturn(0f);
when(mFlags.getMeasurementMinEventReportDelayMillis())
.thenReturn(Flags.MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS);
+ when(mFlags.getMeasurementVtcConfigurableMaxEventReportsCount())
+ .thenReturn(Flags.DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT);
+ when(mFlags.getMeasurementEventReportsVtcEarlyReportingWindows())
+ .thenReturn(Flags.MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS);
+ when(mFlags.getMeasurementEventReportsCtcEarlyReportingWindows())
+ .thenReturn(Flags.MEASUREMENT_EVENT_REPORTS_CTC_EARLY_REPORTING_WINDOWS);
}
@Test
@@ -659,7 +665,6 @@ public class AttributionJobHandlerTest {
public void performPendingAttributions_vtcWithConfiguredReportsCount_attributeUptoConfigLimit()
throws DatastoreException {
// Setup
- doReturn(true).when(mFlags).getMeasurementEnableVtcConfigurableMaxEventReports();
doReturn(3).when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
Source source =
SourceFixture.getMinimalValidSourceBuilder()
@@ -1385,6 +1390,9 @@ public class AttributionJobHandlerTest {
doReturn(5L)
.when(mEventReportWindowCalcDelegate)
.getReportingTime(any(Source.class), anyLong(), anyInt());
+ doReturn(EventReportWindowCalcDelegate.MomentPlacement.WITHIN)
+ .when(mEventReportWindowCalcDelegate)
+ .fallsWithinWindow(any(Source.class), anyLong(), anyInt());
when(mMeasurementDao.getPendingTriggerIds())
.thenReturn(Collections.singletonList(trigger.getId()));
when(mMeasurementDao.getTrigger(trigger.getId())).thenReturn(trigger);
@@ -1658,6 +1666,7 @@ public class AttributionJobHandlerTest {
.setAttributionMode(Source.AttributionMode.TRUTHFULLY)
.setInstallAttributed(true)
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(10))
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(28))
.setEventTime(eventTime - TimeUnit.DAYS.toMillis(2))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
@@ -1737,6 +1746,7 @@ public class AttributionJobHandlerTest {
.setInstallAttributed(true)
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(3))
.setEventTime(eventTime - TimeUnit.DAYS.toMillis(2))
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -1747,6 +1757,7 @@ public class AttributionJobHandlerTest {
.setPriority(200L)
.setAttributionMode(Source.AttributionMode.TRUTHFULLY)
.setEventTime(eventTime)
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.build();
when(mMeasurementDao.getPendingTriggerIds())
@@ -3341,6 +3352,7 @@ public class AttributionJobHandlerTest {
+ " \"key_2\": [\"value_1\", \"value_2\"]\n"
+ "}\n")
.setId("sourceId")
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -3436,6 +3448,7 @@ public class AttributionJobHandlerTest {
+ " \"key_2\": [\"value_1\", \"value_2\"]\n"
+ "}\n")
.setId("sourceId")
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -3533,6 +3546,7 @@ public class AttributionJobHandlerTest {
+ " \"key_2\": [\"value_1\", \"value_2\"]\n"
+ "}\n")
.setId("sourceId")
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -3628,6 +3642,7 @@ public class AttributionJobHandlerTest {
+ " \"key_2\": [\"value_1\", \"value_2\"]\n"
+ "}\n")
.setId("sourceId")
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -3726,6 +3741,7 @@ public class AttributionJobHandlerTest {
+ "}\n")
.setId("sourceId")
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -3961,6 +3977,7 @@ public class AttributionJobHandlerTest {
+ " \"key_1\": [\"value_1\", \"value_2\"],\n"
+ " \"key_2\": [\"value_1\", \"value_2\"]\n"
+ "}\n")
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -4039,6 +4056,7 @@ public class AttributionJobHandlerTest {
+ " \"key_1\": [\"value_1\", \"value_2\"],\n"
+ " \"key_2\": [\"value_1\", \"value_2\"]\n"
+ "}\n")
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -4116,6 +4134,7 @@ public class AttributionJobHandlerTest {
+ " \"key_1\": [\"value_1\", \"value_2\"],\n"
+ " \"key_2\": [\"value_1\", \"value_2\"]\n"
+ "}\n")
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -4338,6 +4357,7 @@ public class AttributionJobHandlerTest {
+ " \"key_1\": [\"value_1\", \"value_2\"],\n"
+ " \"key_2\": [\"value_1\", \"value_2\"]\n"
+ "}\n")
+ .setExpiryTime(triggerTime + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(triggerTime + 1L)
.setAggregatableReportWindow(triggerTime + 1L)
.build();
@@ -6129,6 +6149,7 @@ public class AttributionJobHandlerTest {
.setId("sourceId")
.setEventTime(TRIGGER_TIME - TimeUnit.SECONDS.toMillis(LOOKBACK_WINDOW - 1))
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(TRIGGER_TIME + TimeUnit.DAYS.toMillis(28))
.setEventReportWindow(TRIGGER_TIME + 1)
.setAggregatableReportWindow(TRIGGER_TIME + 1)
.build();
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerAttributionProbabilityTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerAttributionProbabilityTest.java
index ef24154ac..a9fa26909 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerAttributionProbabilityTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerAttributionProbabilityTest.java
@@ -16,14 +16,6 @@
package com.android.adservices.service.measurement.noising;
-import static com.android.adservices.service.Flags.MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY;
-import static com.android.adservices.service.Flags.MEASUREMENT_NAVIGATION_NOISE_PROBABILITY;
import static com.android.adservices.service.measurement.SourceFixture.ValidSourceParams.ATTRIBUTION_DESTINATIONS;
import static com.android.adservices.service.measurement.SourceFixture.ValidSourceParams.WEB_DESTINATIONS;
@@ -61,18 +53,22 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
private static final String DELIMITER = ",";
private static final long CURRENT_TIME = System.currentTimeMillis();
+ private static final double INSTALL_ATTR_EVENT_NOISE_PROBABILITY = 0.0000125D;
+ private static final double INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY = 0.0024263D;
+ private static final double EVENT_NOISE_PROBABILITY = 0.0000025D;
+ private static final double NAVIGATION_NOISE_PROBABILITY = 0.0024263D;
+ private static final double INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY =
+ 0.0170218D;
+
private final String mDescription;
- private final boolean mIsEnableConfigurableEventReportingWindows;
private final Source mSource;
private final Long[] mEarlyReportingWindows;
private final double mExpectedProbability;
- private final boolean mEnableConfiguredMaxEventReports;
private final int mConfiguredMaxEventReportsCount;
/**
- * The data format is measurement_enable_configurable_event_reporting_windows flag, sourceType,
- * sourceEventReportWindow (limit), cooldown window, appDestination, webDestination
- * configuredEarlyReportingWindows, coarse destination, enable configured conversions,
+ * The data format is sourceType, sourceEventReportWindow (limit), cooldown window,
+ * appDestination, webDestination, configuredEarlyReportingWindows, coarse destination,
* configured conversions and expectedProbability. Each test description has numbers like 1-1-1,
* 2-1-2, 3-3-3 etc. These signify max reports, trigger data bits and reporting windows count
* respectively. For e.g., 2-1-2 stands for 2 maximum conversions, 1 trigger data bit (0 or 1)
@@ -85,7 +81,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
{
"non-configured reporting windows, EVENT, 1-1-1, app, fine "
+ "destinations",
- false, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -93,15 +88,13 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configured max reports
1, // configured max reports
- MEASUREMENT_EVENT_NOISE_PROBABILITY, // probability
+ EVENT_NOISE_PROBABILITY, // probability
},
{
"non-configured reporting windows, EVENT, 2-1-2, app, install "
+ "detection, fine "
+ "destinations",
- false, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -109,14 +102,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configured max reports
1, // configured max reports
- MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY, // probability
+ INSTALL_ATTR_EVENT_NOISE_PROBABILITY, // probability
},
{
"non-configured reporting windows, EVENT, 1-1-1, web, fine "
+ "destinations",
- false, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -124,14 +115,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configured max reports
1, // configured max reports
- MEASUREMENT_EVENT_NOISE_PROBABILITY, // probability
+ EVENT_NOISE_PROBABILITY, // probability
},
{
"non-configured reporting windows, EVENT, 1-1-1, app and web, "
+ "fine destinations",
- false, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -139,155 +128,56 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configured max reports
1, // configured max reports
- MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY, // probability
+ 0.0000042, // probability
},
{
- "non-configured reporting windows, EVENT, 2-1-2, app & web, "
+ "non-configured reporting windows, EVENT, 2-1-2, app, "
+ "install "
+ "detection, fine"
+ " destinations",
- false, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
ATTRIBUTION_DESTINATIONS, // app destination
- WEB_DESTINATIONS, // app destination
+ null, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configured max reports
1, // configured max reports
- MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY,
+ 0.0000125,
},
{
- "non-configured reporting windows, EVENT, 2-1-2, app & web, "
+ "non-configured reporting windows, EVENT, 2-1-1, app, "
+ "install "
- + "detection, coarse"
+ + "detection, fine"
+ " destinations",
- false, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
- DAYS.toMillis(10), // source event report window
+ DAYS.toMillis(1), // source event report window
DAYS.toMillis(1), // install cooldown window
ATTRIBUTION_DESTINATIONS, // app destination
- WEB_DESTINATIONS, // app destination
- new Long[] {}, // early reporting windows
- true, // coarse destinations
- false, // enable configurable max reports
- 1, // configured max reports
- MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY,
- },
- {
- "non-configured reporting windows, NAVIGATION, 3-3-3, app, fine "
- + "destinations",
- false, // measurement_enable_configurable_event_reporting_windows
- Source.SourceType.NAVIGATION, // source type
- DAYS.toMillis(10), // source event report window
- 0, // install cooldown window
- ATTRIBUTION_DESTINATIONS, // app destination
null, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configured max reports
- 3, // configured max reports
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, // probability
+ 1, // configured max reports
+ 0.000005,
},
{
- "non-configured reporting windows, NAVIGATION, 3-3-3, app, install "
- + "detection, fine "
- + "destinations",
- false, // measurement_enable_configurable_event_reporting_windows
- Source.SourceType.NAVIGATION, // source type
+ "non-configured reporting windows, EVENT, 2-1-2, app, "
+ + "install "
+ + "detection, coarse"
+ + " destinations",
+ Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
ATTRIBUTION_DESTINATIONS, // app destination
null, // web destination
new Long[] {}, // early reporting windows
- false, // coarse destinations
- false, // enable configured max reports
- 3, // configured max reports
- MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY, // probability
- },
- {
- "non-configured reporting windows, NAVIGATION, 3-3-3, web, fine "
- + "destinations",
- false, // measurement_enable_configurable_event_reporting_windows
- Source.SourceType.NAVIGATION, // source type
- DAYS.toMillis(10), // source event report window
- 0, // install cooldown window
- null,
- WEB_DESTINATIONS, // web destination
- new Long[] {}, // early reporting windows
- false, // coarse destinations
- false, // enable configurable max reports
- 3, // configured max reports
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, // probability
- },
- {
- "non-configured reporting windows, NAVIGATION, 3-3-3, app & web, "
- + "fine destinations",
- false, // measurement_enable_configurable_event_reporting_windows
- Source.SourceType.NAVIGATION, // source type
- DAYS.toMillis(10), // source event report window
- 0, // install cooldown window
- ATTRIBUTION_DESTINATIONS, // app destination
- WEB_DESTINATIONS, // web destination
- new Long[] {}, // early reporting windows
- false, // coarse destinations
- false, // enable configurable max reports
- 3, // configured max reports
- MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY, // probability
- },
- {
- "non-configured reporting windows, NAVIGATION, 3-3-3, app & web, "
- + "coarse destinations",
- false, // measurement_enable_configurable_event_reporting_windows
- Source.SourceType.NAVIGATION, // source type
- DAYS.toMillis(10), // source event report window
- 0, // install cooldown window
- ATTRIBUTION_DESTINATIONS, // app destination
- WEB_DESTINATIONS, // web destination
- new Long[] {}, // early reporting windows
true, // coarse destinations
- false, // enable configurable max reports
- 3, // configured max reports
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, // probability
- },
- {
- "non-configured reporting windows, NAVIGATION, 3-3-3, app & web, "
- + "install detection,"
- + " fine destinations",
- false, // measurement_enable_configurable_event_reporting_windows
- Source.SourceType.NAVIGATION, // source type
- DAYS.toMillis(10), // source event report window
- DAYS.toMillis(1), // install cooldown window
- ATTRIBUTION_DESTINATIONS, // app destination
- WEB_DESTINATIONS, // web destination
- new Long[] {}, // early reporting windows
- false, // coarse destinations
- false, // enable configurable max reports
- 3, // configured max reports
- MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY,
- },
- {
- "non-configured reporting windows, NAVIGATION, 3-3-3, app & web, "
- + "install detection,"
- + " coarse destinations",
- false, // measurement_enable_configurable_event_reporting_windows
- Source.SourceType.NAVIGATION, // source type
- DAYS.toMillis(10), // source event report window
- DAYS.toMillis(1), // install cooldown window
- ATTRIBUTION_DESTINATIONS, // app destination
- WEB_DESTINATIONS, // web destination
- new Long[] {}, // early reporting windows
- true, // coarse destinations
- false, // enable configurable max reports
- 3, // configured max reports
- MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY,
+ 1, // configured max reports
+ INSTALL_ATTR_EVENT_NOISE_PROBABILITY,
},
{
"configured reporting windows, EVENT, 1-1-1, app, fine " + "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -295,13 +185,11 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- MEASUREMENT_EVENT_NOISE_PROBABILITY, // probability
+ EVENT_NOISE_PROBABILITY, // probability
},
{
"configured reporting windows, EVENT, 1-1-2, app, fine " + "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -309,13 +197,11 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(1)}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
0.0000042,
},
{
"configured reporting windows, EVENT, 1-1-3, app, fine " + "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -323,7 +209,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(1), DAYS.toSeconds(1)},
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
0.0000058, // probability
},
@@ -331,7 +216,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
"configured reporting windows, EVENT, 1-1-2(1 effective window), "
+ "app, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -339,15 +223,13 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {DAYS.toSeconds(15)}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- MEASUREMENT_EVENT_NOISE_PROBABILITY, // probability
+ EVENT_NOISE_PROBABILITY, // probability
},
{
"configured reporting windows, EVENT, 1-1-3(2 effective window), "
+ "app, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
HOURS.toMillis(6), // source event report window
0, // install cooldown window
@@ -355,15 +237,13 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(1), DAYS.toSeconds(1)},
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
0.0000042,
},
{
- "configured reporting windows, EVENT, 2-1-3(2 effective windows), "
+ "configured reporting windows, EVENT, 1-1-2 (2 effective window), "
+ "app, install "
+ "detection, fine destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
HOURS.toMillis(6), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -373,15 +253,13 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
HOURS.toSeconds(1), DAYS.toSeconds(1)
}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY, // probability
+ 0.0000042, // probability
},
{
- "configured reporting windows, EVENT, 2-1-3, app, install "
+ "configured reporting windows, EVENT, 1-1-3, app, install "
+ "detection, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(6), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -391,15 +269,13 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
HOURS.toSeconds(1), DAYS.toSeconds(1)
}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- 0.0000233, // probability
+ 0.0000058, // probability
},
{
- "configured reporting windows, EVENT, 2-1-3, app & web, install "
+ "configured reporting windows, EVENT, 1-1-3, app & web, install "
+ "detection, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(6), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -409,15 +285,13 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
HOURS.toSeconds(1), DAYS.toSeconds(1)
}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- 0.0000757, // probability
+ 0.0000108, // probability
},
{
- "configured reporting windows, EVENT, 2-1-3, app & web, install "
+ "configured reporting windows, EVENT, 1-1-3, app & web, install "
+ "detection, coarse "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(6), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -427,16 +301,14 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
HOURS.toSeconds(1), DAYS.toSeconds(1)
}, // early reporting windows
true, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- 0.0000233, // probability
+ 0.0000058, // probability
},
{
"configured reporting windows, EVENT, 1-1-1, web, (install "
+ "cooldown -"
+ " unused), fine"
+ " destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -444,21 +316,13 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- MEASUREMENT_EVENT_NOISE_PROBABILITY, // probability
+ EVENT_NOISE_PROBABILITY, // probability
},
{
- // It is different from "non-configured reporting windows, 2-1-2,
- // app
- // & web, install
- // detection" because we reject 20 states resulting into only 25
- // states in
- // that case. Here we assume all 45 states to be valid.
- "configured reporting windows, EVENT, 2-1-2, app & web, install "
+ "configured reporting windows, EVENT, 1-1-2, app & web, install "
+ "detection, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -466,21 +330,13 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // web destination
new Long[] {HOURS.toSeconds(1)}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- 0.0000374, // probability
+ 0.0000075, // probability
},
{
- // It is different from "non-configured reporting windows, 2-1-2,
- // app
- // & web, install
- // detection, coarse destinations" because we reject 20 states
- // resulting into only 25 states in that case. Here we assume all
- // 45 states to be valid.
- "configured reporting windows, EVENT, 2-1-2, app & web, install "
+ "configured reporting windows, EVENT, 1-1-2, app & web, install "
+ "detection, coarse "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -488,14 +344,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // web destination
new Long[] {HOURS.toSeconds(1)}, // early reporting windows
true, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- 0.0000125, // probability
+ 0.0000042, // probability
},
{
"configured (ignored due to empty), EVENT, 2-1-2, app, install "
+ "detection, fine destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -503,14 +357,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY, // probability
+ INSTALL_ATTR_EVENT_NOISE_PROBABILITY, // probability
},
{
"configured reporting windows, EVENT, 1-1-1, app & web, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -518,14 +370,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // app destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY, // probability
+ 0.0000042, // probability
},
{
"configured reporting windows, EVENT, 1-1-1, app & web, coarse "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -533,14 +383,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // app destination
new Long[] {}, // early reporting windows
true, // coarse destinations
- false, // enable configurable max reports
1, // configured max reports
- MEASUREMENT_EVENT_NOISE_PROBABILITY, // probability
+ EVENT_NOISE_PROBABILITY, // probability
},
{
"configured reporting windows, NAVIGATION, 3-3-1, app, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -548,14 +396,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0001372, // probability
},
{
"configured reporting windows, NAVIGATION, 3-3-2, app, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -563,14 +409,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(1)}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0008051, // probability
},
{
"configured reporting windows, NAVIGATION, 3-3-3, app, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -578,16 +422,14 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(1), DAYS.toSeconds(1)},
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, // probability
+ NAVIGATION_NOISE_PROBABILITY, // probability
},
{
"configured reporting windows, NAVIGATION, 3-3-2 (1 effective "
+ "window)"
+ ", app, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(2), // source event report window
0, // install cooldown window
@@ -595,7 +437,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {DAYS.toMillis(3)}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0001372, // probability
},
@@ -603,7 +444,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
"configured reporting windows, NAVIGATION, 3-3-3 (2 effective "
+ "windows), app, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
HOURS.toMillis(6), // source event report window
0, // install cooldown window
@@ -611,7 +451,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(1), DAYS.toSeconds(1)},
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0008051, // probability
},
@@ -619,7 +458,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
"configured reporting windows, NAVIGATION, 3-3-1, app, install "
+ "detection, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -627,7 +465,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0001372, // probability
},
@@ -635,7 +472,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
"configured reporting windows, NAVIGATION, 3-3-1, web, install "
+ "detection, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -643,14 +479,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // app destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0001372, // probability
},
{
"configured reporting windows, NAVIGATION, 3-3-1, app & web, fine"
+ " destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -658,14 +492,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // app destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0008051, // probability
},
{
"configured reporting windows, NAVIGATION, 3-3-1, app & web, "
+ "coarse destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -673,7 +505,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // app destination
new Long[] {}, // early reporting windows
true, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0001372, // probability
},
@@ -682,7 +513,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
+ "install "
+ "detection, "
+ "fine destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -690,7 +520,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // app destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0008051, // probability
},
@@ -699,7 +528,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
+ "install "
+ "detection, "
+ "coarse destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -707,7 +535,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // app destination
new Long[] {}, // early reporting windows
true, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
0.0001372, // probability
},
@@ -716,7 +543,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
+ "install "
+ "detection, fine"
+ " destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -724,16 +550,14 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // web destination
new Long[] {HOURS.toSeconds(2), DAYS.toSeconds(2)},
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
- MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY,
+ INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY,
},
{
"configured reporting windows, NAVIGATION, 3-3-3, app & web, "
+ "install "
+ "detection, "
+ "coarse destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -741,14 +565,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // web destination
new Long[] {HOURS.toSeconds(2), DAYS.toSeconds(2)},
true, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
- MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY,
+ INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY,
},
{
"configured reporting windows, NAVIGATION, 3-3-3, app, install "
+ "detection, fine destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -756,14 +578,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(2), DAYS.toSeconds(2)},
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
- MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY, // probability
+ INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY, // probability
},
{
"configured reporting windows, NAVIGATION, 3-3-3, app & web, fine"
+ " destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -771,14 +591,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // web destination
new Long[] {HOURS.toSeconds(2), DAYS.toSeconds(2)},
false, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
- MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY, // probability
+ 0.0170218, // probability
},
{
"configured reporting windows, NAVIGATION, 3-3-3, app & web, "
+ "coarse destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.NAVIGATION, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -786,14 +604,12 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
WEB_DESTINATIONS, // web destination
new Long[] {HOURS.toSeconds(2), DAYS.toSeconds(2)},
true, // coarse destinations
- false, // enable configurable max reports
3, // configured max reports
- MEASUREMENT_NAVIGATION_NOISE_PROBABILITY, // probability
+ NAVIGATION_NOISE_PROBABILITY, // probability
},
{
"non-configured reporting windows, EVENT, 3-1-1, app, fine "
+ "destinations",
- false, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -801,13 +617,11 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {}, // early reporting windows
false, // coarse destinations
- true, // enable configured max reports
3, // configured max reports
0.0000083, // probability
},
{
"configured reporting windows, EVENT, 3-1-3, app, fine " + "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -815,13 +629,11 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(1), DAYS.toSeconds(1)},
false, // coarse destinations
- true, // enable configurable max reports
3, // configured max reports
0.0000698, // probability
},
{
"configured reporting windows, EVENT, 2-1-3, app, fine " + "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -829,7 +641,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(1), DAYS.toSeconds(1)},
false, // coarse destinations
- true, // enable configurable max reports
2, // configured max reports
0.0000233, // probability
},
@@ -837,7 +648,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
"configured reporting windows, EVENT, 3-1-3, app, install "
+ "detection, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(6), // source event report window
// not honored because conversions and windows are overridden
@@ -848,7 +658,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
HOURS.toSeconds(1), DAYS.toSeconds(1)
}, // early reporting windows
false, // coarse destinations
- true, // enable configurable max reports
3, // configured max reports
0.0000698, // probability
},
@@ -856,7 +665,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
"configured reporting windows, EVENT, 3-1-3, app & web, install "
+ "detection, fine "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(6), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -866,7 +674,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
HOURS.toSeconds(1), DAYS.toSeconds(1)
}, // early reporting windows
false, // coarse destinations
- true, // enable configurable max reports
3, // configured max reports
0.0003782, // probability
},
@@ -874,7 +681,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
"configured reporting windows, EVENT, 3-1-3, app & web, install "
+ "detection, coarse "
+ "destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(6), // source event report window
DAYS.toMillis(1), // install cooldown window
@@ -884,13 +690,11 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
HOURS.toSeconds(1), DAYS.toSeconds(1)
}, // early reporting windows
true, // coarse destinations
- true, // enable configurable max reports
3, // configured max reports
0.0000698, // probability
},
{
"configured reporting windows, EVENT, 1-1-3, app, fine" + " destinations",
- true, // measurement_enable_configurable_event_reporting_windows
Source.SourceType.EVENT, // source type
DAYS.toMillis(10), // source event report window
0, // install cooldown window
@@ -898,7 +702,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
null, // web destination
new Long[] {HOURS.toSeconds(1), DAYS.toSeconds(1)},
false, // coarse destinations
- true, // enable configurable max reports
1, // configured max reports
0.0000058, // probability
},
@@ -907,7 +710,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
public SourceNoiseHandlerAttributionProbabilityTest(
String description,
- boolean isEnableConfigurableEventReportingWindows,
Source.SourceType sourceType,
long sourceEventReportWindow,
long coolDownWindow,
@@ -915,11 +717,9 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
List<Uri> webDestinations,
Long[] earlyReportingWindows,
boolean coarseDestination,
- boolean isEnableConfigurableMaxEventReports,
int configuredMaxEventReportsCount,
double expectedProbability) {
mDescription = description;
- mIsEnableConfigurableEventReportingWindows = isEnableConfigurableEventReportingWindows;
mSource =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(sourceType)
@@ -936,7 +736,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
BigDecimal.valueOf(expectedProbability)
.setScale(7, RoundingMode.HALF_UP)
.doubleValue();
- mEnableConfiguredMaxEventReports = isEnableConfigurableMaxEventReports;
mConfiguredMaxEventReportsCount = configuredMaxEventReportsCount;
}
@@ -944,9 +743,6 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
public void getRandomAttributionProbability_withParameterizedData() {
// Setup
Flags flags = mock(Flags.class);
- doReturn(mIsEnableConfigurableEventReportingWindows)
- .when(flags)
- .getMeasurementEnableConfigurableEventReportingWindows();
doReturn(convertEarlyReportingWindowFlagString(mEarlyReportingWindows))
.when(flags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -954,36 +750,9 @@ public class SourceNoiseHandlerAttributionProbabilityTest {
.when(flags)
.getMeasurementEventReportsCtcEarlyReportingWindows();
doReturn(true).when(flags).getMeasurementEnableCoarseEventReportDestinations();
- doReturn(mEnableConfiguredMaxEventReports)
- .when(flags)
- .getMeasurementEnableVtcConfigurableMaxEventReports();
doReturn(mConfiguredMaxEventReportsCount)
.when(flags)
.getMeasurementVtcConfigurableMaxEventReportsCount();
- doReturn(MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY)
- .when(flags)
- .getMeasurementInstallAttrDualDestinationEventNoiseProbability();
- doReturn(MEASUREMENT_INSTALL_ATTR_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY)
- .when(flags)
- .getMeasurementInstallAttrDualDestinationNavigationNoiseProbability();
- doReturn(MEASUREMENT_DUAL_DESTINATION_NAVIGATION_NOISE_PROBABILITY)
- .when(flags)
- .getMeasurementDualDestinationNavigationNoiseProbability();
- doReturn(MEASUREMENT_DUAL_DESTINATION_EVENT_NOISE_PROBABILITY)
- .when(flags)
- .getMeasurementDualDestinationEventNoiseProbability();
- doReturn(MEASUREMENT_INSTALL_ATTR_EVENT_NOISE_PROBABILITY)
- .when(flags)
- .getMeasurementInstallAttrEventNoiseProbability();
- doReturn(MEASUREMENT_INSTALL_ATTR_NAVIGATION_NOISE_PROBABILITY)
- .when(flags)
- .getMeasurementInstallAttrNavigationNoiseProbability();
- doReturn(MEASUREMENT_EVENT_NOISE_PROBABILITY)
- .when(flags)
- .getMeasurementEventNoiseProbability();
- doReturn(MEASUREMENT_NAVIGATION_NOISE_PROBABILITY)
- .when(flags)
- .getMeasurementNavigationNoiseProbability();
// Execution
double actualProbability =
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerTest.java
index 06a3dc6ae..c9d0cf23a 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/noising/SourceNoiseHandlerTest.java
@@ -50,49 +50,17 @@ public class SourceNoiseHandlerTest {
@Before
public void setup() {
mFlags = mock(Flags.class);
- doReturn(false).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
+ doReturn(Flags.DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT)
+ .when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
+ doReturn(Flags.MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS)
+ .when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
+ doReturn(Flags.MEASUREMENT_EVENT_REPORTS_CTC_EARLY_REPORTING_WINDOWS)
+ .when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
mSourceNoiseHandler =
spy(new SourceNoiseHandler(mFlags, new EventReportWindowCalcDelegate(mFlags)));
}
@Test
- public void fakeReports_eventSourceDualDestPostInstallMode_generatesFromStaticReportStates() {
- long expiry = System.currentTimeMillis();
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.EVENT)
- .setWebDestinations(SourceFixture.ValidSourceParams.WEB_DESTINATIONS)
- .setEventReportWindow(expiry)
- .setInstallCooldownWindow(
- SourceFixture.ValidSourceParams.INSTALL_COOLDOWN_WINDOW)
- .build();
- // Force increase the probability of random attribution.
- doReturn(0.50D).when(mSourceNoiseHandler).getRandomAttributionProbability(source);
- int falseCount = 0;
- int neverCount = 0;
- int truthCount = 0;
- for (int i = 0; i < 500; i++) {
- List<Source.FakeReport> fakeReports =
- mSourceNoiseHandler.assignAttributionModeAndGenerateFakeReports(source);
- if (source.getAttributionMode() == Source.AttributionMode.FALSELY) {
- falseCount++;
- assertNotEquals(0, fakeReports.size());
- assertTrue(
- isValidEventSourceDualDestPostInstallModeFakeReportState(
- source, fakeReports));
- } else if (source.getAttributionMode() == Source.AttributionMode.NEVER) {
- neverCount++;
- assertEquals(0, fakeReports.size());
- } else {
- truthCount++;
- }
- }
- assertNotEquals(0, falseCount);
- assertNotEquals(0, neverCount);
- assertNotEquals(0, truthCount);
- }
-
- @Test
public void fakeReports_flexEventReport_generatesFromStaticReportStates() {
Source source = SourceFixture.getValidSourceWithFlexEventReportWithFewerState();
// Force increase the probability of random attribution.
@@ -167,6 +135,7 @@ public class SourceNoiseHandlerTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(30))
.build();
assertEquals(
@@ -181,6 +150,7 @@ public class SourceNoiseHandlerTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(7))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(7))
.build();
assertEquals(
@@ -195,6 +165,7 @@ public class SourceNoiseHandlerTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(2))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(2))
.build();
assertEquals(
@@ -302,6 +273,7 @@ public class SourceNoiseHandlerTest {
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(2))
.setInstallAttributionWindow(TimeUnit.DAYS.toMillis(10))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(30))
.build();
assertEquals(
@@ -318,6 +290,7 @@ public class SourceNoiseHandlerTest {
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(2))
.setInstallAttributionWindow(TimeUnit.DAYS.toMillis(10))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(7))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(7))
.build();
assertEquals(
@@ -334,6 +307,7 @@ public class SourceNoiseHandlerTest {
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(2))
.setInstallAttributionWindow(TimeUnit.DAYS.toMillis(10))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(2))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(2))
.build();
assertEquals(
@@ -350,6 +324,7 @@ public class SourceNoiseHandlerTest {
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(2))
.setInstallAttributionWindow(TimeUnit.DAYS.toMillis(10))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(30))
.build();
assertEquals(
@@ -366,6 +341,7 @@ public class SourceNoiseHandlerTest {
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(2))
.setInstallAttributionWindow(TimeUnit.DAYS.toMillis(10))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(7))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(7))
.build();
assertEquals(
@@ -382,6 +358,7 @@ public class SourceNoiseHandlerTest {
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(2))
.setInstallAttributionWindow(TimeUnit.DAYS.toMillis(10))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(2))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(2))
.build();
assertEquals(
@@ -393,11 +370,11 @@ public class SourceNoiseHandlerTest {
mSourceNoiseHandler.getImpressionNoiseParams(navigationSource2dExpiry));
Source eventSourceWith2Destinations30dExpiry =
SourceFixture.getMinimalValidSourceBuilder()
- .setWebDestinations(SourceFixture.ValidSourceParams.WEB_DESTINATIONS)
.setSourceType(Source.SourceType.EVENT)
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(2))
.setInstallAttributionWindow(TimeUnit.DAYS.toMillis(10))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(30))
.build();
assertEquals(
@@ -405,7 +382,7 @@ public class SourceNoiseHandlerTest {
/* reportCount= */ 2,
/* triggerDataCardinality= */ 2,
/* reportingWindowCount= */ 2,
- /* destinationMultiplier */ 2),
+ /* destinationMultiplier */ 1),
mSourceNoiseHandler.getImpressionNoiseParams(
eventSourceWith2Destinations30dExpiry));
}
@@ -491,14 +468,6 @@ public class SourceNoiseHandlerTest {
PrivacyParams.EVENT_TRIGGER_DATA_CARDINALITY);
}
- private boolean isValidEventSourceDualDestPostInstallModeFakeReportState(
- Source source, List<Source.FakeReport> fakeReportsState) {
- // Generated fake reports state matches one of the states
- return Arrays.stream(ImpressionNoiseUtil.DUAL_DESTINATION_POST_INSTALL_FAKE_REPORT_CONFIG)
- .map(reportsState -> convertToReportsState(reportsState, source))
- .anyMatch(fakeReportsState::equals);
- }
-
private List<Source.FakeReport> convertToReportsState(int[][] reportsState, Source source) {
return Arrays.stream(reportsState)
.map(
@@ -507,7 +476,7 @@ public class SourceNoiseHandlerTest {
new UnsignedLong(Long.valueOf(reportState[0])),
new EventReportWindowCalcDelegate(mFlags)
.getReportingTimeForNoising(
- source, reportState[1], true),
+ source, reportState[1]),
reportState[2] == 0
? source.getAppDestinations()
: source.getWebDestinations()))
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueJobServiceTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueJobServiceTest.java
index ee87776c5..632838e41 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueJobServiceTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueJobServiceTest.java
@@ -20,7 +20,6 @@ import static com.android.adservices.mockito.ExtendedMockitoExpectations.mockGet
import static com.android.adservices.mockito.ExtendedMockitoExpectations.mockGetFlags;
import static com.android.adservices.mockito.MockitoExpectations.mockBackgroundJobsLoggingKillSwitch;
import static com.android.adservices.mockito.MockitoExpectations.syncLogExecutionStats;
-import static com.android.adservices.mockito.MockitoExpectations.syncPersistJobExecutionData;
import static com.android.adservices.mockito.MockitoExpectations.verifyBackgroundJobsSkipLogged;
import static com.android.adservices.mockito.MockitoExpectations.verifyLoggingNotHappened;
import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_ASYNC_REGISTRATION_JOB;
@@ -33,7 +32,6 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
@@ -79,7 +77,6 @@ import org.mockito.internal.stubbing.answers.CallsRealMethods;
import org.mockito.quality.Strictness;
import java.util.Optional;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class AsyncRegistrationQueueJobServiceTest {
@@ -168,9 +165,6 @@ public class AsyncRegistrationQueueJobServiceTest {
runWithMocks(
() -> {
mockBackgroundJobsLoggingKillSwitch(mMockFlags, /* overrideValue= */ false);
- JobServiceLoggingCallback onStartJobCallback =
- syncPersistJobExecutionData(mSpyLogger);
- JobServiceLoggingCallback onJobDoneCallback = syncLogExecutionStats(mSpyLogger);
doReturn(
AsyncRegistrationQueueRunner.ProcessingResult
.SUCCESS_ALL_RECORDS_PROCESSED)
@@ -179,8 +173,7 @@ public class AsyncRegistrationQueueJobServiceTest {
onStartJob_killSwitchOff();
- verify(mSpyLogger).recordOnStartJob(anyInt());
- verify(mSpyLogger).persistJobExecutionData(anyInt(), anyLong());
+ verify(mSpyLogger, timeout(WAIT_IN_MILLIS)).recordOnStartJob(anyInt());
});
}
@@ -364,7 +357,7 @@ public class AsyncRegistrationQueueJobServiceTest {
// Validate jobInfo params to run immediately
ArgumentCaptor<JobInfo> captorJobInfo = ArgumentCaptor.forClass(JobInfo.class);
- verify(jobScheduler, times(1)).schedule(captorJobInfo.capture());
+ verify(jobScheduler, timeout(WAIT_IN_MILLIS).times(1)).schedule(captorJobInfo.capture());
JobInfo jobInfo = captorJobInfo.getValue();
assertNotNull(jobInfo);
assertNull(jobInfo.getTriggerContentUris());
@@ -559,8 +552,8 @@ public class AsyncRegistrationQueueJobServiceTest {
// Validate
ExtendedMockito.verify(
() -> AsyncRegistrationQueueJobService.schedule(any(), any()),
- times(1));
- verify(mMockJobScheduler, times(1))
+ timeout(WAIT_IN_MILLIS).times(1));
+ verify(mMockJobScheduler, timeout(WAIT_IN_MILLIS).times(1))
.getPendingJob(eq(MEASUREMENT_ASYNC_REGISTRATION_JOB_ID));
});
}
@@ -589,7 +582,8 @@ public class AsyncRegistrationQueueJobServiceTest {
times(1));
ArgumentCaptor<JobInfo> jobInfoArgumentCaptor =
ArgumentCaptor.forClass(JobInfo.class);
- verify(mMockJobScheduler, times(1)).schedule(jobInfoArgumentCaptor.capture());
+ verify(mMockJobScheduler, timeout(WAIT_IN_MILLIS).times(1))
+ .schedule(jobInfoArgumentCaptor.capture());
JobInfo job = jobInfoArgumentCaptor.getValue();
assertEquals(JOB_TRIGGER_MIN_DELAY_MS, job.getTriggerContentUpdateDelay());
assertEquals(JOB_TRIGGER_MAX_DELAY_MS, job.getTriggerContentMaxDelay());
@@ -612,7 +606,8 @@ public class AsyncRegistrationQueueJobServiceTest {
boolean onStopJobResult =
mSpyService.onStopJob(Mockito.mock(JobParameters.class));
- verify(mSpyService, times(0)).jobFinished(any(), anyBoolean());
+ verify(mSpyService, timeout(WAIT_IN_MILLIS).times(0))
+ .jobFinished(any(), anyBoolean());
assertTrue(onStopJobResult);
assertTrue(mSpyService.getFutureForTesting().isCancelled());
});
@@ -633,8 +628,9 @@ public class AsyncRegistrationQueueJobServiceTest {
assertFalse(result);
// Allow background thread to execute
Thread.sleep(WAIT_IN_MILLIS);
- verify(mSpyService, times(1)).jobFinished(any(), eq(false));
- verify(mMockJobScheduler, times(1)).cancel(eq(MEASUREMENT_ASYNC_REGISTRATION_JOB_ID));
+ verify(mSpyService, timeout(WAIT_IN_MILLIS).times(1)).jobFinished(any(), eq(false));
+ verify(mMockJobScheduler, timeout(WAIT_IN_MILLIS).times(1))
+ .cancel(eq(MEASUREMENT_ASYNC_REGISTRATION_JOB_ID));
}
private void onStartJob_killSwitchOn() throws Exception {
@@ -646,10 +642,9 @@ public class AsyncRegistrationQueueJobServiceTest {
// Validate
assertFalse(result);
- // Allow background thread to execute
- Thread.sleep(WAIT_IN_MILLIS);
- verify(mSpyService, times(1)).jobFinished(any(), eq(false));
- verify(mMockJobScheduler, times(1)).cancel(eq(MEASUREMENT_ASYNC_REGISTRATION_JOB_ID));
+ verify(mSpyService, timeout(WAIT_IN_MILLIS).times(1)).jobFinished(any(), eq(false));
+ verify(mMockJobScheduler, timeout(WAIT_IN_MILLIS).times(1))
+ .cancel(eq(MEASUREMENT_ASYNC_REGISTRATION_JOB_ID));
}
private void onStartJob_killSwitchOff() throws Exception {
@@ -701,9 +696,4 @@ public class AsyncRegistrationQueueJobServiceTest {
ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags);
ExtendedMockito.doReturn(value).when(mMockFlags).getAsyncRegistrationJobQueueKillSwitch();
}
-
- private Object countDown(CountDownLatch countDownLatch) {
- countDownLatch.countDown();
- return null;
- }
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunnerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunnerTest.java
index 3322190dd..2cfc9e6c4 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunnerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncRegistrationQueueRunnerTest.java
@@ -33,7 +33,6 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.adservices.measurement.RegistrationRequest;
import android.adservices.measurement.WebSourceParams;
import android.adservices.measurement.WebSourceRegistrationRequest;
import android.content.ContentProviderClient;
@@ -96,6 +95,7 @@ import org.mockito.stubbing.Answer;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -125,6 +125,10 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
private static final String LIST_TYPE_REDIRECT_URI_1 = WebUtil.validUrl("https://foo.test");
private static final String LIST_TYPE_REDIRECT_URI_2 = WebUtil.validUrl("https://bar.test");
private static final String LOCATION_TYPE_REDIRECT_URI = WebUtil.validUrl("https://baz.test");
+ private static final String LOCATION_TYPE_REDIRECT_URI_2 = WebUtil.validUrl("https://qux.test");
+ private static final String LOCATION_TYPE_REDIRECT_URI_3 =
+ WebUtil.validUrl("https://quux.test");
+
private static final Uri WEB_DESTINATION = WebUtil.validUri("https://web-destination.test");
private static final Uri APP_DESTINATION = Uri.parse("android-app://com.app_destination");
private static final Source SOURCE_1 =
@@ -265,6 +269,12 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mFlags.getMeasurementFlexApiMaxInformationGainDualDestinationNavigation())
.thenReturn(Flags
.MEASUREMENT_FLEX_API_MAX_INFORMATION_GAIN_DUAL_DESTINATION_NAVIGATION);
+ when(mFlags.getMeasurementVtcConfigurableMaxEventReportsCount())
+ .thenReturn(Flags.DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT);
+ when(mFlags.getMeasurementEventReportsVtcEarlyReportingWindows())
+ .thenReturn(Flags.MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS);
+ when(mFlags.getMeasurementEventReportsCtcEarlyReportingWindows())
+ .thenReturn(Flags.MEASUREMENT_EVENT_REPORTS_CTC_EARLY_REPORTING_WINDOWS);
when(mMeasurementDao.insertSource(any())).thenReturn(DEFAULT_SOURCE_ID);
mContext = spy(sDefaultContext);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
@@ -277,17 +287,18 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(
+ WebUtil.validUri("https://example.test/sF1").toString(),
+ WebUtil.validUri("https://example.test/sF2").toString()));
Answer<?> answerAsyncSourceFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- WebUtil.validUri("https://example.test/sF1"),
- WebUtil.validUri("https://example.test/sF2")));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedSource);
};
doAnswer(answerAsyncSourceFetcher)
@@ -305,14 +316,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
// Execution
@@ -339,17 +343,18 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(
+ WebUtil.validUri("https://example.test/sF1").toString(),
+ WebUtil.validUri("https://example.test/sF2").toString()));
Answer<?> answerAsyncSourceFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- WebUtil.validUri("https://example.test/sF1"),
- WebUtil.validUri("https://example.test/sF2")));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedSource);
};
doAnswer(answerAsyncSourceFetcher)
@@ -367,14 +372,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
Thread.currentThread().interrupt();
@@ -420,16 +418,16 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
AsyncRegistrationQueueRunner asyncRegistrationQueueRunner =
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(LIST_TYPE_REDIRECT_URI_1, LIST_TYPE_REDIRECT_URI_2));
Answer<Optional<Source>> answerAsyncSourceFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- Uri.parse(LIST_TYPE_REDIRECT_URI_1),
- Uri.parse(LIST_TYPE_REDIRECT_URI_2)));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedSource);
};
doAnswer(answerAsyncSourceFetcher)
@@ -444,14 +442,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
// Execution
@@ -496,14 +487,16 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
AsyncRegistrationQueueRunner asyncRegistrationQueueRunner =
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LOCATION,
+ List.of(LOCATION_TYPE_REDIRECT_URI));
Answer<Optional<Source>> answerAsyncSourceFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LOCATION,
- List.of(Uri.parse(LOCATION_TYPE_REDIRECT_URI)));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedSource);
};
doAnswer(answerAsyncSourceFetcher)
@@ -518,14 +511,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
// Execution
@@ -562,14 +548,16 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
AsyncRegistrationQueueRunner asyncRegistrationQueueRunner =
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LOCATION,
+ List.of(LOCATION_TYPE_REDIRECT_URI));
Answer<Optional<Source>> answerAsyncSourceFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LOCATION,
- List.of(Uri.parse(LOCATION_TYPE_REDIRECT_URI)));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedSource);
};
doAnswer(answerAsyncSourceFetcher)
@@ -621,6 +609,338 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
}
@Test
+ public void runAsyncRegistrationQueueWorker_appSrc_defaultReg_redirectWellKnown_typeLocation()
+ throws DatastoreException {
+ // Setup
+ AsyncRegistrationQueueRunner asyncRegistrationQueueRunner =
+ getSpyAsyncRegistrationQueueRunner();
+ AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
+ Answer<Optional<Source>> answerAsyncSourceFetcher =
+ getAsyncSourceAnswerForLocationTypeRedirectToWellKnown(
+ LOCATION_TYPE_REDIRECT_URI, validAsyncRegistration);
+ doAnswer(answerAsyncSourceFetcher)
+ .when(mAsyncSourceFetcher)
+ .fetchSource(any(), any(), any());
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+
+ List<Source.FakeReport> eventReportList =
+ Collections.singletonList(
+ new Source.FakeReport(new UnsignedLong(1L), 1L, List.of(APP_DESTINATION)));
+ when(mSourceNoiseHandler.assignAttributionModeAndGenerateFakeReports(mMockedSource))
+ .thenReturn(eventReportList);
+ when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
+ .thenReturn(validAsyncRegistration);
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
+ when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
+
+ // Execution
+ asyncRegistrationQueueRunner.runAsyncRegistrationQueueWorker();
+
+ ArgumentCaptor<AsyncRegistration> asyncRegistrationArgumentCaptor =
+ ArgumentCaptor.forClass(AsyncRegistration.class);
+
+ // Assertions
+ verify(mAsyncSourceFetcher, times(1))
+ .fetchSource(any(AsyncRegistration.class), any(), any());
+ verify(mMeasurementDao, times(1)).insertEventReport(any(EventReport.class));
+ verify(mMeasurementDao, times(1)).insertSource(any(Source.class));
+ verify(mMeasurementDao, times(1))
+ .insertAsyncRegistration(asyncRegistrationArgumentCaptor.capture());
+
+ Assert.assertEquals(1, asyncRegistrationArgumentCaptor.getAllValues().size());
+ AsyncRegistration asyncReg = asyncRegistrationArgumentCaptor.getAllValues().get(0);
+ Assert.assertEquals(
+ getRegistrationRedirectToWellKnownUri(
+ Uri.parse(LOCATION_TYPE_REDIRECT_URI), LOCATION_TYPE_REDIRECT_URI),
+ asyncReg.getRegistrationUri());
+
+ ArgumentCaptor<KeyValueData> redirectCountCaptor =
+ ArgumentCaptor.forClass(KeyValueData.class);
+ verify(mMeasurementDao, times(1)).insertOrUpdateKeyValueData(redirectCountCaptor.capture());
+ assertEquals(2, redirectCountCaptor.getValue().getRegistrationRedirectCount());
+
+ verify(mMeasurementDao, times(1)).deleteAsyncRegistration(any(String.class));
+ }
+
+ @Test
+ public void runAsyncRegistrationQueueWorker_appSrc_defaultReg_redirectChain_typeLocation()
+ throws DatastoreException {
+ // Setup
+ AsyncRegistrationQueueRunner asyncRegistrationQueueRunner =
+ getSpyAsyncRegistrationQueueRunner();
+ AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
+ Answer<Optional<Source>> answerAsyncSourceFetcher =
+ getAsyncSourceAnswerForLocationTypeRedirectToWellKnown(
+ LOCATION_TYPE_REDIRECT_URI, validAsyncRegistration);
+ doAnswer(answerAsyncSourceFetcher)
+ .when(mAsyncSourceFetcher)
+ .fetchSource(any(), any(), any());
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+
+ List<Source.FakeReport> eventReportList =
+ Collections.singletonList(
+ new Source.FakeReport(new UnsignedLong(1L), 1L, List.of(APP_DESTINATION)));
+ when(mSourceNoiseHandler.assignAttributionModeAndGenerateFakeReports(mMockedSource))
+ .thenReturn(eventReportList);
+ when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
+ .thenReturn(validAsyncRegistration);
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
+ when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
+
+ // Execution
+ asyncRegistrationQueueRunner.runAsyncRegistrationQueueWorker();
+ // Set up the second invocation.
+ Answer<Optional<Source>> answerAsyncSourceFetcher2 =
+ getAsyncSourceAnswerForLocationTypeRedirectToWellKnown(
+ LOCATION_TYPE_REDIRECT_URI_2, validAsyncRegistration);
+ doAnswer(answerAsyncSourceFetcher2)
+ .when(mAsyncSourceFetcher)
+ .fetchSource(any(), any(), any());
+
+ asyncRegistrationQueueRunner.runAsyncRegistrationQueueWorker();
+
+ // Set up the third invocation.
+ Answer<Optional<Source>> answerAsyncSourceFetcher3 =
+ getAsyncSourceAnswerForLocationTypeRedirectToWellKnown(
+ LOCATION_TYPE_REDIRECT_URI_3, validAsyncRegistration);
+
+ doAnswer(answerAsyncSourceFetcher3)
+ .when(mAsyncSourceFetcher)
+ .fetchSource(any(), any(), any());
+
+ asyncRegistrationQueueRunner.runAsyncRegistrationQueueWorker();
+
+ // Assertions for all invocations
+ ArgumentCaptor<AsyncRegistration> asyncRegistrationArgumentCaptor =
+ ArgumentCaptor.forClass(AsyncRegistration.class);
+ verify(mMeasurementDao, times(3))
+ .insertAsyncRegistration(asyncRegistrationArgumentCaptor.capture());
+ Assert.assertEquals(3, asyncRegistrationArgumentCaptor.getAllValues().size());
+
+ ArgumentCaptor<KeyValueData> redirectCountCaptor =
+ ArgumentCaptor.forClass(KeyValueData.class);
+ verify(mMeasurementDao, times(3)).insertOrUpdateKeyValueData(redirectCountCaptor.capture());
+ assertEquals(4, redirectCountCaptor.getValue().getRegistrationRedirectCount());
+
+ // Assertions for first invocation
+ assertRepeatedAsyncRegistration(
+ asyncRegistrationArgumentCaptor,
+ 0,
+ getRegistrationRedirectToWellKnownUri(
+ Uri.parse(LOCATION_TYPE_REDIRECT_URI),
+ LOCATION_TYPE_REDIRECT_URI.toString()));
+
+ // Assertions for second invocation
+ assertRepeatedAsyncRegistration(
+ asyncRegistrationArgumentCaptor,
+ 1,
+ getRegistrationRedirectToWellKnownUri(
+ Uri.parse(LOCATION_TYPE_REDIRECT_URI_2),
+ LOCATION_TYPE_REDIRECT_URI_2.toString()));
+
+ // Assertions for third invocation
+ assertRepeatedAsyncRegistration(
+ asyncRegistrationArgumentCaptor,
+ 2,
+ getRegistrationRedirectToWellKnownUri(
+ Uri.parse(LOCATION_TYPE_REDIRECT_URI_3),
+ LOCATION_TYPE_REDIRECT_URI_3.toString()));
+ }
+
+ @Test
+ public void runAsyncRegistrationQueueWorker_appSrc_defaultReg_redirectWithExistingPathAndQuery()
+ throws DatastoreException {
+ // Setup
+ AsyncRegistrationQueueRunner asyncRegistrationQueueRunner =
+ getSpyAsyncRegistrationQueueRunner();
+ AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
+ String redirectWithExistingPath = LOCATION_TYPE_REDIRECT_URI + "/path?key=value";
+ Answer<Optional<Source>> answerAsyncSourceFetcher =
+ getAsyncSourceAnswerForLocationTypeRedirectToWellKnown(
+ redirectWithExistingPath, validAsyncRegistration);
+ doAnswer(answerAsyncSourceFetcher)
+ .when(mAsyncSourceFetcher)
+ .fetchSource(any(), any(), any());
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+
+ List<Source.FakeReport> eventReportList =
+ Collections.singletonList(
+ new Source.FakeReport(new UnsignedLong(1L), 1L, List.of(APP_DESTINATION)));
+ when(mSourceNoiseHandler.assignAttributionModeAndGenerateFakeReports(mMockedSource))
+ .thenReturn(eventReportList);
+ when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
+ .thenReturn(validAsyncRegistration);
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
+ when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
+
+ // Execution
+
+ asyncRegistrationQueueRunner.runAsyncRegistrationQueueWorker();
+
+ ArgumentCaptor<AsyncRegistration> asyncRegistrationArgumentCaptor =
+ ArgumentCaptor.forClass(AsyncRegistration.class);
+
+ // Assertions
+ verify(mAsyncSourceFetcher, times(1))
+ .fetchSource(any(AsyncRegistration.class), any(), any());
+ verify(mMeasurementDao, times(1)).insertEventReport(any(EventReport.class));
+ verify(mMeasurementDao, times(1)).insertSource(any(Source.class));
+ verify(mMeasurementDao, times(1))
+ .insertAsyncRegistration(asyncRegistrationArgumentCaptor.capture());
+
+ Assert.assertEquals(1, asyncRegistrationArgumentCaptor.getAllValues().size());
+ AsyncRegistration asyncReg = asyncRegistrationArgumentCaptor.getAllValues().get(0);
+
+ Uri expectedUri =
+ Uri.parse(
+ LOCATION_TYPE_REDIRECT_URI
+ + "/"
+ + AsyncRedirects.WELL_KNOWN_PATH_SEGMENT
+ + "?"
+ + AsyncRedirects.WELL_KNOWN_QUERY_PARAM
+ + "="
+ + Uri.encode(redirectWithExistingPath));
+ Assert.assertEquals(expectedUri, asyncReg.getRegistrationUri());
+ }
+
+ @Test
+ public void runAsyncRegistrationQueueWorker_noSourceReg_RedirectHasSource()
+ throws DatastoreException {
+ // Setup
+ AsyncRegistrationQueueRunner asyncRegistrationQueueRunner =
+ getSpyAsyncRegistrationQueueRunner();
+ AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
+
+ // Create an empty response for fetchSource. This is necessary because we need to mock the
+ // addition of a redirect, despite a failing initial source registration.
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LOCATION,
+ List.of(LOCATION_TYPE_REDIRECT_URI));
+ redirectHeaders.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
+ Answer<Optional<Source>> answerEmptySource =
+ invocation -> {
+ AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
+ asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
+ return Optional.empty();
+ };
+
+ doAnswer(answerEmptySource).when(mAsyncSourceFetcher).fetchSource(any(), any(), any());
+
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+
+ List<Source.FakeReport> eventReportList =
+ Collections.singletonList(
+ new Source.FakeReport(new UnsignedLong(1L), 1L, List.of(APP_DESTINATION)));
+ when(mSourceNoiseHandler.assignAttributionModeAndGenerateFakeReports(mMockedSource))
+ .thenReturn(eventReportList);
+ when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
+ .thenReturn(validAsyncRegistration);
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
+ when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
+
+ // Execution
+
+ asyncRegistrationQueueRunner.runAsyncRegistrationQueueWorker();
+
+ // Set up second invocation of runner. This time, do return a valid source.
+ Answer<Optional<Source>> answerAsyncSourceFetcher =
+ getAsyncSourceAnswerForLocationTypeRedirectToWellKnown(
+ LOCATION_TYPE_REDIRECT_URI_2, validAsyncRegistration);
+
+ doAnswer(answerAsyncSourceFetcher)
+ .when(mAsyncSourceFetcher)
+ .fetchSource(any(), any(), any());
+
+ asyncRegistrationQueueRunner.runAsyncRegistrationQueueWorker();
+
+ ArgumentCaptor<AsyncRegistration> asyncRegistrationArgumentCaptor =
+ ArgumentCaptor.forClass(AsyncRegistration.class);
+
+ // Assertions
+ verify(mAsyncSourceFetcher, times(2))
+ .fetchSource(any(AsyncRegistration.class), any(), any());
+ verify(mMeasurementDao, times(1)).insertEventReport(any(EventReport.class));
+ verify(mMeasurementDao, times(1)).insertSource(any(Source.class));
+ verify(mMeasurementDao, times(2))
+ .insertAsyncRegistration(asyncRegistrationArgumentCaptor.capture());
+
+ Assert.assertEquals(2, asyncRegistrationArgumentCaptor.getAllValues().size());
+ AsyncRegistration asyncReg = asyncRegistrationArgumentCaptor.getAllValues().get(0);
+
+ // Assert first invocation's redirect
+ Uri expectedUri =
+ getRegistrationRedirectToWellKnownUri(
+ Uri.parse(LOCATION_TYPE_REDIRECT_URI),
+ LOCATION_TYPE_REDIRECT_URI.toString());
+ Assert.assertEquals(expectedUri, asyncReg.getRegistrationUri());
+
+ AsyncRegistration asyncReg2 = asyncRegistrationArgumentCaptor.getAllValues().get(1);
+
+ // Assert second invocation's redirect
+ expectedUri =
+ getRegistrationRedirectToWellKnownUri(
+ Uri.parse(LOCATION_TYPE_REDIRECT_URI_2),
+ LOCATION_TYPE_REDIRECT_URI_2.toString());
+ Assert.assertEquals(expectedUri, asyncReg2.getRegistrationUri());
+ }
+
+ @Test
+ public void runAsyncRegistrationQueueWorker_appSrc_defaultReg_redirectAlreadyWellKnown()
+ throws DatastoreException {
+ // Setup
+ AsyncRegistrationQueueRunner asyncRegistrationQueueRunner =
+ getSpyAsyncRegistrationQueueRunner();
+ AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
+ String redirectAlreadyWellKnown =
+ LOCATION_TYPE_REDIRECT_URI + "/" + AsyncRedirects.WELL_KNOWN_PATH_SEGMENT;
+ Answer<Optional<Source>> answerAsyncSourceFetcher =
+ getAsyncSourceAnswerForLocationTypeRedirectToWellKnown(
+ redirectAlreadyWellKnown, validAsyncRegistration);
+ doAnswer(answerAsyncSourceFetcher)
+ .when(mAsyncSourceFetcher)
+ .fetchSource(any(), any(), any());
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+
+ List<Source.FakeReport> eventReportList =
+ Collections.singletonList(
+ new Source.FakeReport(new UnsignedLong(1L), 1L, List.of(APP_DESTINATION)));
+ when(mSourceNoiseHandler.assignAttributionModeAndGenerateFakeReports(mMockedSource))
+ .thenReturn(eventReportList);
+ when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
+ .thenReturn(validAsyncRegistration);
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
+ when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
+
+ // Execution
+
+ asyncRegistrationQueueRunner.runAsyncRegistrationQueueWorker();
+
+ ArgumentCaptor<AsyncRegistration> asyncRegistrationArgumentCaptor =
+ ArgumentCaptor.forClass(AsyncRegistration.class);
+
+ // Assertions
+ verify(mAsyncSourceFetcher, times(1))
+ .fetchSource(any(AsyncRegistration.class), any(), any());
+ verify(mMeasurementDao, times(1)).insertEventReport(any(EventReport.class));
+ verify(mMeasurementDao, times(1)).insertSource(any(Source.class));
+ verify(mMeasurementDao, times(1))
+ .insertAsyncRegistration(asyncRegistrationArgumentCaptor.capture());
+
+ Assert.assertEquals(1, asyncRegistrationArgumentCaptor.getAllValues().size());
+ AsyncRegistration asyncReg = asyncRegistrationArgumentCaptor.getAllValues().get(0);
+ // Assert .well-known isn't duplicated in path.
+ Assert.assertEquals(
+ getRegistrationRedirectToWellKnownUri(
+ Uri.parse(LOCATION_TYPE_REDIRECT_URI), redirectAlreadyWellKnown.toString()),
+ asyncReg.getRegistrationUri());
+ }
+
+ @Test
public void runAsyncRegistrationQueueWorker_appInstalled_markToBeDeleted()
throws DatastoreException, PackageManager.NameNotFoundException {
// Setup
@@ -639,17 +959,18 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
mLogger);
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(
+ WebUtil.validUri("https://example.test/sF1").toString(),
+ WebUtil.validUri("https://example.test/sF2").toString()));
Answer<?> answerAsyncSourceFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- WebUtil.validUri("https://example.test/sF1"),
- WebUtil.validUri("https://example.test/sF2")));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(
SourceFixture.getValidSourceBuilder()
.setDropSourceIfInstalled(true)
@@ -670,14 +991,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
// Execution
@@ -713,17 +1027,18 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
mLogger);
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(
+ WebUtil.validUri("https://example.test/sF1").toString(),
+ WebUtil.validUri("https://example.test/sF2").toString()));
Answer<?> answerAsyncSourceFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- WebUtil.validUri("https://example.test/sF1"),
- WebUtil.validUri("https://example.test/sF2")));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(
SourceFixture.getValidSourceBuilder()
.setDropSourceIfInstalled(true)
@@ -744,14 +1059,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
// Execution
@@ -786,17 +1094,18 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
mLogger);
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(
+ WebUtil.validUri("https://example.test/sF1").toString(),
+ WebUtil.validUri("https://example.test/sF2").toString()));
Answer<?> answerAsyncSourceFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- WebUtil.validUri("https://example.test/sF1"),
- WebUtil.validUri("https://example.test/sF2")));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(
SourceFixture.getValidSourceBuilder()
.setDropSourceIfInstalled(false)
@@ -817,14 +1126,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
// Execution
@@ -860,17 +1162,18 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
mLogger);
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppSource();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(
+ WebUtil.validUri("https://example.test/sF1").toString(),
+ WebUtil.validUri("https://example.test/sF2").toString()));
Answer<?> answerAsyncSourceFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- WebUtil.validUri("https://example.test/sF1"),
- WebUtil.validUri("https://example.test/sF2")));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(
SourceFixture.getValidSourceBuilder()
.setDropSourceIfInstalled(false)
@@ -891,14 +1194,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
// Execution
@@ -922,17 +1218,16 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppTrigger();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(LIST_TYPE_REDIRECT_URI_1, LIST_TYPE_REDIRECT_URI_2));
Answer<Optional<Trigger>> answerAsyncTriggerFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- Uri.parse(LIST_TYPE_REDIRECT_URI_1),
- Uri.parse(LIST_TYPE_REDIRECT_URI_2)));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedTrigger);
};
doAnswer(answerAsyncTriggerFetcher)
@@ -942,14 +1237,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
// Execution
@@ -996,15 +1284,16 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppTrigger();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LOCATION,
+ List.of(LOCATION_TYPE_REDIRECT_URI));
Answer<Optional<Trigger>> answerAsyncTriggerFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LOCATION,
- List.of(Uri.parse(LOCATION_TYPE_REDIRECT_URI)));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedTrigger);
};
doAnswer(answerAsyncTriggerFetcher)
@@ -1014,14 +1303,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
when(mMeasurementDao.fetchNextQueuedAsyncRegistration(anyInt(), any()))
.thenReturn(validAsyncRegistration)
.thenReturn(null);
- KeyValueData redirectCount =
- new KeyValueData.Builder()
- .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
- .setKey(
- AsyncRegistrationFixture.ValidAsyncRegistrationParams
- .REGISTRATION_ID)
- .setValue(null) // Should default to 1
- .build();
+ KeyValueData redirectCount = getKeyValueDataRedirectCount();
when(mMeasurementDao.getKeyValueData(anyString(), any())).thenReturn(redirectCount);
// Execution
@@ -1059,15 +1341,16 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppTrigger();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LOCATION,
+ List.of(LOCATION_TYPE_REDIRECT_URI));
Answer<Optional<Trigger>> answerAsyncTriggerFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LOCATION,
- List.of(Uri.parse(LOCATION_TYPE_REDIRECT_URI)));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedTrigger);
};
doAnswer(answerAsyncTriggerFetcher)
@@ -1120,17 +1403,18 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppTrigger();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ IntStream.range(1, 10)
+ .mapToObj((i) -> LIST_TYPE_REDIRECT_URI_1 + "/" + i)
+ .collect(Collectors.toList()));
Answer<Optional<Trigger>> answerAsyncTriggerFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- IntStream.range(1, 10)
- .mapToObj((i) -> Uri.parse(LIST_TYPE_REDIRECT_URI_1 + "/" + i))
- .collect(Collectors.toList()));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedTrigger);
};
doAnswer(answerAsyncTriggerFetcher)
@@ -1189,15 +1473,16 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppTrigger();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LOCATION,
+ Collections.singletonList((LOCATION_TYPE_REDIRECT_URI)));
Answer<Optional<Trigger>> answerAsyncTriggerFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LOCATION,
- Collections.singletonList(Uri.parse(LOCATION_TYPE_REDIRECT_URI)));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedTrigger);
};
doAnswer(answerAsyncTriggerFetcher)
@@ -1433,17 +1718,18 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppTrigger();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(
+ WebUtil.validUri("https://example.test/sF1").toString(),
+ WebUtil.validUri("https://example.test/sF2").toString()));
Answer<?> answerAsyncTriggerFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- WebUtil.validUri("https://example.test/sF1"),
- WebUtil.validUri("https://example.test/sF2")));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.of(mMockedTrigger);
};
doAnswer(answerAsyncTriggerFetcher)
@@ -1610,18 +1896,19 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
getSpyAsyncRegistrationQueueRunner();
AsyncRegistration validAsyncRegistration = createAsyncRegistrationForAppTrigger();
-
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(
+ AsyncRegistration.RedirectType.LIST,
+ List.of(
+ WebUtil.validUri("https://example.test/sF1").toString(),
+ WebUtil.validUri("https://example.test/sF2").toString()));
Answer<?> answerAsyncTriggerFetcher =
invocation -> {
AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
asyncFetchStatus.setEntityStatus(AsyncFetchStatus.EntityStatus.PARSING_ERROR);
- AsyncRedirect asyncRedirect = invocation.getArgument(2);
- asyncRedirect.addToRedirects(
- AsyncRegistration.RedirectType.LIST,
- List.of(
- WebUtil.validUri("https://example.test/sF1"),
- WebUtil.validUri("https://example.test/sF2")));
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, validAsyncRegistration);
return Optional.empty();
};
doAnswer(answerAsyncTriggerFetcher)
@@ -3285,12 +3572,56 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
assertTrue(status);
}
- private RegistrationRequest buildRequest(String registrationUri) {
- return new RegistrationRequest.Builder(
- RegistrationRequest.REGISTER_SOURCE,
- Uri.parse(registrationUri),
- sDefaultContext.getAttributionSource().getPackageName(),
- SDK_PACKAGE_NAME)
+ private static KeyValueData getKeyValueDataRedirectCount() {
+ return new KeyValueData.Builder()
+ .setDataType(KeyValueData.DataType.REGISTRATION_REDIRECT_COUNT)
+ .setKey(AsyncRegistrationFixture.ValidAsyncRegistrationParams.REGISTRATION_ID)
+ .setValue(null) // Should default to 1
+ .build();
+ }
+
+ private Map<String, List<String>> getRedirectHeaders(
+ AsyncRegistration.RedirectType redirectType, List<String> uris) {
+ Map<String, List<String>> headers = new HashMap<>();
+ if (redirectType.equals(AsyncRegistration.RedirectType.LOCATION)) {
+ headers.put(AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, uris);
+ } else {
+ headers.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, uris);
+ }
+
+ return headers;
+ }
+
+ private void assertRepeatedAsyncRegistration(
+ ArgumentCaptor<AsyncRegistration> asyncRegistrationArgumentCaptor,
+ int index,
+ Uri redirectUri) {
+ AsyncRegistration asyncReg = asyncRegistrationArgumentCaptor.getAllValues().get(index);
+ Assert.assertEquals(redirectUri, asyncReg.getRegistrationUri());
+ }
+
+ private Answer<Optional<Source>> getAsyncSourceAnswerForLocationTypeRedirectToWellKnown(
+ String redirectUri, AsyncRegistration asyncRegistration) {
+ Map<String, List<String>> redirectHeaders =
+ getRedirectHeaders(AsyncRegistration.RedirectType.LOCATION, List.of(redirectUri));
+ redirectHeaders.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
+ return invocation -> {
+ AsyncFetchStatus asyncFetchStatus = invocation.getArgument(1);
+ asyncFetchStatus.setResponseStatus(AsyncFetchStatus.ResponseStatus.SUCCESS);
+ AsyncRedirects asyncRedirects = invocation.getArgument(2);
+ asyncRedirects.configure(redirectHeaders, mFlags, asyncRegistration);
+ return Optional.of(mMockedSource);
+ };
+ }
+
+ private Uri getRegistrationRedirectToWellKnownUri(
+ Uri registrationUri, String originalUriString) {
+ return registrationUri
+ .buildUpon()
+ .encodedPath(AsyncRedirects.WELL_KNOWN_PATH_SEGMENT)
+ .appendQueryParameter(AsyncRedirects.WELL_KNOWN_QUERY_PARAM, originalUriString)
.build();
}
@@ -3316,7 +3647,7 @@ public final class AsyncRegistrationQueueRunnerTest extends AdServicesExtendedMo
new Source.FakeReport(
new UnsignedLong(0L),
new EventReportWindowCalcDelegate(mFlags)
- .getReportingTimeForNoising(source, 0, false),
+ .getReportingTimeForNoising(source, 0),
destinations))
.collect(Collectors.toList());
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncSourceFetcherTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncSourceFetcherTest.java
index 0489c91f5..aa07077e8 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncSourceFetcherTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncSourceFetcherTest.java
@@ -122,6 +122,15 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
private static final String LIST_TYPE_REDIRECT_URI = WebUtil.validUrl("https://bar.test");
private static final String LOCATION_TYPE_REDIRECT_URI =
WebUtil.validUrl("https://example.test");
+ private static final String LOCATION_TYPE_REDIRECT_WELLKNOWN_URI =
+ WebUtil.validUrl(
+ LOCATION_TYPE_REDIRECT_URI
+ + "/"
+ + AsyncRedirects.WELL_KNOWN_PATH_SEGMENT
+ + "?"
+ + AsyncRedirects.WELL_KNOWN_QUERY_PARAM
+ + "="
+ + Uri.encode(LOCATION_TYPE_REDIRECT_URI));
private static final long ALT_EVENT_ID = 123456789;
private static final long ALT_EXPIRY = 456790;
private static final Uri REGISTRATION_URI_1 = WebUtil.validUri("https://subdomain.foo.test");
@@ -226,6 +235,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
.thenReturn(Flags.MEASUREMENT_MAX_INSTALL_ATTRIBUTION_WINDOW);
when(mFlags.getMeasurementMinInstallAttributionWindow())
.thenReturn(Flags.MEASUREMENT_MIN_INSTALL_ATTRIBUTION_WINDOW);
+ when(mFlags.getMeasurementVtcConfigurableMaxEventReportsCount())
+ .thenReturn(Flags.DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT);
+ when(mFlags.getMeasurementEventReportsVtcEarlyReportingWindows())
+ .thenReturn(Flags.MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS);
+ when(mFlags.getMeasurementEventReportsCtcEarlyReportingWindows())
+ .thenReturn(Flags.MEASUREMENT_EVENT_REPORTS_CTC_EARLY_REPORTING_WINDOWS);
}
@Test
@@ -260,13 +275,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "}\n")));
when(mFlags.getMeasurementEnableXNA()).thenReturn(true);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
asyncFetchStatus.setRegistrationDelay(0L);
// Execution
AsyncRegistration asyncRegistration = appSourceRegistrationRequest(request);
Optional<Source> fetch =
- mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -319,7 +334,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
when(mUrlConnection.getHeaderFields())
.thenReturn(
Map.of(
- "Attribution-Reporting-Redirect",
+ AsyncRedirects.REDIRECT_LIST_HEADER_KEY,
List.of(LIST_TYPE_REDIRECT_URI),
"Attribution-Reporting-Register-Source",
List.of(
@@ -340,19 +355,20 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_KEY
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
// Redirects should be parsed & added
verify(mFetcher, times(1)).openUrl(any());
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
- assertEquals(1, asyncRedirect.getRedirects().size());
- assertEquals(LIST_TYPE_REDIRECT_URI, asyncRedirect.getRedirects().get(0).toString());
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LIST_TYPE_REDIRECT_URI, asyncRedirects.getRedirects().get(0).getUri().toString());
// Source shouldn't be created
assertEquals(
@@ -385,12 +401,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"expiry\": \"432000\","
+ "\"source_event_id\": \"987654321\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -433,12 +449,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"expiry\": \"432000\","
+ "\"source_event_id\": \"987654321\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -476,12 +492,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"expiry\": \"432000\","
+ "\"source_event_id\": \"987654321\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -520,12 +536,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"expiry\": \"432000\","
+ "\"source_event_id\": \"987654321\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -555,12 +571,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -597,12 +613,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"install_attribution_window\": null,\n"
+ " \"post_install_exclusivity_window\": null\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -646,12 +662,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\":"
+ " \"9876543210\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -678,12 +694,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
WebUtil.validUri("http://foo.test"),
sContext.getPackageName(),
SDK_PACKAGE_NAME);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.ResponseStatus.INVALID_URL, asyncFetchStatus.getResponseStatus());
@@ -698,12 +714,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
WebUtil.validUri("bad-schema://foo.test"),
sContext.getPackageName(),
SDK_PACKAGE_NAME);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.ResponseStatus.INVALID_URL, asyncFetchStatus.getResponseStatus());
@@ -716,12 +732,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
doThrow(new IOException("Bad internet things"))
.when(mFetcher)
.openUrl(new URL(DEFAULT_REGISTRATION));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.ResponseStatus.NETWORK_ERROR,
@@ -743,12 +759,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"source_event_id\": \""
+ DEFAULT_EVENT_ID
+ "\"")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.PARSING_ERROR, asyncFetchStatus.getEntityStatus());
@@ -762,12 +778,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(DEFAULT_REGISTRATION));
when(mUrlConnection.getResponseCode()).thenReturn(200);
when(mUrlConnection.getHeaderFields()).thenReturn(Collections.emptyMap());
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -790,12 +806,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"destination\": \""
+ DEFAULT_DESTINATION
+ "\"")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.PARSING_ERROR, asyncFetchStatus.getEntityStatus());
@@ -821,12 +837,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -861,12 +877,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"source_event_id\":\"" + DEFAULT_EVENT_ID + "\","
+ "\"expiry\":\"-15\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -893,12 +909,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\","
+ "\"expiry\":\"86399\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -933,12 +949,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\","
+ "\"expiry\":\"2592001\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -980,12 +996,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ TimeUnit.DAYS.toSeconds(1) / 2L)
+ "\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1025,12 +1041,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
- 1L)
+ "\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1067,12 +1083,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ String.valueOf(TimeUnit.HOURS.toSeconds(25))
+ "\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1107,12 +1123,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\","
+ "\"expiry\":\"172800\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1149,12 +1165,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"86400\","
+ "\"aggregatable_report_window\":\"86400\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1192,12 +1208,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"2000\","
+ "\"aggregatable_report_window\":\"1728\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1236,12 +1252,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"2000\","
+ "\"aggregatable_report_window\":\"1728\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1279,12 +1295,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"172801\","
+ "\"aggregatable_report_window\":\"172801\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1323,12 +1339,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"2592001\","
+ "\"aggregatable_report_window\":\"2592001\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1362,12 +1378,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":86400,"
+ "\"aggregatable_report_window\":86400"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -1397,12 +1413,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"-86400\","
+ "\"aggregatable_report_window\":\"86400\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -1428,12 +1444,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"86400\","
+ "\"aggregatable_report_window\":\"-86400\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -1457,12 +1473,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"source_event_id\":\"" + DEFAULT_EVENT_ID + "\","
+ "\"priority\":15"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -1486,13 +1502,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\","
+ "\"source_event_id\":35}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -1517,13 +1533,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\","
+ "\"source_event_id\":\"-35\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -1546,13 +1562,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\","
+ "\"source_event_id\":\"-35\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -1577,13 +1593,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\",\"source_event_id\":\""
+ "18446744073709551616\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -1606,13 +1622,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\",\"source_event_id\":\""
+ "18446744073709551616\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -1637,13 +1653,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\","
+ "\"source_event_id\":\"8l2\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -1666,13 +1682,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\","
+ "\"source_event_id\":\"8l2\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -1713,13 +1729,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "}\n")));
when(mFlags.getMeasurementEnableXNA()).thenReturn(false);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -1751,13 +1767,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\",\"source_event_id\":\""
+ "18446744073709551615\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -1793,13 +1809,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\","
+ "\"debug_key\":18}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -1835,13 +1851,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\","
+ "\"debug_key\":\"-18\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -1878,13 +1894,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\","
+ "\"debug_key\":\"18446744073709551616\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -1920,13 +1936,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\","
+ "\"debug_key\":\"987fs\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -1962,13 +1978,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\","
+ "\"debug_key\":\"18446744073709551615\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -2005,12 +2021,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"expiry\": null\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -2047,12 +2063,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\",\n"
+ "\"expiry\": 1"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -2089,12 +2105,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\",\n"
+ "\"expiry\": \"1\""
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -2131,12 +2147,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\",\n"
+ "\"expiry\": 2678400"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -2173,12 +2189,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\",\n"
+ "\"expiry\": \"2678400\""
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -2213,13 +2229,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\","
+ "\"debug_reporting\":\"true\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -2254,13 +2270,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\","
+ "\"debug_reporting\":\"invalid\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -2295,13 +2311,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\","
+ "\"debug_reporting\":\"null\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -2336,13 +2352,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\","
+ "\"debug_reporting\":null}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -2376,13 +2392,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"source_event_id\":\""
+ DEFAULT_EVENT_ID
+ "\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
@@ -2421,12 +2437,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ ""
+ "}\n"));
when(mUrlConnection.getHeaderFields()).thenReturn(headersSecondRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.ResponseStatus.SERVER_UNAVAILABLE,
@@ -2442,7 +2458,8 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
when(mUrlConnection.getResponseCode()).thenReturn(200);
Map<String, List<String>> headersFirstRequest = new HashMap<>();
headersFirstRequest.put("Attribution-Reporting-Register-Source", List.of("{}"));
- headersFirstRequest.put("Attribution-Reporting-Redirect", List.of(LIST_TYPE_REDIRECT_URI));
+ headersFirstRequest.put(
+ AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
Map<String, List<String>> headersSecondRequest = new HashMap<>();
headersSecondRequest.put(
"Attribution-Reporting-Register-Source",
@@ -2461,16 +2478,17 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
when(mUrlConnection.getHeaderFields())
.thenReturn(headersFirstRequest)
.thenReturn(headersSecondRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
- assertEquals(1, asyncRedirect.getRedirects().size());
- assertEquals(LIST_TYPE_REDIRECT_URI, asyncRedirect.getRedirects().get(0).toString());
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LIST_TYPE_REDIRECT_URI, asyncRedirects.getRedirects().get(0).getUri().toString());
assertEquals(
AsyncFetchStatus.EntityStatus.PARSING_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
@@ -2500,14 +2518,15 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EXPIRY
+ ""
+ "}\n"));
- headersFirstRequest.put("Attribution-Reporting-Redirect", List.of(LIST_TYPE_REDIRECT_URI));
+ headersFirstRequest.put(
+ AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
when(mUrlConnection.getHeaderFields()).thenReturn(headersFirstRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(AsyncFetchStatus.EntityStatus.SUCCESS, asyncFetchStatus.getEntityStatus());
@@ -2520,8 +2539,9 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
assertEquals(
result.getEventTime() + TimeUnit.SECONDS.toMillis(DEFAULT_EXPIRY_ROUNDED),
result.getExpiryTime());
- assertEquals(1, asyncRedirect.getRedirects().size());
- assertEquals(LIST_TYPE_REDIRECT_URI, asyncRedirect.getRedirects().get(0).toString());
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LIST_TYPE_REDIRECT_URI, asyncRedirects.getRedirects().get(0).getUri().toString());
assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
}
@@ -2549,14 +2569,15 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EXPIRY
+ "\""
+ "}\n"));
- headersFirstRequest.put("Attribution-Reporting-Redirect", List.of(LIST_TYPE_REDIRECT_URI));
+ headersFirstRequest.put(
+ AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
when(mUrlConnection.getHeaderFields()).thenReturn(headersFirstRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(AsyncFetchStatus.EntityStatus.SUCCESS, asyncFetchStatus.getEntityStatus());
@@ -2569,8 +2590,9 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
assertEquals(
result.getEventTime() + TimeUnit.SECONDS.toMillis(DEFAULT_EXPIRY_ROUNDED),
result.getExpiryTime());
- assertEquals(1, asyncRedirect.getRedirects().size());
- assertEquals(LIST_TYPE_REDIRECT_URI, asyncRedirect.getRedirects().get(0).toString());
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LIST_TYPE_REDIRECT_URI, asyncRedirects.getRedirects().get(0).getUri().toString());
assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
}
@@ -2585,33 +2607,36 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
Map<String, List<String>> headers = getDefaultHeaders();
// Populate both 'list' and 'location' type headers
- headers.put("Attribution-Reporting-Redirect", List.of(LIST_TYPE_REDIRECT_URI));
- headers.put("Location", List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
when(mUrlConnection.getHeaderFields()).thenReturn(headers);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
assertDefaultSourceRegistration(result);
- assertEquals(2, asyncRedirect.getRedirects().size());
+ assertEquals(2, asyncRedirects.getRedirects().size());
assertEquals(
LIST_TYPE_REDIRECT_URI,
- asyncRedirect
+ asyncRedirects
.getRedirectsByType(AsyncRegistration.RedirectType.LIST)
.get(0)
+ .getUri()
.toString());
assertEquals(
LOCATION_TYPE_REDIRECT_URI,
- asyncRedirect
+ asyncRedirects
.getRedirectsByType(AsyncRegistration.RedirectType.LOCATION)
.get(0)
+ .getUri()
.toString());
assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2625,22 +2650,25 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
Map<String, List<String>> headers = getDefaultHeaders();
// Populate only 'location' type header
- headers.put("Location", List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
when(mUrlConnection.getHeaderFields()).thenReturn(headers);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
assertDefaultSourceRegistration(result);
- assertEquals(1, asyncRedirect.getRedirects().size());
- assertEquals(LOCATION_TYPE_REDIRECT_URI, asyncRedirect.getRedirects().get(0).toString());
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_URI,
+ asyncRedirects.getRedirects().get(0).getUri().toString());
assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
}
@@ -2652,25 +2680,237 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
when(mUrlConnection.getResponseCode()).thenReturn(302);
Map<String, List<String>> headers = getDefaultHeaders();
- headers.put("Attribution-Reporting-Redirect", List.of(LIST_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ // Execution
+ Optional<Source> fetch =
+ mFetcher.fetchSource(
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Source result = fetch.get();
+ assertDefaultSourceRegistration(result);
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LIST_TYPE_REDIRECT_URI, asyncRedirects.getRedirects().get(0).getUri().toString());
+ assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testRedirects_locationRedirectHeadersToWellKnown() throws Exception {
+ RegistrationRequest request = buildRequest(DEFAULT_REGISTRATION);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(any(URL.class));
+ when(mUrlConnection.getResponseCode()).thenReturn(302);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ // Execution
+ Optional<Source> fetch =
+ mFetcher.fetchSource(
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Source result = fetch.get();
+ assertDefaultSourceRegistration(result);
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_WELLKNOWN_URI,
+ asyncRedirects.getRedirects().get(0).getUri().toString());
+ assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testRedirects_bothHeaders_locationTypeToWellKnown() throws Exception {
+ RegistrationRequest request = buildRequest(DEFAULT_REGISTRATION);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(any(URL.class));
+ when(mUrlConnection.getResponseCode()).thenReturn(200);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
when(mUrlConnection.getHeaderFields()).thenReturn(headers);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
assertDefaultSourceRegistration(result);
- assertEquals(1, asyncRedirect.getRedirects().size());
- assertEquals(LIST_TYPE_REDIRECT_URI, asyncRedirect.getRedirects().get(0).toString());
+ assertEquals(2, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_WELLKNOWN_URI,
+ asyncRedirects
+ .getRedirectsByType(AsyncRegistration.RedirectType.LOCATION)
+ .get(0)
+ .getUri()
+ .toString());
+ assertEquals(
+ LIST_TYPE_REDIRECT_URI,
+ asyncRedirects
+ .getRedirectsByType(AsyncRegistration.RedirectType.LIST)
+ .get(0)
+ .getUri()
+ .toString());
+ assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testRedirects_wellKnownHeader_noop() throws Exception {
+ RegistrationRequest request = buildRequest(DEFAULT_REGISTRATION);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(any(URL.class));
+ when(mUrlConnection.getResponseCode()).thenReturn(302);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ // Populate only redirect behavior header with no actual redirect
+ headers.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ // Execution
+ Optional<Source> fetch =
+ mFetcher.fetchSource(
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Source result = fetch.get();
+ assertDefaultSourceRegistration(result);
+ assertEquals(0, asyncRedirects.getRedirects().size());
+ assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testRedirects_wellKnownHeader_acceptsListTypeWithNoLocationType() throws Exception {
+ RegistrationRequest request = buildRequest(DEFAULT_REGISTRATION);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(any(URL.class));
+ when(mUrlConnection.getResponseCode()).thenReturn(200);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ headers.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ // Execution
+ Optional<Source> fetch =
+ mFetcher.fetchSource(
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Source result = fetch.get();
+ assertDefaultSourceRegistration(result);
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LIST_TYPE_REDIRECT_URI,
+ asyncRedirects
+ .getRedirectsByType(AsyncRegistration.RedirectType.LIST)
+ .get(0)
+ .getUri()
+ .toString());
assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
}
+
+ @Test
+ public void testRedirects_locationRedirectHeaders_wellKnownHeaderMisconfigured()
+ throws Exception {
+ RegistrationRequest request = buildRequest(DEFAULT_REGISTRATION);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(any(URL.class));
+ when(mUrlConnection.getResponseCode()).thenReturn(302);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG, List.of("BAD"));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ // Execution
+ Optional<Source> fetch =
+ mFetcher.fetchSource(
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Source result = fetch.get();
+ assertDefaultSourceRegistration(result);
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_URI,
+ asyncRedirects.getRedirects().get(0).getUri().toString());
+ assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testRedirects_locationRedirectHeaders_wellKnownHeaderNull() throws Exception {
+ RegistrationRequest request = buildRequest(DEFAULT_REGISTRATION);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(any(URL.class));
+ when(mUrlConnection.getResponseCode()).thenReturn(302);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG, null);
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ // Execution
+ Optional<Source> fetch =
+ mFetcher.fetchSource(
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Source result = fetch.get();
+ assertDefaultSourceRegistration(result);
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_URI,
+ asyncRedirects.getRedirects().get(0).getUri().toString());
+ assertEquals(DEFAULT_REGISTRATION, result.getRegistrationOrigin().toString());
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
// End tests for redirect types
@Test
@@ -2693,12 +2933,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\",\n"
+ filterData
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -2736,12 +2976,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\",\n"
+ filterData
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -2770,12 +3010,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\",\n"
+ filterData
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2807,12 +3047,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\",\n"
+ filterData
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2841,12 +3081,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\",\n"
+ filterData
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2882,12 +3122,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\",\n"
+ filterData
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2916,12 +3156,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\",\n"
+ filterData
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2949,12 +3189,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\",\n"
+ filterData
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2967,8 +3207,10 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
doReturn(mUrlConnection).when(mFetcher).openUrl(any(URL.class));
when(mUrlConnection.getResponseCode()).thenReturn(200);
when(mUrlConnection.getHeaderFields())
- .thenReturn(Map.of(
- "Attribution-Reporting-Redirect", List.of(LIST_TYPE_REDIRECT_URI)))
+ .thenReturn(
+ Map.of(
+ AsyncRedirects.REDIRECT_LIST_HEADER_KEY,
+ List.of(LIST_TYPE_REDIRECT_URI)))
.thenReturn(
Map.of(
"Attribution-Reporting-Register-Source",
@@ -2987,22 +3229,23 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.HEADER_MISSING, asyncFetchStatus.getEntityStatus());
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
- assertEquals(1, asyncRedirect.getRedirects().size());
+ assertEquals(1, asyncRedirects.getRedirects().size());
assertEquals(
LIST_TYPE_REDIRECT_URI,
- asyncRedirect
+ asyncRedirects
.getRedirectsByType(AsyncRegistration.RedirectType.LIST)
.get(0)
+ .getUri()
.toString());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -3027,12 +3270,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"aggregation_keys\": {\"campaignCounts\" :"
+ " \"0x159\", \"geoValue\" : \"0x5\"}\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3065,12 +3308,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"aggregation_keys\": {\"campaignCounts\" :"
+ " \"0x159G\", \"geoValue\" : \"0x5\"}\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -3098,12 +3341,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"aggregation_keys\": {\"campaignCounts\" :"
+ " \"0x159G\", \"geoValue\" : \"0x5\"}\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3140,12 +3383,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\":"
+ " \"987654321\",\"aggregation_keys\": "
+ tooManyKeys)));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.PARSING_ERROR, asyncFetchStatus.getEntityStatus());
@@ -3176,12 +3419,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\":"
+ " \"987654321\",\"aggregation_keys\": "
+ tooManyKeys)));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection).setRequestMethod("POST");
@@ -3207,12 +3450,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"aggregation_keys\": [\"campaignCounts\","
+ " \"0x159\", \"geoValue\", \"0x5\"]\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -3240,12 +3483,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\": \"0x159\","
+ "\"geoValue\": \"0x5\"}\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -3272,12 +3515,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"aggregation_keys\": {\"campaignCounts\" :"
+ " \"0159\", \"geoValue\" : \"0x5\"}\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -3305,12 +3548,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ LONG_AGGREGATE_KEY_PIECE
+ "\"}\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -3341,17 +3584,17 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_KEY
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
AsyncRegistration asyncRegistration = webSourceRegistrationRequest(request, true);
Optional<Source> fetch =
- mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertEquals(EVENT_ID_1, result.getEventId());
@@ -3392,14 +3635,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"expiry\": \"432000\","
+ "\"source_event_id\": \"987654321\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3443,14 +3686,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"expiry\": \"432000\","
+ "\"source_event_id\": \"987654321\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3489,14 +3732,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"expiry\": \"432000\","
+ "\"source_event_id\": \"987654321\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -3536,14 +3779,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"expiry\": \"432000\","
+ "\"source_event_id\": \"987654321\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -3573,14 +3816,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\","
+ "\"expiry\":\"2000\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3612,14 +3855,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\","
+ "\"expiry\":\"2592001\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3659,14 +3902,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ TimeUnit.DAYS.toSeconds(1) / 2L)
+ "\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true, Source.SourceType.EVENT),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3704,14 +3947,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
- 1L)
+ "\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true, Source.SourceType.EVENT),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3746,14 +3989,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ String.valueOf(TimeUnit.HOURS.toSeconds(25))
+ "\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true, Source.SourceType.NAVIGATION),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3786,14 +4029,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\","
+ "\"expiry\":\"172800\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3828,14 +4071,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"86400\","
+ "\"aggregatable_report_window\":\"86400\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3872,14 +4115,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"2000\","
+ "\"aggregatable_report_window\":\"1728\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3916,14 +4159,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"2000\","
+ "\"aggregatable_report_window\":\"1728\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3959,14 +4202,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"172801\","
+ "\"aggregatable_report_window\":\"172801\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -4002,14 +4245,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_window\":\"2592001\","
+ "\"aggregatable_report_window\":\"2592001\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -4048,19 +4291,19 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_KEY
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertEquals(EVENT_ID_1, result.getEventId());
@@ -4100,18 +4343,18 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_KEY
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, false),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertEquals(EVENT_ID_1, result.getEventId());
@@ -4154,14 +4397,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_KEY
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -4201,19 +4444,19 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ aggregateSource
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(OS_DESTINATION, result.getAppDestinations().get(0));
assertEquals(filterData, result.getFilterDataString());
@@ -4257,24 +4500,24 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"aggregation_keys\": "
+ aggregateSource
+ "}"),
- "Attribution-Reporting-Redirect",
+ AsyncRedirects.REDIRECT_LIST_HEADER_KEY,
List.of(LIST_TYPE_REDIRECT_URI),
- "Location",
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY,
List.of(LOCATION_TYPE_REDIRECT_URI)));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertEquals(filterData, result.getFilterDataString());
@@ -4318,14 +4561,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"filter_data\": "
+ filterData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -4362,19 +4605,19 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_JOIN_KEY
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertEquals(EVENT_ID_1, result.getEventId());
@@ -4419,19 +4662,19 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_JOIN_KEY
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertEquals(EVENT_ID_1, result.getEventId());
@@ -4483,14 +4726,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"filter_data\": "
+ filterData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -4529,20 +4772,20 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ WEB_DESTINATION
+ "\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(OS_DESTINATION, result.getAppDestinations().get(0));
assertNull(result.getFilterDataString());
@@ -4585,20 +4828,20 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(OS_DESTINATION, result.getAppDestinations().get(0));
assertNull(result.getFilterDataString());
@@ -4638,19 +4881,19 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(OS_DESTINATION, result.getAppDestinations().get(0));
assertNull(result.getFilterDataString());
@@ -4683,14 +4926,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_EVENT_ID
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.PARSING_ERROR, asyncFetchStatus.getEntityStatus());
@@ -4723,19 +4966,19 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ EVENT_ID_1
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertNull(result.getFilterDataString());
@@ -4776,14 +5019,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ EVENT_ID_1
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -4813,13 +5056,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
asyncFetchStatus.setRegistrationDelay(0L);
AsyncRegistration asyncRegistration = appSourceRegistrationRequest(request);
// Execution
Optional<Source> fetch =
- mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, asyncRedirects);
assertTrue(fetch.isPresent());
FetcherUtil.emitHeaderMetrics(mFlags, mLogger, asyncRegistration, asyncFetchStatus);
@@ -4873,13 +5116,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_JOIN_KEY
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -4929,13 +5172,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_JOIN_KEY
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -4977,7 +5220,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
AsyncRegistration asyncRegistration = appSourceRegistrationRequest(request);
// Execution
Optional<Source> fetch =
- mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, new AsyncRedirect());
+ mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, new AsyncRedirects());
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5013,7 +5256,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
AsyncRegistration asyncRegistration = appSourceRegistrationRequest(request);
// Execution
Optional<Source> fetch =
- mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, new AsyncRedirect());
+ mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, new AsyncRedirects());
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5053,7 +5296,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\""
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
@@ -5061,7 +5304,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
mFetcher.fetchSource(
appSourceRegistrationRequestWithAdId(request),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -5105,19 +5348,19 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_AD_ID_VALUE
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertEquals(EVENT_ID_1, result.getEventId());
@@ -5162,19 +5405,19 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_AD_ID_VALUE
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertEquals(EVENT_ID_1, result.getEventId());
@@ -5218,19 +5461,19 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEBUG_AD_ID_VALUE
+ "\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
assertEquals(Uri.parse(DEFAULT_DESTINATION), result.getAppDestinations().get(0));
assertEquals(EVENT_ID_1, result.getEventId());
@@ -5246,7 +5489,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
}
@Test
- public void fetchSource_setsFakeEnrollmentId_whenDisableEnrollmentFlagIsTrue()
+ public void fetchSource_setsSiteEnrollmentId_whenDisableEnrollmentFlagIsTrue()
throws Exception {
String uri = "https://test1.example.com:8081";
RegistrationRequest request = buildRequest(uri);
@@ -5270,13 +5513,87 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
AsyncRegistration asyncRegistration = appSourceRegistrationRequest(request);
// Execution
Optional<Source> fetch =
- mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, new AsyncRedirect());
+ mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, new AsyncRedirects());
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Source result = fetch.get();
assertEquals("https://test1.example.com:8081", result.getRegistrationOrigin().toString());
- assertEquals(Enrollment.FAKE_ENROLLMENT, result.getEnrollmentId());
+ assertEquals("https://example.com", result.getEnrollmentId());
+ assertEquals(DEFAULT_DESTINATION, result.getAppDestinations().get(0).toString());
+ assertEquals(DEFAULT_EVENT_ID, result.getEventId());
+ verify(mUrlConnection).setRequestMethod("POST");
+ }
+
+ @Test
+ public void fetchSource_setsSiteEnrollmentId_whenDisableEnrollmentFlagIsTrueForIP()
+ throws Exception {
+ String uri = "https://127.0.0.1:8081";
+ RegistrationRequest request = buildRequest(uri);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(uri));
+ doReturn(true).when(mFlags).isDisableMeasurementEnrollmentCheck();
+ when(mUrlConnection.getResponseCode()).thenReturn(200);
+ when(mUrlConnection.getHeaderFields())
+ .thenReturn(
+ Map.of(
+ "Attribution-Reporting-Register-Source",
+ List.of(
+ "{\n"
+ + "\"destination\": \""
+ + DEFAULT_DESTINATION
+ + "\",\n"
+ + "\"source_event_id\": \""
+ + DEFAULT_EVENT_ID
+ + "\"\n"
+ + "}\n")));
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appSourceRegistrationRequest(request);
+ // Execution
+ Optional<Source> fetch =
+ mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, new AsyncRedirects());
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Source result = fetch.get();
+ assertEquals("https://127.0.0.1:8081", result.getRegistrationOrigin().toString());
+ assertEquals("https://127.0.0.1", result.getEnrollmentId());
+ assertEquals(DEFAULT_DESTINATION, result.getAppDestinations().get(0).toString());
+ assertEquals(DEFAULT_EVENT_ID, result.getEventId());
+ verify(mUrlConnection).setRequestMethod("POST");
+ }
+
+ @Test
+ public void fetchSource_setsSiteEnrollmentId_whenDisableEnrollmentFlagIsTrueForLocalhost()
+ throws Exception {
+ String uri = "https://localhost:8081";
+ RegistrationRequest request = buildRequest(uri);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(uri));
+ doReturn(true).when(mFlags).isDisableMeasurementEnrollmentCheck();
+ when(mUrlConnection.getResponseCode()).thenReturn(200);
+ when(mUrlConnection.getHeaderFields())
+ .thenReturn(
+ Map.of(
+ "Attribution-Reporting-Register-Source",
+ List.of(
+ "{\n"
+ + "\"destination\": \""
+ + DEFAULT_DESTINATION
+ + "\",\n"
+ + "\"source_event_id\": \""
+ + DEFAULT_EVENT_ID
+ + "\"\n"
+ + "}\n")));
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appSourceRegistrationRequest(request);
+ // Execution
+ Optional<Source> fetch =
+ mFetcher.fetchSource(asyncRegistration, asyncFetchStatus, new AsyncRedirects());
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Source result = fetch.get();
+ assertEquals("https://localhost:8081", result.getRegistrationOrigin().toString());
+ assertEquals("https://localhost", result.getEnrollmentId());
assertEquals(DEFAULT_DESTINATION, result.getAppDestinations().get(0).toString());
assertEquals(DEFAULT_EVENT_ID, result.getEventId());
verify(mUrlConnection).setRequestMethod("POST");
@@ -5307,12 +5624,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5345,12 +5662,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5384,12 +5701,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5423,12 +5740,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5463,12 +5780,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5502,12 +5819,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\"\n"
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5537,12 +5854,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5574,12 +5891,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"trigger_data_matching\": \"INVALID\","
+ "\"post_install_exclusivity_window\": \"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isEmpty());
}
@@ -5623,12 +5940,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5693,12 +6010,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5775,12 +6092,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5837,12 +6154,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -5887,12 +6204,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5954,14 +6271,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -6040,12 +6357,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -6092,12 +6409,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isEmpty());
}
@@ -6142,12 +6459,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isEmpty());
}
@@ -6193,12 +6510,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -6248,12 +6565,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -6321,12 +6638,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -6376,12 +6693,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -6447,12 +6764,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isEmpty());
}
@@ -6499,14 +6816,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertTrue(fetch.isEmpty());
}
@@ -6551,13 +6868,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isEmpty());
}
@@ -6603,7 +6920,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
@@ -6611,7 +6928,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertTrue(fetch.isEmpty());
}
@@ -6667,13 +6984,13 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isEmpty());
}
@@ -6731,7 +7048,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
@@ -6739,7 +7056,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertTrue(fetch.isEmpty());
}
@@ -6795,12 +7112,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -6878,14 +7195,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}\n")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -6951,12 +7268,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -7006,14 +7323,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
webSourceRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -7081,12 +7398,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7154,12 +7471,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7226,12 +7543,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7261,12 +7578,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\","
+ " \"max_event_level_reports\": 21"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7295,12 +7612,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\","
+ " \"max_event_level_reports\": -3"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7330,12 +7647,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"source_event_id\": \"987654321\","
+ " \"max_event_level_reports\": \"3\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7372,12 +7689,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_windows\":"
+ eventReportWindows
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7413,12 +7730,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_windows\":"
+ eventReportWindows
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7454,12 +7771,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_windows\":"
+ eventReportWindows
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -7506,12 +7823,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_windows\":"
+ eventReportWindows
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -7554,12 +7871,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_windows\":"
+ eventReportWindows
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7591,12 +7908,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_windows\":"
+ eventReportWindows
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7628,12 +7945,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_windows\":"
+ eventReportWindows
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7665,12 +7982,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\"event_report_windows\":"
+ eventReportWindows
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7705,12 +8022,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ ","
+ " \"max_event_level_reports\": 5"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7744,12 +8061,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ ","
+ " \"max_event_level_reports\": 5"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7783,12 +8100,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ ","
+ " \"max_event_level_reports\": 5"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7822,12 +8139,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ ","
+ " \"max_event_level_reports\": 5"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -7874,12 +8191,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -7927,12 +8244,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ " \"post_install_exclusivity_window\": "
+ "\"987654\""
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -7974,12 +8291,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ ","
+ " \"max_event_level_reports\": 5"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -8023,12 +8340,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ ","
+ " \"max_event_level_reports\": 5"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -8068,12 +8385,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ ","
+ " \"max_event_level_reports\": 5"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -8113,12 +8430,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ ","
+ " \"max_event_level_reports\": 5"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -8144,14 +8461,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\","
+ "\"source_event_id\":\"35\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
appSourceRegistrationRequestWithPostBody(request, POST_BODY),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(POST_BODY, outputStream.toString());
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -8176,14 +8493,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\","
+ "\"source_event_id\":\"35\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
appSourceRegistrationRequestWithPostBody(request, null),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -8209,7 +8526,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\","
+ "\"source_event_id\":\"35\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
String emptyPostBody = "";
@@ -8217,7 +8534,7 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
mFetcher.fetchSource(
appSourceRegistrationRequestWithPostBody(request, emptyPostBody),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(emptyPostBody, outputStream.toString());
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -8242,14 +8559,14 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ DEFAULT_DESTINATION
+ "\","
+ "\"source_event_id\":\"35\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
appSourceRegistrationRequestWithPostBody(request, POST_BODY),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -8276,12 +8593,12 @@ public final class AsyncSourceFetcherTest extends AdServicesExtendedMockitoTestC
+ "\","
+ "\"source_event_id\":\"35\","
+ "\"drop_source_if_installed\":true}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Source> fetch =
mFetcher.fetchSource(
- appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appSourceRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncTriggerFetcherTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncTriggerFetcherTest.java
index f22a19eb9..41605bc53 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncTriggerFetcherTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/AsyncTriggerFetcherTest.java
@@ -145,6 +145,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
WebUtil.validUrl("https://subdomain.bar.test");
private static final String LOCATION_TYPE_REDIRECT_URI =
WebUtil.validUrl("https://example.test");
+ private static final String LOCATION_TYPE_REDIRECT_WELLKNOWN_URI =
+ WebUtil.validUrl(
+ LOCATION_TYPE_REDIRECT_URI
+ + "/"
+ + AsyncRedirects.WELL_KNOWN_PATH_SEGMENT
+ + "?"
+ + AsyncRedirects.WELL_KNOWN_QUERY_PARAM
+ + "="
+ + Uri.encode(LOCATION_TYPE_REDIRECT_URI));
private static final Uri REGISTRATION_URI_1 = WebUtil.validUri("https://subdomain.foo.test");
private static final WebTriggerParams TRIGGER_REGISTRATION_1 =
new WebTriggerParams.Builder(REGISTRATION_URI_1).setDebugKeyAllowed(true).build();
@@ -248,13 +257,13 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
List.of("{\"event_trigger_data\":" + EVENT_TRIGGERS_1 + "}")));
doReturn(5000L).when(mFlags).getMaxResponseBasedRegistrationPayloadSizeBytes();
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
asyncFetchStatus.setRegistrationDelay(0L);
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -325,13 +334,13 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "}")));
doReturn(5000L).when(mFlags).getMaxResponseBasedRegistrationPayloadSizeBytes();
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
asyncFetchStatus.setRegistrationDelay(0L);
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -385,12 +394,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregateDedupKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -439,12 +448,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregateDedupKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -488,12 +497,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregateDedupKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -541,12 +550,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregateDedupKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -590,12 +599,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregateDedupKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -643,12 +652,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregateDedupKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -692,12 +701,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregateDedupKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -745,12 +754,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregateDedupKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -792,12 +801,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregateDedupKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -816,34 +825,37 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map<String, List<String>> headers = getDefaultHeaders();
// Populate both 'list' and 'location' type headers
- headers.put("Attribution-Reporting-Redirect", List.of(LIST_TYPE_REDIRECT_URI));
- headers.put("Location", List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
when(mUrlConnection.getHeaderFields()).thenReturn(headers);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
assertTriggerRegistration(asyncRegistration, result);
- assertEquals(2, asyncRedirect.getRedirects().size());
+ assertEquals(2, asyncRedirects.getRedirects().size());
assertEquals(
LIST_TYPE_REDIRECT_URI,
- asyncRedirect
+ asyncRedirects
.getRedirectsByType(AsyncRegistration.RedirectType.LIST)
.get(0)
+ .getUri()
.toString());
assertEquals(
LOCATION_TYPE_REDIRECT_URI,
- asyncRedirect
+ asyncRedirects
.getRedirectsByType(AsyncRegistration.RedirectType.LOCATION)
.get(0)
+ .getUri()
.toString());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -857,68 +869,295 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map<String, List<String>> headers = getDefaultHeaders();
// Populate only 'location' type header
- headers.put("Location", List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
when(mUrlConnection.getHeaderFields()).thenReturn(headers);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
assertTriggerRegistration(asyncRegistration, result);
- assertEquals(1, asyncRedirect.getRedirects().size());
- assertEquals(LOCATION_TYPE_REDIRECT_URI, asyncRedirect.getRedirects().get(0).toString());
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_URI,
+ asyncRedirects.getRedirects().get(0).getUri().toString());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
}
@Test
- public void testRedirectType_locationRedirectType_ignoresListType() throws Exception {
+ public void testRedirectType_locationRedirectType_acceptsListType() throws Exception {
RegistrationRequest request = buildRequest(TRIGGER_URI);
doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(TRIGGER_URI));
when(mUrlConnection.getResponseCode()).thenReturn(302);
Map<String, List<String>> headers = getDefaultHeaders();
// Populate both 'list' and 'location' type headers
- headers.put("Attribution-Reporting-Redirect", List.of(LIST_TYPE_REDIRECT_URI));
- headers.put("Location", List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
when(mUrlConnection.getHeaderFields()).thenReturn(headers);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
assertTriggerRegistration(asyncRegistration, result);
- assertEquals(2, asyncRedirect.getRedirects().size());
+ assertEquals(2, asyncRedirects.getRedirects().size());
assertEquals(
LOCATION_TYPE_REDIRECT_URI,
- asyncRedirect
+ asyncRedirects
+ .getRedirectsByType(AsyncRegistration.RedirectType.LOCATION)
+ .get(0)
+ .getUri()
+ .toString());
+ assertEquals(
+ LIST_TYPE_REDIRECT_URI,
+ asyncRedirects
+ .getRedirectsByType(AsyncRegistration.RedirectType.LIST)
+ .get(0)
+ .getUri()
+ .toString());
+
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testRedirectType_locationRedirectHeaderType_wellKnownPath() throws Exception {
+ RegistrationRequest request = buildRequest(TRIGGER_URI);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(TRIGGER_URI));
+ when(mUrlConnection.getResponseCode()).thenReturn(302);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ // Populate only 'location' type header
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
+ // Execution
+ Optional<Trigger> fetch =
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Trigger result = fetch.get();
+ assertTriggerRegistration(asyncRegistration, result);
+
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_WELLKNOWN_URI,
+ asyncRedirects.getRedirects().get(0).getUri().toString());
+
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testRedirectType_locationRedirectType_wellKnownPath_acceptsList() throws Exception {
+ RegistrationRequest request = buildRequest(TRIGGER_URI);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(TRIGGER_URI));
+ when(mUrlConnection.getResponseCode()).thenReturn(302);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
+ headers.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
+ // Execution
+ Optional<Trigger> fetch =
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Trigger result = fetch.get();
+ assertTriggerRegistration(asyncRegistration, result);
+
+ assertEquals(2, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_WELLKNOWN_URI,
+ asyncRedirects
.getRedirectsByType(AsyncRegistration.RedirectType.LOCATION)
.get(0)
+ .getUri()
.toString());
assertEquals(
LIST_TYPE_REDIRECT_URI,
- asyncRedirect
+ asyncRedirects
.getRedirectsByType(AsyncRegistration.RedirectType.LIST)
.get(0)
+ .getUri()
.toString());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
}
+ @Test
+ public void testWellKnownPathHeader_noop() throws Exception {
+ RegistrationRequest request = buildRequest(TRIGGER_URI);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(TRIGGER_URI));
+ when(mUrlConnection.getResponseCode()).thenReturn(200);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ // Populate behavior config header, but no redirects.
+ headers.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
+ // Execution
+ Optional<Trigger> fetch =
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Trigger result = fetch.get();
+ assertTriggerRegistration(asyncRegistration, result);
+
+ assertEquals(0, asyncRedirects.getRedirects().size());
+
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testWellKnownPathHeader_acceptsListTypeWithNoLocationType() throws Exception {
+ RegistrationRequest request = buildRequest(TRIGGER_URI);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(TRIGGER_URI));
+ when(mUrlConnection.getResponseCode()).thenReturn(200);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ // Populate behavior config header, but no Location type redirect.
+ headers.put(
+ AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG,
+ List.of(AsyncRedirects.REDIRECT_302_TO_WELL_KNOWN));
+ headers.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(LIST_TYPE_REDIRECT_URI));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
+ // Execution
+ Optional<Trigger> fetch =
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Trigger result = fetch.get();
+ assertTriggerRegistration(asyncRegistration, result);
+
+ assertEquals(1, asyncRedirects.getRedirects().size());
+
+ assertEquals(
+ LIST_TYPE_REDIRECT_URI,
+ asyncRedirects
+ .getRedirectsByType(AsyncRegistration.RedirectType.LIST)
+ .get(0)
+ .getUri()
+ .toString());
+
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testRedirectType_locationRedirectHeaderType_wellKnownHeaderMisconfigured()
+ throws Exception {
+ RegistrationRequest request = buildRequest(TRIGGER_URI);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(TRIGGER_URI));
+ when(mUrlConnection.getResponseCode()).thenReturn(302);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG, List.of("BAD"));
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
+ // Execution
+ Optional<Trigger> fetch =
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Trigger result = fetch.get();
+ assertTriggerRegistration(asyncRegistration, result);
+
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_URI,
+ asyncRedirects.getRedirects().get(0).getUri().toString());
+
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
+ @Test
+ public void testRedirectType_locationRedirectHeaderType_wellKnownHeaderNull() throws Exception {
+ RegistrationRequest request = buildRequest(TRIGGER_URI);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(TRIGGER_URI));
+ when(mUrlConnection.getResponseCode()).thenReturn(302);
+ when(mFlags.getMeasurementEnableRedirectToWellKnownPath()).thenReturn(true);
+ Map<String, List<String>> headers = getDefaultHeaders();
+
+ headers.put(
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY, List.of(LOCATION_TYPE_REDIRECT_URI));
+ headers.put(AsyncRedirects.HEADER_ATTRIBUTION_REPORTING_REDIRECT_CONFIG, null);
+
+ when(mUrlConnection.getHeaderFields()).thenReturn(headers);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
+ // Execution
+ Optional<Trigger> fetch =
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Trigger result = fetch.get();
+ assertTriggerRegistration(asyncRegistration, result);
+
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(
+ LOCATION_TYPE_REDIRECT_URI,
+ asyncRedirects.getRedirects().get(0).getUri().toString());
+
+ verify(mUrlConnection, times(1)).setRequestMethod("POST");
+ }
+
// End tests for redirect types
@Test
@@ -935,12 +1174,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -966,12 +1205,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggers + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -991,12 +1230,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"debug_key\": \"" + DEBUG_KEY + "\"}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1021,12 +1260,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1055,12 +1294,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggers + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -1080,15 +1319,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1107,15 +1346,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1135,12 +1374,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1165,15 +1404,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1194,12 +1433,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1223,15 +1462,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1251,12 +1490,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1280,12 +1519,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1309,12 +1548,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1338,15 +1577,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1366,15 +1605,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1394,15 +1633,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1422,12 +1661,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1452,12 +1691,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1482,15 +1721,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1510,15 +1749,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1539,12 +1778,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1568,15 +1807,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1596,12 +1835,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1628,15 +1867,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1658,15 +1897,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1689,12 +1928,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1721,15 +1960,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1752,12 +1991,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1784,15 +2023,15 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
- assertEquals(AsyncFetchStatus.EntityStatus.VALIDATION_ERROR,
- asyncFetchStatus.getEntityStatus());
+ assertEquals(
+ AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -1815,12 +2054,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1845,12 +2084,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1875,12 +2114,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -1905,12 +2144,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -1935,12 +2174,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -1961,12 +2200,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -1995,12 +2234,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2021,12 +2260,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2047,12 +2286,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -2080,12 +2319,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2113,12 +2352,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2142,12 +2381,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2179,12 +2418,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2208,12 +2447,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + eventTriggerData + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2234,12 +2473,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -2265,12 +2504,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2289,12 +2528,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2325,12 +2564,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_deduplication_keys\":"
+ tooManyEntries
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2362,12 +2601,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_deduplication_keys\":"
+ deduplicationKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2421,12 +2660,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ ",\"aggregatable_deduplication_keys\":"
+ deduplicationKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2481,12 +2720,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_deduplication_keys\":"
+ deduplicationKeys
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2509,12 +2748,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ ","
+ "\"aggregatable_deduplication_keys\":{}"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2537,12 +2776,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ ","
+ "\"aggregatable_deduplication_keys\":"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2565,12 +2804,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2589,12 +2828,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2621,12 +2860,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2645,12 +2884,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2669,12 +2908,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
when(mFlags.getMeasurementEnableLookbackWindowFilter()).thenReturn(true);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2693,12 +2932,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
when(mFlags.getMeasurementEnableLookbackWindowFilter()).thenReturn(true);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2717,12 +2956,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
when(mFlags.getMeasurementEnableLookbackWindowFilter()).thenReturn(true);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2741,12 +2980,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\":" + filters + "}")));
when(mFlags.getMeasurementEnableLookbackWindowFilter()).thenReturn(true);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2767,12 +3006,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"not_filters\":" + notFilters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -2798,12 +3037,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"not_filters\":" + notFilters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2822,12 +3061,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"not_filters\":" + notFilters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2850,12 +3089,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"not_filters\":" + notFilters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2874,12 +3113,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"not_filters\":" + notFilters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2906,12 +3145,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"not_filters\":" + notFilters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2930,12 +3169,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"not_filters\":" + notFilters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
@@ -2956,21 +3195,21 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields())
.thenReturn(
Map.of(
- "Attribution-Reporting-Redirect",
+ AsyncRedirects.REDIRECT_LIST_HEADER_KEY,
List.of(DEFAULT_REDIRECT),
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + EVENT_TRIGGERS_1 + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
verify(mFetcher, times(1)).openUrl(any());
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
- assertEquals(1, asyncRedirect.getRedirects().size());
- assertEquals(DEFAULT_REDIRECT, asyncRedirect.getRedirects().get(0).toString());
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(DEFAULT_REDIRECT, asyncRedirects.getRedirects().get(0).getUri().toString());
assertEquals(
AsyncFetchStatus.EntityStatus.INVALID_ENROLLMENT,
asyncFetchStatus.getEntityStatus());
@@ -2994,12 +3233,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3030,12 +3269,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -3062,12 +3301,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -3094,12 +3333,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -3126,12 +3365,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -3149,12 +3388,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
WebUtil.validUri("http://foo.test"),
CONTEXT.getPackageName(),
SDK_PACKAGE_NAME);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.ResponseStatus.INVALID_URL, asyncFetchStatus.getResponseStatus());
@@ -3178,11 +3417,11 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
false,
false,
null);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(registration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(registration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.ResponseStatus.INVALID_URL, asyncFetchStatus.getResponseStatus());
@@ -3195,12 +3434,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
doThrow(new IOException("Bad internet things"))
.when(mFetcher)
.openUrl(new URL(TRIGGER_URI));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.ResponseStatus.NETWORK_ERROR,
@@ -3219,12 +3458,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + EVENT_TRIGGERS_1 + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.ResponseStatus.SERVER_UNAVAILABLE,
@@ -3243,12 +3482,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\": [{}]}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3271,14 +3510,14 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
headersFirstRequest.put(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + EVENT_TRIGGERS_1 + "}"));
- headersFirstRequest.put("Attribution-Reporting-Redirect", List.of(DEFAULT_REDIRECT));
+ headersFirstRequest.put(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(DEFAULT_REDIRECT));
when(mUrlConnection.getHeaderFields()).thenReturn(headersFirstRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3298,21 +3537,22 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
doReturn(mUrlConnection).when(mFetcher).openUrl(any(URL.class));
when(mUrlConnection.getResponseCode()).thenReturn(200);
when(mUrlConnection.getHeaderFields())
- .thenReturn(Map.of("Attribution-Reporting-Redirect", List.of(DEFAULT_REDIRECT)))
+ .thenReturn(
+ Map.of(AsyncRedirects.REDIRECT_LIST_HEADER_KEY, List.of(DEFAULT_REDIRECT)))
.thenReturn(
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + EVENT_TRIGGERS_1 + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
- assertEquals(1, asyncRedirect.getRedirects().size());
- assertEquals(DEFAULT_REDIRECT, asyncRedirect.getRedirects().get(0).toString());
+ assertEquals(1, asyncRedirects.getRedirects().size());
+ assertEquals(DEFAULT_REDIRECT, asyncRedirects.getRedirects().get(0).getUri().toString());
assertEquals(
AsyncFetchStatus.EntityStatus.HEADER_MISSING, asyncFetchStatus.getEntityStatus());
@@ -3342,12 +3582,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregateTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3383,12 +3623,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregateTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.PARSING_ERROR, asyncFetchStatus.getEntityStatus());
@@ -3418,12 +3658,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregateTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3460,12 +3700,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregateTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3504,12 +3744,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"{\"aggregatable_trigger_data\":"
+ aggregateTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -3543,12 +3783,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"{\"aggregatable_trigger_data\":"
+ aggregateTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -3572,12 +3812,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3603,12 +3843,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"aggregatable_values\": " + tooManyKeys + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
@@ -3632,12 +3872,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"filters\": " + filters + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3668,14 +3908,14 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection1.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
webTriggerRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3722,14 +3962,14 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
webTriggerRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -3758,24 +3998,24 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\": " + EVENT_TRIGGERS_1 + "}"),
- "Attribution-Reporting-Redirect",
+ AsyncRedirects.REDIRECT_LIST_HEADER_KEY,
List.of(LIST_TYPE_REDIRECT_URI),
- "Location",
+ AsyncRedirects.REDIRECT_LOCATION_HEADER_KEY,
List.of(LOCATION_TYPE_REDIRECT_URI)));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
webTriggerRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
- assertEquals(0, asyncRedirect.getRedirects().size());
+ assertEquals(0, asyncRedirects.getRedirects().size());
assertEquals(new JSONArray(EVENT_TRIGGERS_1).toString(), result.getEventTriggers());
assertEquals(REGISTRATION_URI_1, result.getRegistrationOrigin());
verify(mUrlConnection).setRequestMethod("POST");
@@ -3802,11 +4042,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
- Optional<Trigger> fetch = mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ Optional<Trigger> fetch =
+ mFetcher.fetchTrigger(
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -3833,12 +4074,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -3867,12 +4108,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -3907,12 +4148,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -3942,12 +4183,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -3974,12 +4215,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4016,12 +4257,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4049,12 +4290,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4082,12 +4323,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -4118,12 +4359,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4157,12 +4398,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4191,12 +4432,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4234,12 +4475,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4268,12 +4509,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4307,12 +4548,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4342,12 +4583,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4385,12 +4626,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4420,12 +4661,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_trigger_data\": "
+ aggregatableTriggerData
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4447,12 +4688,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -4479,12 +4720,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -4511,12 +4752,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -4543,12 +4784,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -4572,12 +4813,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -4603,12 +4844,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
@@ -4633,12 +4874,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
@@ -4662,12 +4903,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
@@ -4692,12 +4933,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
@@ -4721,12 +4962,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
@@ -4753,12 +4994,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
@@ -4784,12 +5025,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
@@ -4816,12 +5057,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertEquals(
AsyncFetchStatus.EntityStatus.VALIDATION_ERROR, asyncFetchStatus.getEntityStatus());
assertFalse(fetch.isPresent());
@@ -4847,12 +5088,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
@@ -4876,12 +5117,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4905,12 +5146,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{\"aggregatable_values\": " + tooManyKeys + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4932,12 +5173,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\"aggregatable_values\": "
+ aggregatableValues
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
- appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirect);
+ appTriggerRegistrationRequest(request), asyncFetchStatus, asyncRedirects);
assertFalse(fetch.isPresent());
verify(mUrlConnection, times(1)).setRequestMethod("POST");
verify(mFetcher, times(1)).openUrl(any());
@@ -4970,14 +5211,14 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
"Attribution-Reporting-Register-Trigger",
List.of("{\"event_trigger_data\":" + EVENT_TRIGGERS_1 + "}")));
doReturn(5L).when(mFlags).getMaxResponseBasedRegistrationPayloadSizeBytes();
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
asyncFetchStatus.setRegistrationDelay(0L);
asyncFetchStatus.setRetryCount(0);
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
assertEquals(ENROLLMENT_ID, result.getEnrollmentId());
@@ -5073,7 +5314,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
attributionConfig1.serializeAsJson(mFlags),
attributionConfig2.serializeAsJson(mFlags)));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
@@ -5081,7 +5322,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -5180,7 +5421,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
attributionConfig1.serializeAsJson(mFlags),
attributionConfig2.serializeAsJson(mFlags)));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = webTriggerRegistrationRequest(request, true);
@@ -5188,7 +5429,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -5245,7 +5486,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "}")));
doReturn(5000L).when(mFlags).getMaxResponseBasedRegistrationPayloadSizeBytes();
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = webTriggerRegistrationRequest(request, true);
@@ -5253,7 +5494,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -5289,7 +5530,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, new AsyncRedirect());
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, new AsyncRedirects());
// Assertion
assertEquals(
@@ -5318,7 +5559,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "}")));
doReturn(5000L).when(mFlags).getMaxResponseBasedRegistrationPayloadSizeBytes();
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
@@ -5326,7 +5567,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -5361,7 +5602,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "}")));
doReturn(5000L).when(mFlags).getMaxResponseBasedRegistrationPayloadSizeBytes();
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
@@ -5369,7 +5610,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -5426,7 +5667,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "}")));
doReturn(5000L).when(mFlags).getMaxResponseBasedRegistrationPayloadSizeBytes();
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
@@ -5434,7 +5675,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
@@ -5469,14 +5710,14 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection1.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
webTriggerRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5514,14 +5755,14 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection1.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
webTriggerRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5552,12 +5793,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -5591,12 +5832,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -5627,12 +5868,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5665,12 +5906,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5702,12 +5943,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequestWithAdId(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertTrue(fetch.isPresent());
Trigger result = fetch.get();
@@ -5742,14 +5983,14 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection1.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
webTriggerRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5786,14 +6027,14 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection1.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
webTriggerRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5829,14 +6070,14 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection1.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
// Execution
Optional<Trigger> fetch =
mFetcher.fetchTrigger(
webTriggerRegistrationRequest(request, true),
asyncFetchStatus,
- asyncRedirect);
+ asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5847,7 +6088,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
}
@Test
- public void fetchTrigger_setsFakeEnrollmentId_whenDisableEnrollmentFlagIsTrue()
+ public void fetchTrigger_setsSiteEnrollmentId_whenDisableEnrollmentFlagIsTrue()
throws Exception {
String uri = WebUtil.validUrl("https://test1.example.test:8081");
RegistrationRequest request = buildRequest(uri);
@@ -5866,12 +6107,12 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "\""
+ "}"));
when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertTrue(fetch.isPresent());
@@ -5879,7 +6120,85 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
assertEquals(
WebUtil.validUrl("https://test1.example.test:8081"),
result.getRegistrationOrigin().toString());
- assertEquals(Enrollment.FAKE_ENROLLMENT, result.getEnrollmentId());
+ assertEquals("https://example.com", result.getEnrollmentId());
+ assertEquals(new JSONArray(EVENT_TRIGGERS_1).toString(), result.getEventTriggers());
+ assertEquals(DEBUG_KEY, result.getDebugKey());
+ verify(mUrlConnection).setRequestMethod("POST");
+ }
+
+ @Test
+ public void fetchTrigger_setsSiteEnrollmentId_whenDisableEnrollmentFlagIsTrueForLocalhost()
+ throws Exception {
+ String uri = WebUtil.validUrl("https://localhost:8081");
+ RegistrationRequest request = buildRequest(uri);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(uri));
+ when(mUrlConnection.getResponseCode()).thenReturn(200);
+ doReturn(true).when(mFlags).isDisableMeasurementEnrollmentCheck();
+ Map<String, List<String>> headersRequest = new HashMap<>();
+ headersRequest.put(
+ "Attribution-Reporting-Register-Trigger",
+ List.of(
+ "{"
+ + "\"event_trigger_data\": "
+ + EVENT_TRIGGERS_1
+ + ", \"debug_key\": \""
+ + DEBUG_KEY
+ + "\""
+ + "}"));
+ when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
+ // Execution
+ Optional<Trigger> fetch =
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Trigger result = fetch.get();
+ assertEquals(
+ WebUtil.validUrl("https://localhost:8081"),
+ result.getRegistrationOrigin().toString());
+ assertEquals("https://localhost", result.getEnrollmentId());
+ assertEquals(new JSONArray(EVENT_TRIGGERS_1).toString(), result.getEventTriggers());
+ assertEquals(DEBUG_KEY, result.getDebugKey());
+ verify(mUrlConnection).setRequestMethod("POST");
+ }
+
+ @Test
+ public void fetchTrigger_setsSiteEnrollmentId_whenDisableEnrollmentFlagIsTrueForIP()
+ throws Exception {
+ String uri = WebUtil.validUrl("https://127.0.0.1:8081");
+ RegistrationRequest request = buildRequest(uri);
+ doReturn(mUrlConnection).when(mFetcher).openUrl(new URL(uri));
+ when(mUrlConnection.getResponseCode()).thenReturn(200);
+ doReturn(true).when(mFlags).isDisableMeasurementEnrollmentCheck();
+ Map<String, List<String>> headersRequest = new HashMap<>();
+ headersRequest.put(
+ "Attribution-Reporting-Register-Trigger",
+ List.of(
+ "{"
+ + "\"event_trigger_data\": "
+ + EVENT_TRIGGERS_1
+ + ", \"debug_key\": \""
+ + DEBUG_KEY
+ + "\""
+ + "}"));
+ when(mUrlConnection.getHeaderFields()).thenReturn(headersRequest);
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
+ AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
+ AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
+ // Execution
+ Optional<Trigger> fetch =
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
+ // Assertion
+ assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
+ assertTrue(fetch.isPresent());
+ Trigger result = fetch.get();
+ assertEquals(
+ WebUtil.validUrl("https://127.0.0.1:8081"),
+ result.getRegistrationOrigin().toString());
+ assertEquals("https://127.0.0.1", result.getEnrollmentId());
assertEquals(new JSONArray(EVENT_TRIGGERS_1).toString(), result.getEventTriggers());
assertEquals(DEBUG_KEY, result.getDebugKey());
verify(mUrlConnection).setRequestMethod("POST");
@@ -5900,7 +6219,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "'aggregation_coordinator_origin': "
+ "'https://cloud.coordination.test'"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
when(mFlags.getMeasurementAggregationCoordinatorOriginEnabled()).thenReturn(true);
@@ -5908,7 +6227,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
.thenReturn("https://cloud.coordination.test");
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(AsyncFetchStatus.EntityStatus.SUCCESS, asyncFetchStatus.getEntityStatus());
@@ -5941,7 +6260,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "'aggregation_coordinator_origin': "
+ "'https://invalid.cloud.coordination.test'"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
when(mFlags.getMeasurementAggregationCoordinatorOriginEnabled()).thenReturn(true);
@@ -5949,7 +6268,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
.thenReturn("https://cloud.coordination.test");
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -5968,13 +6287,13 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
Map.of(
"Attribution-Reporting-Register-Trigger",
List.of("{" + "\"event_trigger_data\": " + "[{}]" + "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
when(mFlags.getMeasurementAggregationCoordinatorOriginEnabled()).thenReturn(true);
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(AsyncFetchStatus.EntityStatus.SUCCESS, asyncFetchStatus.getEntityStatus());
@@ -6005,7 +6324,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
+ "'aggregation_coordinator_origin': "
+ "'https://invalid.cloud.coordination.test'"
+ "}")));
- AsyncRedirect asyncRedirect = new AsyncRedirect();
+ AsyncRedirects asyncRedirects = new AsyncRedirects();
AsyncFetchStatus asyncFetchStatus = new AsyncFetchStatus();
AsyncRegistration asyncRegistration = appTriggerRegistrationRequest(request);
when(mFlags.getMeasurementAggregationCoordinatorOriginEnabled()).thenReturn(true);
@@ -6013,7 +6332,7 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
.thenReturn("https://cloud.coordination.test");
// Execution
Optional<Trigger> fetch =
- mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirect);
+ mFetcher.fetchTrigger(asyncRegistration, asyncFetchStatus, asyncRedirects);
// Assertion
assertEquals(AsyncFetchStatus.ResponseStatus.SUCCESS, asyncFetchStatus.getResponseStatus());
assertEquals(
@@ -6050,26 +6369,6 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
private static AsyncRegistration appTriggerRegistrationRequest(
RegistrationRequest registrationRequest) {
- // Necessary for testing
- String enrollmentId = "";
- if (EnrollmentDao.getInstance(CONTEXT)
- .getEnrollmentDataFromMeasurementUrl(
- registrationRequest
- .getRegistrationUri()
- .buildUpon()
- .clearQuery()
- .build())
- != null) {
- enrollmentId =
- EnrollmentDao.getInstance(CONTEXT)
- .getEnrollmentDataFromMeasurementUrl(
- registrationRequest
- .getRegistrationUri()
- .buildUpon()
- .clearQuery()
- .build())
- .getEnrollmentId();
- }
return createAsyncRegistration(
UUID.randomUUID().toString(),
registrationRequest.getRegistrationUri(),
@@ -6091,26 +6390,6 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
private static AsyncRegistration appTriggerRegistrationRequestWithAdId(
RegistrationRequest registrationRequest) {
- // Necessary for testing
- String enrollmentId = "";
- if (EnrollmentDao.getInstance(CONTEXT)
- .getEnrollmentDataFromMeasurementUrl(
- registrationRequest
- .getRegistrationUri()
- .buildUpon()
- .clearQuery()
- .build())
- != null) {
- enrollmentId =
- EnrollmentDao.getInstance(CONTEXT)
- .getEnrollmentDataFromMeasurementUrl(
- registrationRequest
- .getRegistrationUri()
- .buildUpon()
- .clearQuery()
- .build())
- .getEnrollmentId();
- }
return createAsyncRegistration(
UUID.randomUUID().toString(),
registrationRequest.getRegistrationUri(),
@@ -6136,28 +6415,6 @@ public final class AsyncTriggerFetcherTest extends AdServicesExtendedMockitoTest
if (webTriggerRegistrationRequest.getTriggerParams().size() > 0) {
WebTriggerParams webTriggerParams =
webTriggerRegistrationRequest.getTriggerParams().get(0);
- // Necessary for testing
- String enrollmentId = "";
- if (EnrollmentDao.getInstance(CONTEXT)
- .getEnrollmentDataFromMeasurementUrl(
- webTriggerRegistrationRequest
- .getTriggerParams()
- .get(0)
- .getRegistrationUri()
- .buildUpon()
- .clearQuery()
- .build())
- != null) {
- enrollmentId =
- EnrollmentDao.getInstance(CONTEXT)
- .getEnrollmentDataFromMeasurementUrl(
- webTriggerParams
- .getRegistrationUri()
- .buildUpon()
- .clearQuery()
- .build())
- .getEnrollmentId();
- }
return createAsyncRegistration(
UUID.randomUUID().toString(),
webTriggerParams.getRegistrationUri(),
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistrationTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistrationTest.java
index 847dc6ab3..7b6e78903 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistrationTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/registration/EnqueueAsyncRegistrationTest.java
@@ -243,6 +243,8 @@ public class EnqueueAsyncRegistrationTest {
Assert.assertNotNull(asyncRegistration.getType());
Assert.assertEquals(
AsyncRegistration.RegistrationType.APP_SOURCE, asyncRegistration.getType());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration.getRedirectBehavior());
}
}
@@ -300,6 +302,8 @@ public class EnqueueAsyncRegistrationTest {
Assert.assertNotNull(asyncRegistration.getType());
Assert.assertEquals(
AsyncRegistration.RegistrationType.APP_SOURCE, asyncRegistration.getType());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration.getRedirectBehavior());
}
}
@@ -390,6 +394,8 @@ public class EnqueueAsyncRegistrationTest {
Assert.assertEquals(
Uri.parse("android-app://test.destination"), asyncRegistration.getRegistrant());
Assert.assertNull(asyncRegistration.getSourceType());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration.getRedirectBehavior());
}
}
@@ -523,6 +529,8 @@ public class EnqueueAsyncRegistrationTest {
VALID_WEB_SOURCE_REGISTRATION_NULL_INPUT_EVENT.getTopOriginUri(),
asyncRegistration1.getTopOrigin());
assertEqualsWebSourceRegistrationCommon(asyncRegistration1);
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration1.getRedirectBehavior());
Assert.assertTrue(cursor.moveToNext());
AsyncRegistration asyncRegistration2 =
@@ -533,6 +541,8 @@ public class EnqueueAsyncRegistrationTest {
VALID_WEB_SOURCE_REGISTRATION_NULL_INPUT_EVENT.getTopOriginUri(),
asyncRegistration2.getTopOrigin());
assertEqualsWebSourceRegistrationCommon(asyncRegistration2);
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration2.getRedirectBehavior());
Assert.assertEquals(
asyncRegistration1.getRegistrationId(),
@@ -591,6 +601,8 @@ public class EnqueueAsyncRegistrationTest {
validWebSourceRegistration.getTopOriginUri(),
asyncRegistration1.getTopOrigin());
assertEqualsWebSourceRegistrationCommon(asyncRegistration1);
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration1.getRedirectBehavior());
Assert.assertTrue(cursor.moveToNext());
AsyncRegistration asyncRegistration2 =
@@ -601,6 +613,8 @@ public class EnqueueAsyncRegistrationTest {
validWebSourceRegistration.getTopOriginUri(),
asyncRegistration2.getTopOrigin());
assertEqualsWebSourceRegistrationCommon(asyncRegistration2);
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration2.getRedirectBehavior());
Assert.assertEquals(
asyncRegistration1.getRegistrationId(),
@@ -642,12 +656,16 @@ public class EnqueueAsyncRegistrationTest {
SqliteObjectMapper.constructAsyncRegistration(cursor);
Assert.assertEquals(REGISTRATION_URI_1, asyncRegistration1.getRegistrationUri());
assertEqualsWebTriggerRegistrationCommon(asyncRegistration1);
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration1.getRedirectBehavior());
Assert.assertTrue(cursor.moveToNext());
AsyncRegistration asyncRegistration2 =
SqliteObjectMapper.constructAsyncRegistration(cursor);
Assert.assertEquals(REGISTRATION_URI_2, asyncRegistration2.getRegistrationUri());
assertEqualsWebTriggerRegistrationCommon(asyncRegistration2);
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration2.getRedirectBehavior());
Assert.assertEquals(
asyncRegistration1.getRegistrationId(),
@@ -656,7 +674,7 @@ public class EnqueueAsyncRegistrationTest {
}
@Test
- public void testRunInTransactionFail_inValid() {
+ public void testRunInTransactionFail_invalid() {
when(mDatastoreManagerMock.runInTransaction(any())).thenReturn(false);
Assert.assertFalse(
EnqueueAsyncRegistration.webTriggerRegistrationRequest(
@@ -722,6 +740,8 @@ public class EnqueueAsyncRegistrationTest {
Assert.assertNotNull(asyncRegistration.getType());
Assert.assertEquals(
AsyncRegistration.RegistrationType.APP_SOURCE, asyncRegistration.getType());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration.getRedirectBehavior());
}
}
@@ -773,6 +793,8 @@ public class EnqueueAsyncRegistrationTest {
assertEqualsAppSourcesRegistrationCommon(asyncRegistration1);
Assert.assertEquals(REGISTRATION_URI_1, asyncRegistration1.getRegistrationUri());
Assert.assertEquals(Source.SourceType.EVENT, asyncRegistration1.getSourceType());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration1.getRedirectBehavior());
Assert.assertTrue(cursor.moveToNext());
AsyncRegistration asyncRegistration2 =
@@ -780,6 +802,8 @@ public class EnqueueAsyncRegistrationTest {
assertEqualsAppSourcesRegistrationCommon(asyncRegistration2);
Assert.assertEquals(REGISTRATION_URI_2, asyncRegistration2.getRegistrationUri());
Assert.assertEquals(Source.SourceType.EVENT, asyncRegistration2.getSourceType());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration2.getRedirectBehavior());
Assert.assertEquals(
asyncRegistration1.getRegistrationId(), asyncRegistration2.getRegistrationId());
@@ -835,6 +859,8 @@ public class EnqueueAsyncRegistrationTest {
assertEqualsAppSourcesRegistrationCommon(asyncRegistration1);
Assert.assertEquals(REGISTRATION_URI_1, asyncRegistration1.getRegistrationUri());
Assert.assertEquals(Source.SourceType.NAVIGATION, asyncRegistration1.getSourceType());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration1.getRedirectBehavior());
Assert.assertTrue(cursor.moveToNext());
AsyncRegistration asyncRegistration2 =
@@ -842,6 +868,8 @@ public class EnqueueAsyncRegistrationTest {
assertEqualsAppSourcesRegistrationCommon(asyncRegistration2);
Assert.assertEquals(REGISTRATION_URI_2, asyncRegistration2.getRegistrationUri());
Assert.assertEquals(Source.SourceType.NAVIGATION, asyncRegistration2.getSourceType());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration2.getRedirectBehavior());
Assert.assertEquals(
asyncRegistration1.getRegistrationId(), asyncRegistration2.getRegistrationId());
@@ -898,6 +926,8 @@ public class EnqueueAsyncRegistrationTest {
Assert.assertEquals(REGISTRATION_URI_1, asyncRegistration1.getRegistrationUri());
Assert.assertEquals(Source.SourceType.NAVIGATION, asyncRegistration1.getSourceType());
Assert.assertNull(asyncRegistration1.getPostBody());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration1.getRedirectBehavior());
Assert.assertTrue(cursor.moveToNext());
AsyncRegistration asyncRegistration2 =
@@ -906,6 +936,8 @@ public class EnqueueAsyncRegistrationTest {
Assert.assertEquals(REGISTRATION_URI_2, asyncRegistration2.getRegistrationUri());
Assert.assertEquals(Source.SourceType.NAVIGATION, asyncRegistration2.getSourceType());
Assert.assertNull(asyncRegistration2.getPostBody());
+ Assert.assertEquals(
+ AsyncRedirect.RedirectBehavior.AS_IS, asyncRegistration2.getRedirectBehavior());
Assert.assertEquals(
asyncRegistration1.getRegistrationId(), asyncRegistration2.getRegistrationId());
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java
index e5700638e..fd7668d93 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java
@@ -54,6 +54,7 @@ import com.android.adservices.service.measurement.aggregation.AggregateCryptoFix
import com.android.adservices.service.measurement.aggregation.AggregateEncryptionKey;
import com.android.adservices.service.measurement.aggregation.AggregateEncryptionKeyManager;
import com.android.adservices.service.measurement.aggregation.AggregateReport;
+import com.android.adservices.service.measurement.aggregation.AggregateReportFixture;
import com.android.adservices.service.measurement.util.UnsignedLong;
import com.android.adservices.service.stats.AdServicesLogger;
import com.android.adservices.service.stats.MeasurementReportsStats;
@@ -989,6 +990,164 @@ public class AggregateReportingJobHandlerTest {
verify(mTransaction, times(1)).end();
}
+ @Test
+ public void performReport_normalReportWithDebugKeys_hasDebugModeEnabled()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.SOURCE_DEBUG_KEY)
+ .setTriggerDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.TRIGGER_DEBUG_KEY)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyAggregateReportingJobHandler, "enabled");
+ verify(mMeasurementDao, times(1))
+ .markAggregateReportStatus(
+ eq(aggregateReport.getId()), eq(AggregateReport.Status.DELIVERED));
+ }
+
+ @Test
+ public void performReport_normalReportWithOnlySourceDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ // Setup
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.SOURCE_DEBUG_KEY)
+ .setTriggerDebugKey(null)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateReportStatus(
+ eq(aggregateReport.getId()), eq(AggregateReport.Status.DELIVERED));
+ }
+
+ @Test
+ public void performReport_normalReportWithOnlyTriggerDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(null)
+ .setTriggerDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.TRIGGER_DEBUG_KEY)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateReportStatus(
+ eq(aggregateReport.getId()), eq(AggregateReport.Status.DELIVERED));
+ }
+
+ @Test
+ public void performReport_normalReportWithNoDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(null)
+ .setTriggerDebugKey(null)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateReportStatus(
+ eq(aggregateReport.getId()), eq(AggregateReport.Status.DELIVERED));
+ }
+
+ @Test
+ public void performReport_debugReportWithDebugKeys_hasDebugModeEnabled()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.SOURCE_DEBUG_KEY)
+ .setTriggerDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.TRIGGER_DEBUG_KEY)
+ .build();
+ executeDebugModeVerification(
+ aggregateReport, mSpyDebugAggregateReportingJobHandler, "enabled");
+ verify(mMeasurementDao, times(1))
+ .markAggregateDebugReportDelivered(eq(aggregateReport.getId()));
+ }
+
+ @Test
+ public void performReport_debugReportWithOnlySourceDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.SOURCE_DEBUG_KEY)
+ .setTriggerDebugKey(null)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyDebugAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateDebugReportDelivered(eq(aggregateReport.getId()));
+ }
+
+ @Test
+ public void performReport_debugReportWithOnlyTriggerDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(null)
+ .setTriggerDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.TRIGGER_DEBUG_KEY)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyDebugAggregateReportingJobHandler, "");
+ }
+
+ @Test
+ public void performReport_debugReportWithNoDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(null)
+ .setTriggerDebugKey(null)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyDebugAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateDebugReportDelivered(eq(aggregateReport.getId()));
+ }
+
+ private void executeDebugModeVerification(
+ AggregateReport aggregateReport,
+ AggregateReportingJobHandler aggregateReportingJobHandler,
+ String expectedDebugMode)
+ throws DatastoreException, IOException, JSONException {
+ when(mMeasurementDao.getAggregateReport(aggregateReport.getId()))
+ .thenReturn(aggregateReport);
+ doReturn(HttpURLConnection.HTTP_OK)
+ .when(aggregateReportingJobHandler)
+ .makeHttpPostRequest(eq(REPORTING_URI), Mockito.any());
+
+ doNothing()
+ .when(mMeasurementDao)
+ .markAggregateReportStatus(
+ aggregateReport.getId(), AggregateReport.Status.DELIVERED);
+ ArgumentCaptor<JSONObject> aggregateReportBodyCaptor =
+ ArgumentCaptor.forClass(JSONObject.class);
+
+ // Execution
+ Assert.assertEquals(
+ AdServicesStatusUtils.STATUS_SUCCESS,
+ aggregateReportingJobHandler.performReport(
+ aggregateReport.getId(),
+ AggregateCryptoFixture.getKey(),
+ new ReportingStatus()));
+
+ // Assertion
+ verify(aggregateReportingJobHandler)
+ .makeHttpPostRequest(eq(REPORTING_URI), aggregateReportBodyCaptor.capture());
+ verify(mTransaction, times(2)).begin();
+ verify(mTransaction, times(2)).end();
+
+ JSONObject aggregateReportBody = aggregateReportBodyCaptor.getValue();
+ JSONObject sharedInfo =
+ new JSONObject(
+ aggregateReportBody.getString(
+ AggregateReportBody.PayloadBodyKeys.SHARED_INFO));
+ assertEquals(
+ expectedDebugMode,
+ sharedInfo.optString(AggregateReportBody.SharedInfoKeys.DEBUG_MODE));
+ }
+
private static JSONObject createASampleAggregateReportBody(AggregateReport aggregateReport)
throws JSONException {
return new AggregateReportBody.Builder()
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/DebugReportApiTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/DebugReportApiTest.java
index 8e1a178ab..5656ba007 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/DebugReportApiTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/DebugReportApiTest.java
@@ -92,6 +92,12 @@ public final class DebugReportApiTest {
when(mFlags.getMeasurementEnableDebugReport()).thenReturn(true);
when(mFlags.getMeasurementEnableSourceDebugReport()).thenReturn(true);
when(mFlags.getMeasurementEnableTriggerDebugReport()).thenReturn(true);
+ when(mFlags.getMeasurementVtcConfigurableMaxEventReportsCount())
+ .thenReturn(Flags.DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT);
+ when(mFlags.getMeasurementEventReportsVtcEarlyReportingWindows())
+ .thenReturn(Flags.MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS);
+ when(mFlags.getMeasurementEventReportsCtcEarlyReportingWindows())
+ .thenReturn(Flags.MEASUREMENT_EVENT_REPORTS_CTC_EARLY_REPORTING_WINDOWS);
}
@Test
@@ -3650,6 +3656,194 @@ public final class DebugReportApiTest {
verify(mMeasurementDao, never()).insertDebugReport(any());
}
+ @Test
+ public void testScheduleTriggerEventWindowNotStartedDebugReport_triggerNotOpIn_dontSchedule()
+ throws Exception {
+ Source source =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setEventId(SOURCE_EVENT_ID)
+ .setIsDebugReporting(true)
+ .setAdIdPermission(true)
+ .build();
+ Trigger trigger =
+ TriggerFixture.getValidTriggerBuilder()
+ .setIsDebugReporting(false)
+ .setAdIdPermission(true)
+ .build();
+ ExtendedMockito.doNothing()
+ .when(() -> VerboseDebugReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+
+ mDebugReportApi.scheduleTriggerDebugReport(
+ source,
+ trigger,
+ /* limit =*/ null,
+ mMeasurementDao,
+ DebugReportApi.Type.TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED);
+ verify(mMeasurementDao, never()).insertDebugReport(any());
+ }
+
+ @Test
+ public void testScheduleTriggerEventWindowNotStartedDebugReport_sourceNoAdId_dontSchedule()
+ throws Exception {
+ Source source =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setEventId(SOURCE_EVENT_ID)
+ .setIsDebugReporting(true)
+ .setAdIdPermission(false)
+ .build();
+ Trigger trigger =
+ TriggerFixture.getValidTriggerBuilder()
+ .setIsDebugReporting(true)
+ .setAdIdPermission(true)
+ .build();
+ ExtendedMockito.doNothing()
+ .when(() -> VerboseDebugReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+
+ mDebugReportApi.scheduleTriggerDebugReport(
+ source,
+ trigger,
+ /* limit =*/ null,
+ mMeasurementDao,
+ DebugReportApi.Type.TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED);
+ verify(mMeasurementDao, never()).insertDebugReport(any());
+ }
+
+ @Test
+ public void testScheduleTriggerEventWindowNotStartedDebugReport_sourceNoArDebug_dontSchedule()
+ throws Exception {
+ Source source =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setEventId(SOURCE_EVENT_ID)
+ .setIsDebugReporting(true)
+ .setPublisherType(EventSurfaceType.WEB)
+ .setPublisher(SourceFixture.ValidSourceParams.WEB_PUBLISHER)
+ .setAppDestinations(null)
+ .setWebDestinations(SourceFixture.ValidSourceParams.WEB_DESTINATIONS)
+ .setArDebugPermission(false)
+ .build();
+ Trigger trigger =
+ TriggerFixture.getValidTriggerBuilder()
+ .setIsDebugReporting(true)
+ .setDestinationType(EventSurfaceType.WEB)
+ .setAttributionDestination(
+ SourceFixture.ValidSourceParams.WEB_DESTINATIONS.get(0))
+ .setArDebugPermission(true)
+ .build();
+ ExtendedMockito.doNothing()
+ .when(() -> VerboseDebugReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+
+ mDebugReportApi.scheduleTriggerDebugReport(
+ source,
+ trigger,
+ /* limit =*/ null,
+ mMeasurementDao,
+ DebugReportApi.Type.TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED);
+ verify(mMeasurementDao, never()).insertDebugReport(any());
+ }
+
+ @Test
+ public void testScheduleTriggerEventWindowNotStartedDebugReport_success() throws Exception {
+ Source source =
+ SourceFixture.getValidSourceBuilder()
+ .setEventId(SOURCE_EVENT_ID)
+ .setIsDebugReporting(true)
+ .setAdIdPermission(true)
+ .build();
+ Trigger trigger =
+ TriggerFixture.getValidTriggerBuilder()
+ .setIsDebugReporting(true)
+ .setAdIdPermission(true)
+ .build();
+ ExtendedMockito.doNothing()
+ .when(() -> VerboseDebugReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+
+ mDebugReportApi.scheduleTriggerDebugReport(
+ source,
+ trigger,
+ /* limit =*/ null,
+ mMeasurementDao,
+ DebugReportApi.Type.TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED);
+ verify(mMeasurementDao, times(1)).insertDebugReport(any());
+ }
+
+ @Test
+ public void testScheduleTriggerEventWindowNotStartedDebugReport_debugFlagDisabled_dontSchedule()
+ throws Exception {
+ when(mFlags.getMeasurementEnableDebugReport()).thenReturn(false);
+ Source source =
+ SourceFixture.getValidSourceBuilder()
+ .setEventId(SOURCE_EVENT_ID)
+ .setIsDebugReporting(true)
+ .setAdIdPermission(true)
+ .build();
+ Trigger trigger =
+ TriggerFixture.getValidTriggerBuilder()
+ .setIsDebugReporting(true)
+ .setAdIdPermission(true)
+ .build();
+ ExtendedMockito.doNothing()
+ .when(() -> VerboseDebugReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+
+ mDebugReportApi.scheduleTriggerDebugReport(
+ source,
+ trigger,
+ /* limit =*/ null,
+ mMeasurementDao,
+ DebugReportApi.Type.TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED);
+ verify(mMeasurementDao, never()).insertDebugReport(any());
+ }
+
+ @Test
+ public void
+ testScheduleTriggerEventWindowNotStartedDebugReport_triggerFlagDisabled_dontSchedule()
+ throws Exception {
+ when(mFlags.getMeasurementEnableTriggerDebugReport()).thenReturn(false);
+ Source source =
+ SourceFixture.getValidSourceBuilder()
+ .setEventId(SOURCE_EVENT_ID)
+ .setIsDebugReporting(true)
+ .setAdIdPermission(true)
+ .build();
+ Trigger trigger =
+ TriggerFixture.getValidTriggerBuilder()
+ .setIsDebugReporting(true)
+ .setAdIdPermission(true)
+ .build();
+ ExtendedMockito.doNothing()
+ .when(() -> VerboseDebugReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+
+ mDebugReportApi.scheduleTriggerDebugReport(
+ source,
+ trigger,
+ /* limit =*/ null,
+ mMeasurementDao,
+ DebugReportApi.Type.TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED);
+ verify(mMeasurementDao, never()).insertDebugReport(any());
+ }
+
+ @Test
+ public void
+ testScheduleTriggerEventWindowNotStartedDebugReport_noTriggerPermission_dontSchedule()
+ throws Exception {
+ Source source =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setEventId(SOURCE_EVENT_ID)
+ .setIsDebugReporting(true)
+ .setAdIdPermission(true)
+ .build();
+ Trigger trigger = TriggerFixture.getValidTriggerBuilder().setIsDebugReporting(true).build();
+ ExtendedMockito.doNothing()
+ .when(() -> VerboseDebugReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+
+ mDebugReportApi.scheduleTriggerDebugReport(
+ source,
+ trigger,
+ /* limit =*/ null,
+ mMeasurementDao,
+ DebugReportApi.Type.TRIGGER_EVENT_REPORT_WINDOW_NOT_STARTED);
+ verify(mMeasurementDao, never()).insertDebugReport(any());
+ }
+
private static void assertSourceDebugReportParameters(
DebugReport actualReport,
String expectedReportType,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegateTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegateTest.java
index 713ce8e98..756c5434c 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegateTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/EventReportWindowCalcDelegateTest.java
@@ -61,6 +61,9 @@ public class EventReportWindowCalcDelegateTest {
private static final String EVENT_REPORT_WINDOWS_2_WINDOWS_NO_START =
"{'end_times': [172800000, 432000000]}";
+ private static final String EVENT_REPORT_WINDOWS_2_WINDOWS_WITH_START =
+ "{ 'start_time': 3600000, 'end_times': [86400000, 1728000000]}";
+
private static final String EVENT_REPORT_WINDOWS_5_WINDOWS_WITH_START =
"{'start_time': 86400000, 'end_times': [172800000, 432000000, 604800000, 864000000,"
+ " 1728000000]}";
@@ -71,9 +74,14 @@ public class EventReportWindowCalcDelegateTest {
@Before
public void setup() {
- doReturn(false).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS)
.when(mFlags).getMeasurementMinEventReportDelayMillis();
+ doReturn(Flags.DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT)
+ .when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
+ doReturn(Flags.MEASUREMENT_EVENT_REPORTS_VTC_EARLY_REPORTING_WINDOWS)
+ .when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
+ doReturn(Flags.MEASUREMENT_EVENT_REPORTS_CTC_EARLY_REPORTING_WINDOWS)
+ .when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
mEventReportWindowCalcDelegate = new EventReportWindowCalcDelegate(mFlags);
}
@@ -85,6 +93,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -104,6 +113,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -121,6 +131,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -141,6 +152,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -159,6 +171,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -177,6 +190,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -195,6 +209,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -212,6 +227,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -231,6 +247,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -250,6 +267,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -267,6 +285,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -278,6 +297,9 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void testMaxReportCount() {
+ doReturn(Flags.DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT)
+ .when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
+
Source eventSourceInstallNotAttributed =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
@@ -285,12 +307,7 @@ public class EventReportWindowCalcDelegateTest {
.build();
assertEquals(
PrivacyParams.EVENT_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(
- eventSourceInstallNotAttributed, false));
- assertEquals(
- PrivacyParams.EVENT_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(
- eventSourceInstallNotAttributed, false));
+ mEventReportWindowCalcDelegate.getMaxReportCount(eventSourceInstallNotAttributed));
Source navigationSourceInstallNotAttributed =
SourceFixture.getMinimalValidSourceBuilder()
@@ -300,46 +317,33 @@ public class EventReportWindowCalcDelegateTest {
assertEquals(
PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS,
mEventReportWindowCalcDelegate.getMaxReportCount(
- navigationSourceInstallNotAttributed, false));
- assertEquals(
- PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(
- navigationSourceInstallNotAttributed, false));
+ navigationSourceInstallNotAttributed));
Source eventSourceInstallAttributed =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
.setInstallAttributed(true)
+ .setInstallCooldownWindow(1L)
.build();
assertEquals(
PrivacyParams.INSTALL_ATTR_EVENT_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(
- eventSourceInstallAttributed, true));
- // Install attribution state does not matter for web destination
- assertEquals(
- PrivacyParams.EVENT_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(
- eventSourceInstallAttributed, false));
+ mEventReportWindowCalcDelegate.getMaxReportCount(eventSourceInstallAttributed));
Source navigationSourceInstallAttributed =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
.setInstallAttributed(true)
+ .setInstallCooldownWindow(1L)
.build();
assertEquals(
PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS,
mEventReportWindowCalcDelegate.getMaxReportCount(
- navigationSourceInstallAttributed, true));
- assertEquals(
- PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(
- navigationSourceInstallAttributed, true));
+ navigationSourceInstallAttributed));
}
@Test
public void getMaxReportCount_configuredConversionsNonInstall_returnsConfiguredCount() {
// Setup
- doReturn(true).when(mFlags).getMeasurementEnableVtcConfigurableMaxEventReports();
doReturn(3).when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
Source nonInstallEventSource =
SourceFixture.getMinimalValidSourceBuilder()
@@ -349,13 +353,12 @@ public class EventReportWindowCalcDelegateTest {
// Execution & assertion
Assert.assertEquals(
- 3, mEventReportWindowCalcDelegate.getMaxReportCount(nonInstallEventSource, false));
+ 3, mEventReportWindowCalcDelegate.getMaxReportCount(nonInstallEventSource));
}
@Test
public void getMaxReportCount_configuredConversionsInstallCase_returnsConfiguredCount() {
// Setup
- doReturn(true).when(mFlags).getMeasurementEnableVtcConfigurableMaxEventReports();
doReturn(2).when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
Source installEventSource =
SourceFixture.getMinimalValidSourceBuilder()
@@ -365,29 +368,28 @@ public class EventReportWindowCalcDelegateTest {
// Execution & assertion
Assert.assertEquals(
- 2, mEventReportWindowCalcDelegate.getMaxReportCount(installEventSource, true));
+ 2, mEventReportWindowCalcDelegate.getMaxReportCount(installEventSource));
}
@Test
public void getMaxReportCount_configuredConversionsToOneInstallCase_incrementConfiguredCount() {
// Setup
- doReturn(true).when(mFlags).getMeasurementEnableVtcConfigurableMaxEventReports();
doReturn(1).when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
Source installEventSource =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
.setInstallAttributed(true)
+ .setInstallCooldownWindow(1L)
.build();
// Execution & assertion
Assert.assertEquals(
- 2, mEventReportWindowCalcDelegate.getMaxReportCount(installEventSource, true));
+ 2, mEventReportWindowCalcDelegate.getMaxReportCount(installEventSource));
}
@Test
public void getMaxReportCount_configuredConversionsToOneInstallCase_noEffectOnCtc() {
// Setup
- doReturn(true).when(mFlags).getMeasurementEnableVtcConfigurableMaxEventReports();
doReturn(2).when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
Source navigationSource =
SourceFixture.getMinimalValidSourceBuilder()
@@ -397,7 +399,7 @@ public class EventReportWindowCalcDelegateTest {
// Execution & assertion
Assert.assertEquals(
- 3, mEventReportWindowCalcDelegate.getMaxReportCount(navigationSource, false));
+ 3, mEventReportWindowCalcDelegate.getMaxReportCount(navigationSource));
}
@Test
@@ -409,48 +411,51 @@ public class EventReportWindowCalcDelegateTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(10))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 1));
// Expected: 1 window at expiry
Source eventSource7d =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(7))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(7) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource7d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ eventSource7d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(7) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource7d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ eventSource7d, /* windowIndex= */ 1));
// Expected: 1 window at expiry
Source eventSource2d =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(2))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource2d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ eventSource2d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource2d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ eventSource2d, /* windowIndex= */ 1));
}
@Test
@@ -465,21 +470,21 @@ public class EventReportWindowCalcDelegateTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(10))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + minDelayMillis,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + minDelayMillis,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 1));
}
@Test
public void getReportingTimeForNoising_eventSrcWithConfiguredReportingWindows() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -493,27 +498,27 @@ public class EventReportWindowCalcDelegateTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(10))
.build();
assertEquals(
eventTime + TimeUnit.HOURS.toMillis(1) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(1) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 1));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 2, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 2));
}
@Test
public void getReportingTimeForNoising_eventSrcInstallAttWithConfiguredReportingWindows() {
// Addition another window for install attribution is ignored when configurable windows
// are applied.
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -528,28 +533,28 @@ public class EventReportWindowCalcDelegateTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
.setEventTime(eventTime)
+ .setExpiryTime(expiry)
.setEventReportWindow(expiry)
.setInstallCooldownWindow(expiry)
.build();
assertEquals(
eventTime + TimeUnit.HOURS.toMillis(1) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 0, /* isInstallCase */ true));
+ eventSource10d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(1) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 1, /* isInstallCase */ true));
+ eventSource10d, /* windowIndex= */ 1));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 2, /* isInstallCase */ true));
+ eventSource10d, /* windowIndex= */ 2));
}
@Test
public void getReportingTimeForNoising_navigationSrcWithConfiguredReportingWindows() {
// Addition another window for install attribution is ignored when configurable windows
// are applied.
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -563,27 +568,27 @@ public class EventReportWindowCalcDelegateTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(10))
.build();
assertEquals(
eventTime + TimeUnit.HOURS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 1));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 2, /* isInstallCase */ false));
+ eventSource10d, /* windowIndex= */ 2));
}
@Test
public void getReportingTimeForNoising_navigationSrcInstallAttWithConfiguredReportingWindows() {
// Addition another window for install attribution is ignored when configurable windows
// are applied.
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -598,21 +603,22 @@ public class EventReportWindowCalcDelegateTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
.setEventTime(eventTime)
+ .setExpiryTime(expiry)
.setEventReportWindow(expiry)
.setInstallCooldownWindow(expiry)
.build();
assertEquals(
eventTime + TimeUnit.HOURS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 0, /* isInstallCase */ true));
+ eventSource10d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 1, /* isInstallCase */ true));
+ eventSource10d, /* windowIndex= */ 1));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 2, /* isInstallCase */ true));
+ eventSource10d, /* windowIndex= */ 2));
}
@Test
@@ -625,36 +631,38 @@ public class EventReportWindowCalcDelegateTest {
.setSourceType(Source.SourceType.EVENT)
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(1))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(10))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 0, /* isInstallCase */ true));
+ eventSource10d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 1, /* isInstallCase */ true));
+ eventSource10d, /* windowIndex= */ 1));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(10) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource10d, /* windowIndex= */ 2, /* isInstallCase */ true));
+ eventSource10d, /* windowIndex= */ 2));
// Expected: 1 window at 2d(expiry)
Source eventSource2d =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(2))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource2d, /* windowIndex= */ 0, /* isInstallCase */ true));
+ eventSource2d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- eventSource2d, /* windowIndex= */ 1, /* isInstallCase */ true));
+ eventSource2d, /* windowIndex= */ 1));
}
@Test
@@ -666,56 +674,59 @@ public class EventReportWindowCalcDelegateTest {
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(20))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource20d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ navigationSource20d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(7) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource20d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ navigationSource20d, /* windowIndex= */ 1));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(20) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource20d, /* windowIndex= */ 2, /* isInstallCase */ false));
+ navigationSource20d, /* windowIndex= */ 2));
// Expected: 2 windows at 2d & expiry(7d)
Source navigationSource7d =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(7))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource7d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ navigationSource7d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(7) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource7d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ navigationSource7d, /* windowIndex= */ 1));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(7) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource7d, /* windowIndex= */ 2, /* isInstallCase */ false));
+ navigationSource7d, /* windowIndex= */ 2));
// Expected: 1 window at 2d(expiry)
Source navigationSource2d =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(2))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource2d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ navigationSource2d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource2d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ navigationSource2d, /* windowIndex= */ 1));
}
@Test
@@ -728,20 +739,21 @@ public class EventReportWindowCalcDelegateTest {
.setSourceType(Source.SourceType.NAVIGATION)
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(1))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(20))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource20d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ navigationSource20d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(7) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource20d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ navigationSource20d, /* windowIndex= */ 1));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(20) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource20d, /* windowIndex= */ 2, /* isInstallCase */ false));
+ navigationSource20d, /* windowIndex= */ 2));
// Expected: 2 windows at 2d & expiry(7d)
Source navigationSource7d =
@@ -749,20 +761,21 @@ public class EventReportWindowCalcDelegateTest {
.setSourceType(Source.SourceType.NAVIGATION)
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(1))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(7))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource7d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ navigationSource7d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(7) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource7d, /* windowIndex= */ 1, /* isInstallCase */ false));
+ navigationSource7d, /* windowIndex= */ 1));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(7) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource7d, /* windowIndex= */ 2, /* isInstallCase */ false));
+ navigationSource7d, /* windowIndex= */ 2));
// Expected: 1 window at 2d(expiry)
Source navigationSource2d =
@@ -770,169 +783,21 @@ public class EventReportWindowCalcDelegateTest {
.setSourceType(Source.SourceType.NAVIGATION)
.setInstallCooldownWindow(TimeUnit.DAYS.toMillis(1))
.setEventTime(eventTime)
+ .setExpiryTime(eventTime + TimeUnit.DAYS.toMillis(30))
.setEventReportWindow(eventTime + TimeUnit.DAYS.toMillis(2))
.build();
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource2d, /* windowIndex= */ 0, /* isInstallCase */ false));
+ navigationSource2d, /* windowIndex= */ 0));
assertEquals(
eventTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- navigationSource2d, /* windowIndex= */ 1, /* isInstallCase */ false));
- }
-
- @Test
- public void getReportingTime_nullWindowConfigEventSrcAppDest_fallbackToDefault() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long expiryTime = triggerTime + TimeUnit.DAYS.toMillis(30);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(1);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.EVENT)
- .setEventReportWindow(expiryTime)
- .setEventTime(sourceEventTime)
- .build();
- assertEquals(
- expiryTime + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.APP));
- }
-
- @Test
- public void getReportingTime_nullWindowConfigEventSrcInstallAttAppDestTrigger1stWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long expiryTime = triggerTime + TimeUnit.DAYS.toMillis(30);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(1);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.EVENT)
- .setEventReportWindow(expiryTime)
- .setEventTime(sourceEventTime)
- .setInstallAttributed(true)
- .build();
- assertEquals(
- sourceEventTime
- + PrivacyParams.INSTALL_ATTR_EVENT_EARLY_REPORTING_WINDOW_MILLISECONDS[0]
- + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.APP));
- }
-
- @Test
- public void getReportingTime_nullWindowConfigEventSrcInstallAttAppDestTrigger2ndWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long expiryTime = triggerTime + TimeUnit.DAYS.toMillis(30);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(3);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.EVENT)
- .setEventReportWindow(expiryTime)
- .setEventTime(sourceEventTime)
- .setInstallAttributed(true)
- .build();
- assertEquals(
- expiryTime + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.APP));
- }
-
- @Test
- public void getReportingTime_nullWindowConfigEventSrcInstallAttWebDestTrigger1stWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long expiryTime = triggerTime + TimeUnit.DAYS.toMillis(30);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(1);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.EVENT)
- .setEventReportWindow(expiryTime)
- .setEventTime(sourceEventTime)
- .setInstallAttributed(true)
- .build();
- assertEquals(
- expiryTime + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.WEB));
- }
-
- @Test
- public void getReportingTime_nullWindowConfigEventSrcInstallAttWebDestTrigger2ndWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long expiryTime = triggerTime + TimeUnit.DAYS.toMillis(30);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(3);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.EVENT)
- .setEventReportWindow(expiryTime)
- .setEventTime(sourceEventTime)
- .setInstallAttributed(true)
- .build();
- assertEquals(
- expiryTime + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.WEB));
- }
-
- @Test
- public void getReportingTime_nullWindowConfigEventSourceWebDestination_fallbackToDefault() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long expiryTime = triggerTime + TimeUnit.DAYS.toMillis(30);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(1);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.EVENT)
- .setEventReportWindow(expiryTime)
- .setEventTime(sourceEventTime)
- .build();
- assertEquals(
- expiryTime + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.WEB));
- }
-
- @Test
- public void getReportingTime_nullWindowConfigNavigationSourceTriggerInFirstWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long sourceExpiryTime = triggerTime + TimeUnit.DAYS.toMillis(25);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(1);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.NAVIGATION)
- .setEventReportWindow(sourceExpiryTime)
- .setEventTime(sourceEventTime)
- .build();
- assertEquals(
- sourceEventTime
- + PrivacyParams.NAVIGATION_EARLY_REPORTING_WINDOW_MILLISECONDS[0]
- + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.APP));
+ navigationSource2d, /* windowIndex= */ 1));
}
@Test
public void getReportingTime_emptyWindowConfigNavigationSourceTriggerNextHour() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn("").when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
doReturn("").when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
long triggerTime = System.currentTimeMillis();
@@ -941,6 +806,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -952,7 +818,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_emptyWindowConfigEventSrcTriggerNextHour() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn("").when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
doReturn("").when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
long triggerTime = System.currentTimeMillis();
@@ -963,6 +828,7 @@ public class EventReportWindowCalcDelegateTest {
.setAppDestinations(
SourceFixture.ValidSourceParams.ATTRIBUTION_DESTINATIONS)
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -974,7 +840,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_emptyWindowConfigEventSrcInstallAttTriggerNextHour() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn("").when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
doReturn("").when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
long triggerTime = System.currentTimeMillis();
@@ -985,6 +850,7 @@ public class EventReportWindowCalcDelegateTest {
.setAppDestinations(
SourceFixture.ValidSourceParams.ATTRIBUTION_DESTINATIONS)
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -999,7 +865,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_emptyWindowConfigNavigationSrcInstallAttTriggerNextHour() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn("").when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
doReturn("").when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
long triggerTime = System.currentTimeMillis();
@@ -1010,6 +875,7 @@ public class EventReportWindowCalcDelegateTest {
.setAppDestinations(
SourceFixture.ValidSourceParams.ATTRIBUTION_DESTINATIONS)
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -1021,70 +887,7 @@ public class EventReportWindowCalcDelegateTest {
}
@Test
- public void getReportingTime_nullWindowConfigNavigationSourceTriggerInSecondWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long sourceExpiryTime = triggerTime + TimeUnit.DAYS.toMillis(25);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(3);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.NAVIGATION)
- .setEventReportWindow(sourceExpiryTime)
- .setEventTime(sourceEventTime)
- .build();
- assertEquals(
- sourceEventTime
- + PrivacyParams.NAVIGATION_EARLY_REPORTING_WINDOW_MILLISECONDS[1]
- + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.APP));
- }
-
- @Test
- public void getReportingTime_nullWindowConfigNavigationSecondExpiry() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long sourceExpiryTime = triggerTime + TimeUnit.DAYS.toMillis(2);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(3);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.NAVIGATION)
- .setEventReportWindow(sourceExpiryTime)
- .setEventTime(sourceEventTime)
- .build();
- assertEquals(
- sourceExpiryTime + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.APP));
- }
-
- @Test
- public void getReportingTime_nullWindowConfigNavigationLast_fallbackToDefault() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsVtcEarlyReportingWindows();
- doReturn(null).when(mFlags).getMeasurementEventReportsCtcEarlyReportingWindows();
- long triggerTime = System.currentTimeMillis();
- long sourceExpiryTime = triggerTime + TimeUnit.DAYS.toMillis(1);
- long sourceEventTime = triggerTime - TimeUnit.DAYS.toMillis(20);
- Source source =
- SourceFixture.getMinimalValidSourceBuilder()
- .setSourceType(Source.SourceType.NAVIGATION)
- .setEventReportWindow(sourceExpiryTime)
- .setEventTime(sourceEventTime)
- .build();
- assertEquals(
- sourceExpiryTime + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
- mEventReportWindowCalcDelegate.getReportingTime(
- source, triggerTime, EventSurfaceType.APP));
- }
-
- @Test
public void getReportingTime_MalformedWindowConfigEventSourceAppDestination_returnsDefault() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(MALFORMED_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1097,6 +900,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1108,7 +912,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_MalformedWindowConfigEventSrcInstallAttAppDestTrigger1stWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(MALFORMED_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1121,6 +924,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -1135,7 +939,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_MalformedWindowConfigEventSrcInstallAttAppDestTrigger2ndWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(MALFORMED_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1148,6 +951,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -1160,7 +964,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_MalformedWindowConfigEventSrcInstallAttWebDestTrigger1stWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(MALFORMED_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1173,6 +976,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -1185,7 +989,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_MalformedWindowConfigEventSrcInstallAttWebDestTrigger2ndWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(MALFORMED_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1198,6 +1001,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -1210,7 +1014,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_MalformedWindowConfigEventSourceWebDestination() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(MALFORMED_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1223,6 +1026,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1234,7 +1038,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_MalformedWindowConfigNavigationSourceTriggerInFirstWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1247,6 +1050,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1260,7 +1064,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_MalformedWindowConfigNavigationSourceTriggerInSecondWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1273,6 +1076,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1286,7 +1090,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_MalformedWindowConfigNavigationSecondExpiry_fallbackToDefault() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1299,6 +1102,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1310,7 +1114,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_MalformedWindowConfigNavigationLast_fallbackToDefault() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1323,6 +1126,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(sourceExpiryTime)
.setEventReportWindow(sourceExpiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1334,7 +1138,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_validWindowConfigEventSourceTriggerIn1stWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1347,6 +1150,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1358,7 +1162,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_validWindowConfigEventSourceTriggerIn2ndWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1371,6 +1174,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1383,7 +1187,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_validWindowConfigEventSourceTriggerInLastWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1396,6 +1199,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -1408,7 +1212,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_validWindowConfigNavigationSourceTriggerIn1stWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1421,6 +1224,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1432,7 +1236,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_validWindowConfigNavigationSourceTriggerIn2ndWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1445,6 +1248,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1457,7 +1261,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_validWindowConfigNavigationSourceTriggerInLastWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(MALFORMED_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1470,6 +1273,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.setInstallAttributed(true)
@@ -1482,7 +1286,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_invalidWindowConfigEventSourceTriggerIn1stWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(INVALID_1H_1D_2D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1495,6 +1298,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.EVENT)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1506,7 +1310,6 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getReportingTime_invalidWindowConfigNavigationSourceTriggerIn1stWindow() {
- doReturn(true).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
doReturn(VALID_1H_1D_WINDOW_CONFIG)
.when(mFlags)
.getMeasurementEventReportsVtcEarlyReportingWindows();
@@ -1519,6 +1322,7 @@ public class EventReportWindowCalcDelegateTest {
Source source =
SourceFixture.getMinimalValidSourceBuilder()
.setSourceType(Source.SourceType.NAVIGATION)
+ .setExpiryTime(expiryTime)
.setEventReportWindow(expiryTime)
.setEventTime(sourceEventTime)
.build();
@@ -1713,49 +1517,49 @@ public class EventReportWindowCalcDelegateTest {
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- oneWindowNoStart, 0, false));
+ oneWindowNoStart, 0));
// InstallCase doesn't affect the report time
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- oneWindowNoStart, 0, true));
+ oneWindowNoStart, 0));
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- oneWindowWithStart, 0, false));
+ oneWindowWithStart, 0));
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- twoWindowsNoStart, 0, false));
+ twoWindowsNoStart, 0));
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(5) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- twoWindowsNoStart, 1, false));
+ twoWindowsNoStart, 1));
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(2) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- fiveWindowsWithStart, 0, false));
+ fiveWindowsWithStart, 0));
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(5) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- fiveWindowsWithStart, 1, false));
+ fiveWindowsWithStart, 1));
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(7) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- fiveWindowsWithStart, 2, false));
+ fiveWindowsWithStart, 2));
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(10) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- fiveWindowsWithStart, 3, false));
+ fiveWindowsWithStart, 3));
assertEquals(
sourceTime + TimeUnit.DAYS.toMillis(20) + MEASUREMENT_MIN_EVENT_REPORT_DELAY_MILLIS,
mEventReportWindowCalcDelegate.getReportingTimeForNoising(
- fiveWindowsWithStart, 4, false));
+ fiveWindowsWithStart, 4));
}
@Test
@@ -1863,7 +1667,8 @@ public class EventReportWindowCalcDelegateTest {
@Test
public void getMaxReportCount_flexLiteApi() {
doReturn(true).when(mFlags).getMeasurementFlexLiteApiEnabled();
- doReturn(false).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
+ doReturn(Flags.DEFAULT_MEASUREMENT_VTC_CONFIGURABLE_MAX_EVENT_REPORTS_COUNT)
+ .when(mFlags).getMeasurementVtcConfigurableMaxEventReportsCount();
long sourceTime = System.currentTimeMillis();
Source source10Reports =
SourceFixture.getMinimalValidSourceBuilder()
@@ -1871,10 +1676,20 @@ public class EventReportWindowCalcDelegateTest {
.setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(30))
.setEventTime(sourceTime)
.build();
- assertEquals(10, mEventReportWindowCalcDelegate.getMaxReportCount(source10Reports, true));
- assertEquals(10, mEventReportWindowCalcDelegate.getMaxReportCount(source10Reports, false));
+ assertEquals(10, mEventReportWindowCalcDelegate.getMaxReportCount(source10Reports));
+ assertEquals(10, mEventReportWindowCalcDelegate.getMaxReportCount(source10Reports));
- Source sourceDefaultEvent =
+ Source eventSourceInstallAttributed =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setEventReportWindows(EVENT_REPORT_WINDOWS_5_WINDOWS_WITH_START)
+ .setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(30))
+ .setEventTime(sourceTime)
+ .setSourceType(Source.SourceType.EVENT)
+ .setInstallAttributed(true)
+ .setInstallCooldownWindow(1L)
+ .build();
+
+ Source eventSource =
SourceFixture.getMinimalValidSourceBuilder()
.setEventReportWindows(EVENT_REPORT_WINDOWS_5_WINDOWS_WITH_START)
.setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(30))
@@ -1884,12 +1699,23 @@ public class EventReportWindowCalcDelegateTest {
assertEquals(
PrivacyParams.INSTALL_ATTR_EVENT_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(sourceDefaultEvent, true));
+ mEventReportWindowCalcDelegate.getMaxReportCount(
+ eventSourceInstallAttributed));
assertEquals(
PrivacyParams.EVENT_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(sourceDefaultEvent, false));
+ mEventReportWindowCalcDelegate.getMaxReportCount(eventSource));
- Source sourceDefaultNavigation =
+ Source navigationSourceInstallAttributed =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setEventReportWindows(EVENT_REPORT_WINDOWS_5_WINDOWS_WITH_START)
+ .setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(30))
+ .setEventTime(sourceTime)
+ .setSourceType(Source.SourceType.NAVIGATION)
+ .setInstallAttributed(true)
+ .setInstallCooldownWindow(1L)
+ .build();
+
+ Source navigationSource =
SourceFixture.getMinimalValidSourceBuilder()
.setEventReportWindows(EVENT_REPORT_WINDOWS_5_WINDOWS_WITH_START)
.setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(30))
@@ -1898,18 +1724,27 @@ public class EventReportWindowCalcDelegateTest {
.build();
assertEquals(
- PrivacyParams.INSTALL_ATTR_NAVIGATION_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(sourceDefaultNavigation, true));
+ PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS,
+ mEventReportWindowCalcDelegate.getMaxReportCount(
+ navigationSourceInstallAttributed));
assertEquals(
PrivacyParams.NAVIGATION_SOURCE_MAX_REPORTS,
- mEventReportWindowCalcDelegate.getMaxReportCount(sourceDefaultNavigation, false));
+ mEventReportWindowCalcDelegate.getMaxReportCount(navigationSource));
}
@Test
public void getReportingWindowCountForNoising_flexLiteApi() {
doReturn(true).when(mFlags).getMeasurementFlexLiteApiEnabled();
- doReturn(false).when(mFlags).getMeasurementEnableConfigurableEventReportingWindows();
long sourceTime = System.currentTimeMillis();
+ Source defaultSourceEventInstallAttributed =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(30))
+ .setEventTime(sourceTime)
+ .setSourceType(Source.SourceType.EVENT)
+ .setInstallAttributed(true)
+ .setInstallCooldownWindow(1L)
+ .build();
+
Source defaultSourceEvent =
SourceFixture.getMinimalValidSourceBuilder()
.setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(30))
@@ -1952,56 +1787,110 @@ public class EventReportWindowCalcDelegateTest {
assertEquals(
2,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- defaultSourceEvent, true));
+ defaultSourceEventInstallAttributed));
assertEquals(
1,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- defaultSourceEvent, false));
+ defaultSourceEvent));
assertEquals(
3,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- defaultSourceNavigation, true));
+ defaultSourceNavigation));
assertEquals(
3,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- defaultSourceNavigation, false));
+ defaultSourceNavigation));
// InstallCase doesn't affect the report count
assertEquals(
1,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- oneWindowNoStart, true));
+ oneWindowNoStart));
assertEquals(
1,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- oneWindowNoStart, false));
+ oneWindowNoStart));
assertEquals(
1,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- oneWindowWithStart, true));
+ oneWindowWithStart));
assertEquals(
1,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- oneWindowWithStart, false));
+ oneWindowWithStart));
assertEquals(
2,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- twoWindowsNoStart, true));
+ twoWindowsNoStart));
assertEquals(
2,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- twoWindowsNoStart, false));
+ twoWindowsNoStart));
assertEquals(
5,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- fiveWindowsWithStart, true));
+ fiveWindowsWithStart));
assertEquals(
5,
mEventReportWindowCalcDelegate.getReportingWindowCountForNoising(
- fiveWindowsWithStart, false));
+ fiveWindowsWithStart));
+ }
+
+ @Test
+ public void fallsWithinWindow_windowNotStarted() {
+ doReturn(true).when(mFlags).getMeasurementFlexLiteApiEnabled();
+ long sourceTime = System.currentTimeMillis();
+ long triggerTime = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1) - 1;
+ Source source =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setSourceType(Source.SourceType.EVENT)
+ .setEventTime(sourceTime)
+ .setEventReportWindows(EVENT_REPORT_WINDOWS_2_WINDOWS_WITH_START)
+ .setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(25))
+ .build();
+ assertEquals(
+ EventReportWindowCalcDelegate.MomentPlacement.BEFORE,
+ mEventReportWindowCalcDelegate.fallsWithinWindow(
+ source, triggerTime, EventSurfaceType.APP));
+ }
+
+ @Test
+ public void fallsWithinWindow_windowWithin() {
+ doReturn(true).when(mFlags).getMeasurementFlexLiteApiEnabled();
+ long sourceTime = System.currentTimeMillis();
+ long triggerTime = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1);
+ Source source =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setSourceType(Source.SourceType.EVENT)
+ .setEventTime(sourceTime)
+ .setEventReportWindows(EVENT_REPORT_WINDOWS_2_WINDOWS_WITH_START)
+ .setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(25))
+ .build();
+ assertEquals(
+ EventReportWindowCalcDelegate.MomentPlacement.WITHIN,
+ mEventReportWindowCalcDelegate.fallsWithinWindow(
+ source, triggerTime, EventSurfaceType.APP));
+ }
+
+ @Test
+ public void fallsWithinWindow_windowPassed() {
+ doReturn(true).when(mFlags).getMeasurementFlexLiteApiEnabled();
+ long sourceTime = System.currentTimeMillis();
+ long triggerTime = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(20);
+ Source source =
+ SourceFixture.getMinimalValidSourceBuilder()
+ .setSourceType(Source.SourceType.EVENT)
+ .setEventTime(sourceTime)
+ .setEventReportWindows(EVENT_REPORT_WINDOWS_2_WINDOWS_WITH_START)
+ .setExpiryTime(sourceTime + TimeUnit.DAYS.toMillis(25))
+ .build();
+ assertEquals(
+ EventReportWindowCalcDelegate.MomentPlacement.AFTER,
+ mEventReportWindowCalcDelegate.fallsWithinWindow(
+ source, triggerTime, EventSurfaceType.APP));
}
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/shell/AdServicesShellCommandHandlerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/shell/AdServicesShellCommandHandlerTest.java
index 7341b1d33..0d2c08844 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/shell/AdServicesShellCommandHandlerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/shell/AdServicesShellCommandHandlerTest.java
@@ -70,14 +70,14 @@ public final class AdServicesShellCommandHandlerTest extends AdServicesExtendedM
@Test
public void testRunHelp() throws Exception {
- String result = mCmd.runInvalid(CMD_HELP);
+ String result = mCmd.runValid(CMD_HELP);
assertHelpContents(result);
}
@Test
public void testRunHelpShort() throws Exception {
- String result = mCmd.runInvalid(CMD_SHORT_HELP);
+ String result = mCmd.runValid(CMD_SHORT_HELP);
assertHelpContents(result);
}
@@ -283,7 +283,10 @@ public final class AdServicesShellCommandHandlerTest extends AdServicesExtendedM
private final StringWriter mOutStringWriter = new StringWriter();
private final PrintWriter mOut = new PrintWriter(mOutStringWriter);
- public final AdServicesShellCommandHandler cmd = new AdServicesShellCommandHandler(mOut);
+ private final StringWriter mErrStringWriter = new StringWriter();
+ private final PrintWriter mErr = new PrintWriter(mErrStringWriter);
+ public final AdServicesShellCommandHandler cmd =
+ new AdServicesShellCommandHandler(mOut, mErr);
private boolean mOutCalled;
@@ -302,7 +305,7 @@ public final class AdServicesShellCommandHandlerTest extends AdServicesExtendedM
.that(result)
.isAtLeast(0);
- return getOut();
+ return getResult(mOut, mOutStringWriter);
}
/**
@@ -316,7 +319,7 @@ public final class AdServicesShellCommandHandlerTest extends AdServicesExtendedM
.that(result)
.isLessThan(0);
- return getOut();
+ return getResult(mErr, mErrStringWriter);
}
/**
@@ -334,13 +337,13 @@ public final class AdServicesShellCommandHandlerTest extends AdServicesExtendedM
* <p>Can only be called once per test, as there is no way to reset it, which could cause
* confusion for the test developer.
*/
- String getOut() throws IOException {
+ String getResult(PrintWriter pw, StringWriter sw) throws IOException {
if (mOutCalled) {
throw new IllegalStateException("getOut() already called");
}
- mOut.flush();
- String out = mOutStringWriter.toString();
- mOut.close();
+ pw.flush();
+ String out = sw.toString();
+ pw.close();
mOutCalled = true;
return out;
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/shell/ShellCommandServiceImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/shell/ShellCommandServiceImplTest.java
new file mode 100644
index 000000000..a07a5f650
--- /dev/null
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/shell/ShellCommandServiceImplTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 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.service.shell;
+
+import android.adservices.shell.IShellCommandCallback;
+import android.adservices.shell.ShellCommandParam;
+import android.adservices.shell.ShellCommandResult;
+import android.os.IBinder;
+
+import com.android.adservices.common.AdServicesUnitTestCase;
+import com.android.adservices.common.NoFailureSyncCallback;
+
+import org.junit.Test;
+
+public final class ShellCommandServiceImplTest extends AdServicesUnitTestCase {
+
+ @Test
+ public void testRunShellCommand() throws Exception {
+ ShellCommandServiceImpl service = new ShellCommandServiceImpl();
+ SyncIShellCommandCallback callback = new SyncIShellCommandCallback();
+
+ service.runShellCommand(new ShellCommandParam("echo", "xxx"), callback);
+
+ ShellCommandResult response = callback.assertResultReceived();
+ expect.withMessage("result").that(response.getResultCode()).isEqualTo(0);
+ expect.withMessage("out").that(response.getOut()).contains("xxx");
+ expect.withMessage("err").that(response.getErr()).isEmpty();
+ }
+
+ @Test
+ public void testRunShellCommand_invalidCommand() throws Exception {
+ ShellCommandServiceImpl service = new ShellCommandServiceImpl();
+ SyncIShellCommandCallback callback = new SyncIShellCommandCallback();
+
+ service.runShellCommand(new ShellCommandParam("invalid-cmd"), callback);
+
+ ShellCommandResult response = callback.assertResultReceived();
+ expect.withMessage("result").that(response.getResultCode()).isEqualTo(-1);
+ expect.withMessage("out").that(response.getOut()).isEmpty();
+ expect.withMessage("err").that(response.getErr()).contains("Unknown command");
+ }
+
+ private static final class SyncIShellCommandCallback
+ extends NoFailureSyncCallback<ShellCommandResult> implements IShellCommandCallback {
+
+ @Override
+ public void onResult(ShellCommandResult response) {
+ injectResult(response);
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return null;
+ }
+ }
+}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/PeriodicEncodingJobWorkerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/PeriodicEncodingJobWorkerTest.java
index 3be31f28b..1bf8fb9b9 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/PeriodicEncodingJobWorkerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/PeriodicEncodingJobWorkerTest.java
@@ -37,10 +37,12 @@ import android.adservices.common.CommonFixture;
import com.android.adservices.concurrency.AdServicesExecutors;
import com.android.adservices.data.signals.DBEncodedPayload;
import com.android.adservices.data.signals.DBEncoderLogicMetadata;
+import com.android.adservices.data.signals.DBSignalsUpdateMetadata;
import com.android.adservices.data.signals.EncodedPayloadDao;
import com.android.adservices.data.signals.EncoderLogicHandler;
import com.android.adservices.data.signals.EncoderLogicMetadataDao;
import com.android.adservices.data.signals.EncoderPersistenceDao;
+import com.android.adservices.data.signals.ProtectedSignalsDao;
import com.android.adservices.service.Flags;
import com.android.adservices.service.adselection.AdSelectionScriptEngine;
import com.android.adservices.service.devapi.DevContextFilter;
@@ -113,6 +115,7 @@ public class PeriodicEncodingJobWorkerTest {
@Mock private EncoderLogicMetadataDao mEncoderLogicMetadataDao;
@Mock private EncoderPersistenceDao mEncoderPersistenceDao;
@Mock private EncodedPayloadDao mEncodedPayloadDao;
+ @Mock private ProtectedSignalsDao mProtectedSignalsDao;
@Mock private SignalsProviderImpl mSignalStorageManager;
@Mock private AdSelectionScriptEngine mScriptEngine;
@Mock private DevContextFilter mDevContextFilter;
@@ -138,9 +141,9 @@ public class PeriodicEncodingJobWorkerTest {
new PeriodicEncodingJobWorker(
mEncoderLogicHandler,
mEncoderLogicMetadataDao,
- mEncoderPersistenceDao,
mEncodedPayloadDao,
mSignalStorageManager,
+ mProtectedSignalsDao,
mScriptEngine,
mBackgroundExecutor,
mLightWeightExecutor,
@@ -172,9 +175,9 @@ public class PeriodicEncodingJobWorkerTest {
new PeriodicEncodingJobWorker(
mEncoderLogicHandler,
mEncoderLogicMetadataDao,
- mEncoderPersistenceDao,
mEncodedPayloadDao,
mSignalStorageManager,
+ mProtectedSignalsDao,
mScriptEngine,
mBackgroundExecutor,
mLightWeightExecutor,
@@ -243,7 +246,8 @@ public class PeriodicEncodingJobWorkerTest {
.get(5, TimeUnit.SECONDS));
assertEquals(IllegalStateException.class, e.getCause().getClass());
assertEquals(PAYLOAD_PERSISTENCE_ERROR_MSG, e.getCause().getMessage());
- Mockito.verifyZeroInteractions(mEncodedPayloadDao);
+ verify(mEncodedPayloadDao).getEncodedPayload(BUYER);
+ verifyNoMoreInteractions(mEncodedPayloadDao);
}
@Test
@@ -267,7 +271,8 @@ public class PeriodicEncodingJobWorkerTest {
});
assertEquals(IllegalStateException.class, e.getCause().getClass());
assertEquals(PAYLOAD_PERSISTENCE_ERROR_MSG, e.getCause().getMessage());
- Mockito.verifyZeroInteractions(mEncodedPayloadDao);
+ verify(mEncodedPayloadDao).getEncodedPayload(BUYER);
+ verifyNoMoreInteractions(mEncodedPayloadDao);
}
@Test
@@ -328,7 +333,8 @@ public class PeriodicEncodingJobWorkerTest {
stallEncodingLatch.getCount());
// e is TimeoutFuture$TimeoutFutureException which extends TimeoutException
assertTrue(TimeoutException.class.isAssignableFrom(e.getCause().getClass()));
- Mockito.verifyZeroInteractions(mEncodedPayloadDao);
+ verify(mEncodedPayloadDao).getEncodedPayload(BUYER);
+ verifyNoMoreInteractions(mEncodedPayloadDao);
}
@Test
@@ -361,6 +367,8 @@ public class PeriodicEncodingJobWorkerTest {
verify(mEncoderLogicHandler).getAllRegisteredEncoders();
verify(mEncoderLogicHandler).getEncoder(BUYER);
verify(mSignalStorageManager).getSignals(BUYER);
+ verify(mEncodedPayloadDao, times(1)).getEncodedPayload(BUYER);
+ verify(mEncodedPayloadDao, times(1)).getEncodedPayload(BUYER_2);
verify(mEncodedPayloadDao, times(1)).persistEncodedPayload(mEncodedPayloadCaptor.capture());
verify(mEncoderLogicHandler).updateEncoderFailedCount(BUYER_2, 1);
assertEquals(BUYER, mEncodedPayloadCaptor.getValue().getBuyer());
@@ -368,7 +376,6 @@ public class PeriodicEncodingJobWorkerTest {
assertEquals(
getSetFromBytes(validResponse),
getSetFromBytes(mEncodedPayloadCaptor.getValue().getEncodedPayload()));
- verify(mEncoderLogicHandler).updateEncoderFailedCount(BUYER_2, 1);
}
@Test
@@ -417,6 +424,39 @@ public class PeriodicEncodingJobWorkerTest {
}
@Test
+ public void testEncodeSignals_noUpdateToBuyer_skipEncoding()
+ throws ExecutionException, InterruptedException, TimeoutException {
+ when(mSignalStorageManager.getSignals(BUYER)).thenReturn(FAKE_SIGNALS);
+ when(mProtectedSignalsDao.getSignalsUpdateMetadata(BUYER))
+ .thenReturn(
+ DBSignalsUpdateMetadata.builder()
+ .setBuyer(BUYER)
+ .setLastSignalsUpdatedTime(CommonFixture.FIXED_EARLIER_ONE_DAY)
+ .build());
+ when(mEncodedPayloadDao.getEncodedPayload(BUYER))
+ .thenReturn(
+ DBEncodedPayload.create(
+ BUYER, 1, CommonFixture.FIXED_NOW, new byte[] {0x22, 0x33}));
+
+ mJobWorker
+ .runEncodingPerBuyer(
+ DBEncoderLogicMetadata.builder()
+ .setBuyer(BUYER)
+ .setCreationTime(CommonFixture.FIXED_EARLIER_ONE_DAY)
+ .setVersion(1)
+ .setFailedEncodingCount(1)
+ .build(),
+ TIMEOUT_SECONDS)
+ .get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+
+ verify(mSignalStorageManager).getSignals(BUYER);
+ verify(mProtectedSignalsDao).getSignalsUpdateMetadata(BUYER);
+ verify(mEncodedPayloadDao).getEncodedPayload(BUYER);
+ verifyNoMoreInteractions(mSignalStorageManager, mProtectedSignalsDao, mEncodedPayloadDao);
+ verifyZeroInteractions(mEncoderLogicHandler, mScriptEngine);
+ }
+
+ @Test
public void testUpdatesEncodersAllUpdatedEncodersDoNotDownloadAgain() {
when(mEncoderLogicMetadataDao.getBuyersWithEncodersBeforeTime(any()))
.thenReturn(Collections.emptyList());
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/ProtectedSignalsServiceImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/ProtectedSignalsServiceImplTest.java
index 07ca5a5b4..079d58612 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/ProtectedSignalsServiceImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/ProtectedSignalsServiceImplTest.java
@@ -170,8 +170,7 @@ public class ProtectedSignalsServiceImplTest {
mProtectedSignalsService.updateSignals(mInput, mUpdateSignalsCallbackMock);
verify(mFledgeAuthorizationFilterMock)
- .assertAppDeclaredProtectedSignalsPermission(
- eq(CONTEXT), eq(PACKAGE), eq(API_NAME));
+ .assertAppDeclaredPermission(eq(CONTEXT), eq(PACKAGE), eq(API_NAME));
verify(mCallingAppUidSupplierMock).getCallingAppUid();
verify(mDevContextFilterMock).createDevContext();
verify(mFlagsMock).getDisableFledgeEnrollmentCheck();
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsEncodingE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsEncodingE2ETest.java
index 3c8e73dfc..f877873f9 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsEncodingE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsEncodingE2ETest.java
@@ -25,7 +25,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
@@ -199,6 +198,7 @@ public class SignalsEncodingE2ETest {
mEncoderPersistenceDao,
mEncoderEndpointsDao,
mEncoderLogicMetadataDao,
+ mSignalsDao,
mAdServicesHttpsClient,
mBackgroundExecutorService);
mUpdateEncoderEventHandler =
@@ -244,7 +244,8 @@ public class SignalsEncodingE2ETest {
mBackgroundExecutorService,
mUpdatesDownloader,
mUpdateProcessingOrchestrator,
- mAdtechUriValidator);
+ mAdtechUriValidator,
+ CommonFixture.FIXED_CLOCK_TRUNCATED_TO_MILLI);
mService =
new ProtectedSignalsServiceImpl(
mContextSpy,
@@ -277,9 +278,9 @@ public class SignalsEncodingE2ETest {
new PeriodicEncodingJobWorker(
mEncoderLogicHandler,
mEncoderLogicMetadataDao,
- mEncoderPersistenceDao,
mEncodedPayloadDao,
mSignalStorageManager,
+ mSignalsDao,
mAdSelectionScriptEngine,
mBackgroundExecutorService,
mLightweightExecutorService,
@@ -650,9 +651,9 @@ public class SignalsEncodingE2ETest {
new PeriodicEncodingJobWorker(
mEncoderLogicHandler,
mEncoderLogicMetadataDao,
- mEncoderPersistenceDao,
mEncodedPayloadDao,
mSignalStorageManager,
+ mSignalsDao,
mAdSelectionScriptEngine,
mBackgroundExecutorService,
mLightweightExecutorService,
@@ -686,9 +687,9 @@ public class SignalsEncodingE2ETest {
new PeriodicEncodingJobWorker(
mEncoderLogicHandler,
mEncoderLogicMetadataDao,
- mEncoderPersistenceDao,
mEncodedPayloadDao,
mSignalStorageManager,
+ mSignalsDao,
mAdSelectionScriptEngine,
mBackgroundExecutorService,
mLightweightExecutorService,
@@ -705,7 +706,9 @@ public class SignalsEncodingE2ETest {
"Encoding JS should have returned size of signals as result",
new byte[] {(byte) expected.size()},
payload2);
- assertTrue(secondEncodingRun.getCreationTime().isAfter(firstEncodingRun.getCreationTime()));
+ // The second run should skip based on the logic that we will skip encoding for unchanged
+ // buyer.
+ assertEquals(secondEncodingRun.getCreationTime(), firstEncodingRun.getCreationTime());
encoderLogicDownloadedLatch.await(5, TimeUnit.SECONDS);
assertEquals(
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsIntakeE2ETest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsIntakeE2ETest.java
index d57f6adf1..c158543e1 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsIntakeE2ETest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsIntakeE2ETest.java
@@ -172,6 +172,7 @@ public class SignalsIntakeE2ETest {
mEncoderPersistenceDao,
mEncoderEndpointsDao,
mEncoderLogicMetadataDao,
+ mSignalsDao,
mAdServicesHttpsClientMock,
mBackgroundExecutorService);
mUpdateEncoderEventHandler =
@@ -235,7 +236,8 @@ public class SignalsIntakeE2ETest {
mBackgroundExecutorService,
mUpdatesDownloader,
mUpdateProcessingOrchestrator,
- mAdtechUriValidator);
+ mAdtechUriValidator,
+ CommonFixture.FIXED_CLOCK_TRUNCATED_TO_MILLI);
mService =
new ProtectedSignalsServiceImpl(
mContextSpy,
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsMaintenanceTasksWorkerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsMaintenanceTasksWorkerTest.java
index ab251d56a..60d8859ac 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsMaintenanceTasksWorkerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/SignalsMaintenanceTasksWorkerTest.java
@@ -17,6 +17,7 @@
package com.android.adservices.service.signals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@@ -55,6 +56,7 @@ public class SignalsMaintenanceTasksWorkerTest {
@Mock private PackageManager mPackageManagerMock;
SignalsMaintenanceTasksWorker mSignalsMaintenanceTasksWorker;
+ Instant mNow;
Instant mExpirationTime;
@Before
@@ -69,6 +71,7 @@ public class SignalsMaintenanceTasksWorkerTest {
mClockMock,
mPackageManagerMock);
when(mClockMock.instant()).thenReturn(CommonFixture.FIXED_NOW);
+ mNow = CommonFixture.FIXED_NOW;
mExpirationTime = CommonFixture.FIXED_NOW.minusSeconds(ProtectedSignal.EXPIRATION_SECONDS);
}
@@ -76,21 +79,25 @@ public class SignalsMaintenanceTasksWorkerTest {
public void testClearInvalidSignalsEnrollmentEnabled() throws Exception {
when(mFlagsMock.getDisableFledgeEnrollmentCheck()).thenReturn(false);
- mSignalsMaintenanceTasksWorker.clearInvalidSignals(mExpirationTime);
+ mSignalsMaintenanceTasksWorker.clearInvalidSignals(mExpirationTime, mNow);
- verify(mProtectedSignalsDaoMock).deleteSignalsBeforeTime(mExpirationTime);
+ verify(mProtectedSignalsDaoMock)
+ .deleteExpiredSignalsAndUpdateSignalsUpdateMetadata(mExpirationTime, mNow);
verify(mFlagsMock).getDisableFledgeEnrollmentCheck();
verify(mProtectedSignalsDaoMock).deleteDisallowedBuyerSignals(any());
- verify(mProtectedSignalsDaoMock).deleteAllDisallowedPackageSignals(any(), any());
+ verify(mProtectedSignalsDaoMock)
+ .deleteAllDisallowedPackageSignalsAndUpdateSignalUpdateMetadata(
+ any(), any(), eq(mNow));
}
@Test
public void testClearInvalidSignalsEnrollmentDisabled() throws Exception {
when(mFlagsMock.getDisableFledgeEnrollmentCheck()).thenReturn(true);
- mSignalsMaintenanceTasksWorker.clearInvalidSignals(mExpirationTime);
+ mSignalsMaintenanceTasksWorker.clearInvalidSignals(mExpirationTime, mNow);
- verify(mProtectedSignalsDaoMock).deleteSignalsBeforeTime(mExpirationTime);
+ verify(mProtectedSignalsDaoMock)
+ .deleteExpiredSignalsAndUpdateSignalsUpdateMetadata(mExpirationTime, mNow);
verify(mFlagsMock).getDisableFledgeEnrollmentCheck();
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateProcessingOrchestratorTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateProcessingOrchestratorTest.java
index 4b6b57b39..346f969a0 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateProcessingOrchestratorTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateProcessingOrchestratorTest.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@@ -97,7 +98,7 @@ public class UpdateProcessingOrchestratorTest {
ADTECH, PACKAGE, NOW, new JSONObject(), DEV_CONTEXT);
verify(mProtectedSignalsDaoMock).getSignalsByBuyer(eq(ADTECH));
verify(mProtectedSignalsDaoMock)
- .insertAndDelete(Collections.emptyList(), Collections.emptyList());
+ .insertAndDelete(ADTECH, NOW, Collections.emptyList(), Collections.emptyList());
verifyZeroInteractions(mUpdateProcessorSelectorMock);
verify(mSignalEvictionControllerMock)
.evict(
@@ -136,7 +137,9 @@ public class UpdateProcessingOrchestratorTest {
mUpdateProcessingOrchestrator.processUpdates(
ADTECH, PACKAGE, NOW, commandToNumber, DEV_CONTEXT));
assertEquals(exception, t.getCause());
+ verify(mProtectedSignalsDaoMock).getSignalsByBuyer(ADTECH);
verifyZeroInteractions(mSignalEvictionControllerMock);
+ verifyNoMoreInteractions(mProtectedSignalsDaoMock);
}
@Test
@@ -156,8 +159,9 @@ public class UpdateProcessingOrchestratorTest {
mUpdateProcessingOrchestrator.processUpdates(ADTECH, PACKAGE, NOW, json, DEV_CONTEXT);
- List<DBProtectedSignal> expected = Arrays.asList(createSignal(KEY_1, VALUE));
- verify(mProtectedSignalsDaoMock).insertAndDelete(eq(expected), eq(Collections.emptyList()));
+ List<DBProtectedSignal> expected = List.of(createSignal(KEY_1, VALUE));
+ verify(mProtectedSignalsDaoMock)
+ .insertAndDelete(ADTECH, NOW, expected, Collections.emptyList());
verify(mUpdateProcessorSelectorMock).getUpdateProcessor(eq(TEST_PROCESSOR));
verify(mSignalEvictionControllerMock)
.evict(
@@ -185,7 +189,8 @@ public class UpdateProcessingOrchestratorTest {
mUpdateProcessingOrchestrator.processUpdates(ADTECH, PACKAGE, NOW, json, DEV_CONTEXT);
List<DBProtectedSignal> expected = Arrays.asList(createSignal(KEY_1, VALUE));
- verify(mProtectedSignalsDaoMock).insertAndDelete(eq(expected), eq(Collections.emptyList()));
+ verify(mProtectedSignalsDaoMock)
+ .insertAndDelete(ADTECH, NOW, expected, Collections.emptyList());
verify(mUpdateProcessorSelectorMock).getUpdateProcessor(eq(TEST_PROCESSOR));
verify(mSignalEvictionControllerMock)
.evict(
@@ -214,7 +219,7 @@ public class UpdateProcessingOrchestratorTest {
verify(mProtectedSignalsDaoMock).getSignalsByBuyer(eq(ADTECH));
verify(mProtectedSignalsDaoMock)
- .insertAndDelete(eq(Collections.emptyList()), eq(Arrays.asList(toRemove)));
+ .insertAndDelete(ADTECH, NOW, Collections.emptyList(), Arrays.asList(toRemove));
verify(mUpdateProcessorSelectorMock).getUpdateProcessor(eq(TEST_PROCESSOR));
verify(mSignalEvictionControllerMock)
.evict(eq(ADTECH), eq(List.of(toKeep)), mUpdateOutputArgumentCaptor.capture());
@@ -250,7 +255,8 @@ public class UpdateProcessingOrchestratorTest {
DBProtectedSignal expected1 = createSignal(KEY_1, VALUE);
DBProtectedSignal expected2 = createSignal(KEY_2, VALUE);
verify(mProtectedSignalsDaoMock)
- .insertAndDelete(mInsertCaptor.capture(), eq(Collections.emptyList()));
+ .insertAndDelete(
+ eq(ADTECH), eq(NOW), mInsertCaptor.capture(), eq(Collections.emptyList()));
assertThat(mInsertCaptor.getValue())
.containsExactlyElementsIn(Arrays.asList(expected1, expected2));
verify(mUpdateProcessorSelectorMock).getUpdateProcessor(eq(TEST_PROCESSOR + 1));
@@ -317,7 +323,7 @@ public class UpdateProcessingOrchestratorTest {
verify(mProtectedSignalsDaoMock).getSignalsByBuyer(eq(ADTECH));
verify(mProtectedSignalsDaoMock)
.insertAndDelete(
- eq(Collections.emptyList()), eq(Arrays.asList(toRemove1, toRemove2)));
+ ADTECH, NOW, Collections.emptyList(), Arrays.asList(toRemove1, toRemove2));
verify(mUpdateProcessorSelectorMock).getUpdateProcessor(eq(TEST_PROCESSOR));
verify(mSignalEvictionControllerMock)
.evict(eq(ADTECH), eq(List.of()), mUpdateOutputArgumentCaptor.capture());
@@ -441,7 +447,7 @@ public class UpdateProcessingOrchestratorTest {
mUpdateProcessingOrchestrator.processUpdates(ADTECH, PACKAGE, NOW, json, DEV_CONTEXT);
List<DBProtectedSignal> expected = Arrays.asList(createSignal(KEY_1, VALUE));
- verify(mProtectedSignalsDaoMock).insertAndDelete(eq(expected), eq(expected));
+ verify(mProtectedSignalsDaoMock).insertAndDelete(ADTECH, NOW, expected, expected);
verify(mUpdateProcessorSelectorMock).getUpdateProcessor(eq(TEST_PROCESSOR));
}
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateSignalsOrchestratorTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateSignalsOrchestratorTest.java
index 0e693ffd3..9fea32c03 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateSignalsOrchestratorTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/signals/UpdateSignalsOrchestratorTest.java
@@ -66,7 +66,8 @@ public class UpdateSignalsOrchestratorTest {
AdServicesExecutors.getBackgroundExecutor(),
mUpdatesDownloader,
mUpdateProcessingOrchestrator,
- mAdTechUriValidator);
+ mAdTechUriValidator,
+ CommonFixture.FIXED_CLOCK_TRUNCATED_TO_MILLI);
}
@Test
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/AdServicesLoggerImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/AdServicesLoggerImplTest.java
index 7e63a2ced..4fbe03c82 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/AdServicesLoggerImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/AdServicesLoggerImplTest.java
@@ -88,48 +88,37 @@ import static com.android.adservices.service.stats.RunAdSelectionProcessReported
import static com.android.adservices.service.stats.UpdateCustomAudienceProcessReportedStatsTest.DATA_SIZE_OF_ADS_IN_BYTES;
import static com.android.adservices.service.stats.UpdateCustomAudienceProcessReportedStatsTest.NUM_OF_ADS;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import android.adservices.adselection.ReportEventRequest;
+import com.android.adservices.common.AdServicesMockitoTestCase;
import com.android.adservices.service.enrollment.EnrollmentStatus;
import com.android.adservices.service.measurement.Source;
import com.android.adservices.service.measurement.WipeoutStatus;
import com.android.adservices.service.measurement.attribution.AttributionStatus;
-import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** Unit tests for {@link AdServicesLoggerImpl}. */
-public class AdServicesLoggerImplTest {
- @Mock StatsdAdServicesLogger mStatsdLoggerMock;
- private static final String SOURCE_REGISTRANT = "android-app://com.registrant";
+public final class AdServicesLoggerImplTest extends AdServicesMockitoTestCase {
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- }
+ @Mock private StatsdAdServicesLogger mStatsdLoggerMock;
@Test
public void testLogFledgeApiCallStats() {
- final int latencyMs = 10;
+ int latencyMs = 10;
AdServicesLoggerImpl adServicesLogger = new AdServicesLoggerImpl(mStatsdLoggerMock);
adServicesLogger.logFledgeApiCallStats(
AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS, STATUS_SUCCESS, latencyMs);
verify(mStatsdLoggerMock)
.logFledgeApiCallStats(
- eq(AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS),
- eq(STATUS_SUCCESS),
- eq(latencyMs));
+ AD_SERVICES_API_CALLED__API_NAME__SELECT_ADS, STATUS_SUCCESS, latencyMs);
}
@Test
@@ -149,22 +138,18 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<RunAdSelectionProcessReportedStats> argumentCaptor =
ArgumentCaptor.forClass(RunAdSelectionProcessReportedStats.class);
verify(mStatsdLoggerMock).logRunAdSelectionProcessReportedStats(argumentCaptor.capture());
- assertEquals(argumentCaptor.getValue().getIsRemarketingAdsWon(), IS_RMKT_ADS_WON);
- assertEquals(
- argumentCaptor.getValue().getDBAdSelectionSizeInBytes(),
- DB_AD_SELECTION_SIZE_IN_BYTES);
- assertEquals(
- argumentCaptor.getValue().getPersistAdSelectionLatencyInMillis(),
- PERSIST_AD_SELECTION_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getRunAdSelectionResultCode(),
- PERSIST_AD_SELECTION_RESULT_CODE);
- assertEquals(
- argumentCaptor.getValue().getRunAdSelectionLatencyInMillis(),
- RUN_AD_SELECTION_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getRunAdSelectionResultCode(),
- RUN_AD_SELECTION_RESULT_CODE);
+ RunAdSelectionProcessReportedStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getIsRemarketingAdsWon()).isEqualTo(IS_RMKT_ADS_WON);
+ expect.that(loggedStats.getDBAdSelectionSizeInBytes())
+ .isEqualTo(DB_AD_SELECTION_SIZE_IN_BYTES);
+ expect.that(loggedStats.getPersistAdSelectionLatencyInMillis())
+ .isEqualTo(PERSIST_AD_SELECTION_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getRunAdSelectionResultCode())
+ .isEqualTo(PERSIST_AD_SELECTION_RESULT_CODE);
+ expect.that(loggedStats.getRunAdSelectionLatencyInMillis())
+ .isEqualTo(RUN_AD_SELECTION_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getRunAdSelectionResultCode())
+ .isEqualTo(RUN_AD_SELECTION_RESULT_CODE);
}
@Test
@@ -200,49 +185,35 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<RunAdScoringProcessReportedStats> argumentCaptor =
ArgumentCaptor.forClass(RunAdScoringProcessReportedStats.class);
verify(mStatsdLoggerMock).logRunAdScoringProcessReportedStats(argumentCaptor.capture());
- assertEquals(
- argumentCaptor.getValue().getGetAdSelectionLogicLatencyInMillis(),
- GET_AD_SELECTION_LOGIC_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getGetAdSelectionLogicResultCode(),
- GET_AD_SELECTION_LOGIC_RESULT_CODE);
- assertEquals(
- argumentCaptor.getValue().getGetAdSelectionLogicScriptType(),
- GET_AD_SELECTION_LOGIC_SCRIPT_TYPE);
- assertEquals(
- argumentCaptor.getValue().getFetchedAdSelectionLogicScriptSizeInBytes(),
- FETCHED_AD_SELECTION_LOGIC_SCRIPT_SIZE_IN_BYTES);
- assertEquals(
- argumentCaptor.getValue().getGetTrustedScoringSignalsLatencyInMillis(),
- GET_TRUSTED_SCORING_SIGNALS_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getGetTrustedScoringSignalsResultCode(),
- GET_TRUSTED_SCORING_SIGNALS_RESULT_CODE);
- assertEquals(
- argumentCaptor.getValue().getFetchedTrustedScoringSignalsDataSizeInBytes(),
- FETCHED_TRUSTED_SCORING_SIGNALS_DATA_SIZE_IN_BYTES);
- assertEquals(
- argumentCaptor.getValue().getScoreAdsLatencyInMillis(),
- SCORE_ADS_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getGetAdScoresLatencyInMillis(),
- GET_AD_SCORES_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getGetAdScoresResultCode(), GET_AD_SCORES_RESULT_CODE);
- assertEquals(
- argumentCaptor.getValue().getNumOfCasEnteringScoring(),
- NUM_OF_CAS_ENTERING_SCORING);
- assertEquals(
- argumentCaptor.getValue().getNumOfRemarketingAdsEnteringScoring(),
- NUM_OF_REMARKETING_ADS_ENTERING_SCORING);
- assertEquals(
- argumentCaptor.getValue().getNumOfContextualAdsEnteringScoring(),
- NUM_OF_CONTEXTUAL_ADS_ENTERING_SCORING);
- assertEquals(
- argumentCaptor.getValue().getRunAdScoringLatencyInMillis(),
- RUN_AD_SCORING_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getRunAdScoringResultCode(), RUN_AD_SCORING_RESULT_CODE);
+ RunAdScoringProcessReportedStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getGetAdSelectionLogicLatencyInMillis())
+ .isEqualTo(GET_AD_SELECTION_LOGIC_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getGetAdSelectionLogicResultCode())
+ .isEqualTo(GET_AD_SELECTION_LOGIC_RESULT_CODE);
+ expect.that(loggedStats.getGetAdSelectionLogicScriptType())
+ .isEqualTo(GET_AD_SELECTION_LOGIC_SCRIPT_TYPE);
+ expect.that(loggedStats.getFetchedAdSelectionLogicScriptSizeInBytes())
+ .isEqualTo(FETCHED_AD_SELECTION_LOGIC_SCRIPT_SIZE_IN_BYTES);
+ expect.that(loggedStats.getGetTrustedScoringSignalsLatencyInMillis())
+ .isEqualTo(GET_TRUSTED_SCORING_SIGNALS_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getGetTrustedScoringSignalsResultCode())
+ .isEqualTo(GET_TRUSTED_SCORING_SIGNALS_RESULT_CODE);
+ expect.that(loggedStats.getFetchedTrustedScoringSignalsDataSizeInBytes())
+ .isEqualTo(FETCHED_TRUSTED_SCORING_SIGNALS_DATA_SIZE_IN_BYTES);
+ expect.that(loggedStats.getScoreAdsLatencyInMillis())
+ .isEqualTo(SCORE_ADS_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getGetAdScoresLatencyInMillis())
+ .isEqualTo(GET_AD_SCORES_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getGetAdScoresResultCode()).isEqualTo(GET_AD_SCORES_RESULT_CODE);
+ expect.that(loggedStats.getNumOfCasEnteringScoring())
+ .isEqualTo(NUM_OF_CAS_ENTERING_SCORING);
+ expect.that(loggedStats.getNumOfRemarketingAdsEnteringScoring())
+ .isEqualTo(NUM_OF_REMARKETING_ADS_ENTERING_SCORING);
+ expect.that(loggedStats.getNumOfContextualAdsEnteringScoring())
+ .isEqualTo(NUM_OF_CONTEXTUAL_ADS_ENTERING_SCORING);
+ expect.that(loggedStats.getRunAdScoringLatencyInMillis())
+ .isEqualTo(RUN_AD_SCORING_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getRunAdScoringResultCode()).isEqualTo(RUN_AD_SCORING_RESULT_CODE);
}
@Test
@@ -270,34 +241,26 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<RunAdBiddingProcessReportedStats> argumentCaptor =
ArgumentCaptor.forClass(RunAdBiddingProcessReportedStats.class);
verify(mStatsdLoggerMock).logRunAdBiddingProcessReportedStats(argumentCaptor.capture());
- assertEquals(
- argumentCaptor.getValue().getGetBuyersCustomAudienceLatencyInMills(),
- GET_BUYERS_CUSTOM_AUDIENCE_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getGetBuyersCustomAudienceResultCode(),
- GET_BUYERS_CUSTOM_AUDIENCE_RESULT_CODE);
- assertEquals(argumentCaptor.getValue().getNumBuyersRequested(), NUM_BUYERS_REQUESTED);
- assertEquals(argumentCaptor.getValue().getNumBuyersFetched(), NUM_BUYERS_FETCHED);
- assertEquals(
- argumentCaptor.getValue().getNumOfAdsEnteringBidding(),
- NUM_OF_ADS_ENTERING_BIDDING);
- assertEquals(
- argumentCaptor.getValue().getNumOfCasEnteringBidding(),
- NUM_OF_CAS_ENTERING_BIDDING);
- assertEquals(
- argumentCaptor.getValue().getNumOfCasPostBidding(), NUM_OF_CAS_POSTING_BIDDING);
- assertEquals(
- argumentCaptor.getValue().getRatioOfCasSelectingRmktAds(),
- RATIO_OF_CAS_SELECTING_RMKT_ADS,
- 0.0f);
- assertEquals(
- argumentCaptor.getValue().getRunAdBiddingLatencyInMillis(),
- RUN_AD_BIDDING_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getRunAdBiddingResultCode(), RUN_AD_BIDDING_RESULT_CODE);
- assertEquals(
- argumentCaptor.getValue().getTotalAdBiddingStageLatencyInMillis(),
- TOTAL_AD_BIDDING_STAGE_LATENCY_IN_MILLIS);
+ RunAdBiddingProcessReportedStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getGetBuyersCustomAudienceLatencyInMills())
+ .isEqualTo(GET_BUYERS_CUSTOM_AUDIENCE_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getGetBuyersCustomAudienceResultCode())
+ .isEqualTo(GET_BUYERS_CUSTOM_AUDIENCE_RESULT_CODE);
+ expect.that(loggedStats.getNumBuyersRequested()).isEqualTo(NUM_BUYERS_REQUESTED);
+ expect.that(loggedStats.getNumBuyersFetched()).isEqualTo(NUM_BUYERS_FETCHED);
+ expect.that(loggedStats.getNumOfAdsEnteringBidding())
+ .isEqualTo(NUM_OF_ADS_ENTERING_BIDDING);
+ expect.that(loggedStats.getNumOfCasEnteringBidding())
+ .isEqualTo(NUM_OF_CAS_ENTERING_BIDDING);
+ expect.that(loggedStats.getNumOfCasPostBidding()).isEqualTo(NUM_OF_CAS_POSTING_BIDDING);
+ expect.that(loggedStats.getRatioOfCasSelectingRmktAds())
+ .isWithin(0.0f)
+ .of(RATIO_OF_CAS_SELECTING_RMKT_ADS);
+ expect.that(loggedStats.getRunAdBiddingLatencyInMillis())
+ .isEqualTo(RUN_AD_BIDDING_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getRunAdBiddingResultCode()).isEqualTo(RUN_AD_BIDDING_RESULT_CODE);
+ expect.that(loggedStats.getTotalAdBiddingStageLatencyInMillis())
+ .isEqualTo(TOTAL_AD_BIDDING_STAGE_LATENCY_IN_MILLIS);
}
@Test
@@ -332,44 +295,33 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor.forClass(RunAdBiddingPerCAProcessReportedStats.class);
verify(mStatsdLoggerMock)
.logRunAdBiddingPerCAProcessReportedStats(argumentCaptor.capture());
- assertEquals(argumentCaptor.getValue().getNumOfAdsForBidding(), NUM_OF_ADS_FOR_BIDDING);
- assertEquals(
- argumentCaptor.getValue().getRunAdBiddingPerCaLatencyInMillis(),
- RUN_AD_BIDDING_PER_CA_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getRunAdBiddingPerCaResultCode(),
- RUN_AD_BIDDING_PER_CA_RESULT_CODE);
- assertEquals(
- argumentCaptor.getValue().getGetBuyerDecisionLogicLatencyInMillis(),
- GET_BUYER_DECISION_LOGIC_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getGetBuyerDecisionLogicResultCode(),
- GET_BUYER_DECISION_LOGIC_RESULT_CODE);
- assertEquals(
- argumentCaptor.getValue().getBuyerDecisionLogicScriptType(),
- BUYER_DECISION_LOGIC_SCRIPT_TYPE);
- assertEquals(
- argumentCaptor.getValue().getFetchedBuyerDecisionLogicScriptSizeInBytes(),
- FETCHED_BUYER_DECISION_LOGIC_SCRIPT_SIZE_IN_BYTES);
- assertEquals(
- argumentCaptor.getValue().getNumOfKeysOfTrustedBiddingSignals(),
- NUM_OF_KEYS_OF_TRUSTED_BIDDING_SIGNALS);
- assertEquals(
- argumentCaptor.getValue().getFetchedTrustedBiddingSignalsDataSizeInBytes(),
- FETCHED_TRUSTED_BIDDING_SIGNALS_DATA_SIZE_IN_BYTES);
- assertEquals(
- argumentCaptor.getValue().getGetTrustedBiddingSignalsLatencyInMillis(),
- GET_TRUSTED_BIDDING_SIGNALS_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getGetTrustedBiddingSignalsResultCode(),
- GET_TRUSTED_BIDDING_SIGNALS_RESULT_CODE);
- assertEquals(
- argumentCaptor.getValue().getGenerateBidsLatencyInMillis(),
- GENERATE_BIDS_LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getRunBiddingLatencyInMillis(),
- RUN_BIDDING_LATENCY_IN_MILLIS);
- assertEquals(argumentCaptor.getValue().getRunBiddingResultCode(), RUN_BIDDING_RESULT_CODE);
+ RunAdBiddingPerCAProcessReportedStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getNumOfAdsForBidding()).isEqualTo(NUM_OF_ADS_FOR_BIDDING);
+ expect.that(loggedStats.getRunAdBiddingPerCaLatencyInMillis())
+ .isEqualTo(RUN_AD_BIDDING_PER_CA_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getRunAdBiddingPerCaResultCode())
+ .isEqualTo(RUN_AD_BIDDING_PER_CA_RESULT_CODE);
+ expect.that(loggedStats.getGetBuyerDecisionLogicLatencyInMillis())
+ .isEqualTo(GET_BUYER_DECISION_LOGIC_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getGetBuyerDecisionLogicResultCode())
+ .isEqualTo(GET_BUYER_DECISION_LOGIC_RESULT_CODE);
+ expect.that(loggedStats.getBuyerDecisionLogicScriptType())
+ .isEqualTo(BUYER_DECISION_LOGIC_SCRIPT_TYPE);
+ expect.that(loggedStats.getFetchedBuyerDecisionLogicScriptSizeInBytes())
+ .isEqualTo(FETCHED_BUYER_DECISION_LOGIC_SCRIPT_SIZE_IN_BYTES);
+ expect.that(loggedStats.getNumOfKeysOfTrustedBiddingSignals())
+ .isEqualTo(NUM_OF_KEYS_OF_TRUSTED_BIDDING_SIGNALS);
+ expect.that(loggedStats.getFetchedTrustedBiddingSignalsDataSizeInBytes())
+ .isEqualTo(FETCHED_TRUSTED_BIDDING_SIGNALS_DATA_SIZE_IN_BYTES);
+ expect.that(loggedStats.getGetTrustedBiddingSignalsLatencyInMillis())
+ .isEqualTo(GET_TRUSTED_BIDDING_SIGNALS_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getGetTrustedBiddingSignalsResultCode())
+ .isEqualTo(GET_TRUSTED_BIDDING_SIGNALS_RESULT_CODE);
+ expect.that(loggedStats.getGenerateBidsLatencyInMillis())
+ .isEqualTo(GENERATE_BIDS_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getRunBiddingLatencyInMillis())
+ .isEqualTo(RUN_BIDDING_LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getRunBiddingResultCode()).isEqualTo(RUN_BIDDING_RESULT_CODE);
}
@Test
@@ -386,11 +338,11 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<BackgroundFetchProcessReportedStats> argumentCaptor =
ArgumentCaptor.forClass(BackgroundFetchProcessReportedStats.class);
verify(mStatsdLoggerMock).logBackgroundFetchProcessReportedStats(argumentCaptor.capture());
- assertEquals(argumentCaptor.getValue().getLatencyInMillis(), LATENCY_IN_MILLIS);
- assertEquals(
- argumentCaptor.getValue().getNumOfEligibleToUpdateCas(),
- NUM_OF_ELIGIBLE_TO_UPDATE_CAS);
- assertEquals(argumentCaptor.getValue().getResultCode(), RESULT_CODE);
+ BackgroundFetchProcessReportedStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getLatencyInMillis()).isEqualTo(LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getNumOfEligibleToUpdateCas())
+ .isEqualTo(NUM_OF_ELIGIBLE_TO_UPDATE_CAS);
+ expect.that(loggedStats.getResultCode()).isEqualTo(RESULT_CODE);
}
@Test
@@ -408,11 +360,11 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor.forClass(UpdateCustomAudienceProcessReportedStats.class);
verify(mStatsdLoggerMock)
.logUpdateCustomAudienceProcessReportedStats(argumentCaptor.capture());
- assertEquals(argumentCaptor.getValue().getLatencyInMills(), LATENCY_IN_MILLIS);
- assertEquals(argumentCaptor.getValue().getResultCode(), RESULT_CODE);
- assertEquals(
- argumentCaptor.getValue().getDataSizeOfAdsInBytes(), DATA_SIZE_OF_ADS_IN_BYTES);
- assertEquals(argumentCaptor.getValue().getNumOfAds(), NUM_OF_ADS);
+ UpdateCustomAudienceProcessReportedStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getLatencyInMills()).isEqualTo(LATENCY_IN_MILLIS);
+ expect.that(loggedStats.getResultCode()).isEqualTo(RESULT_CODE);
+ expect.that(loggedStats.getDataSizeOfAdsInBytes()).isEqualTo(DATA_SIZE_OF_ADS_IN_BYTES);
+ expect.that(loggedStats.getNumOfAds()).isEqualTo(NUM_OF_ADS);
}
@Test
@@ -428,18 +380,18 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<MeasurementReportsStats> argumentCaptor =
ArgumentCaptor.forClass(MeasurementReportsStats.class);
verify(mStatsdLoggerMock).logMeasurementReports(argumentCaptor.capture());
- assertEquals(argumentCaptor.getValue().getCode(), AD_SERVICES_MESUREMENT_REPORTS_UPLOADED);
- assertEquals(
- argumentCaptor.getValue().getType(),
- AD_SERVICES_MEASUREMENT_REPORTS_UPLOADED__TYPE__EVENT);
- assertEquals(argumentCaptor.getValue().getResultCode(), STATUS_SUCCESS);
+ MeasurementReportsStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getCode()).isEqualTo(AD_SERVICES_MESUREMENT_REPORTS_UPLOADED);
+ expect.that(loggedStats.getType())
+ .isEqualTo(AD_SERVICES_MEASUREMENT_REPORTS_UPLOADED__TYPE__EVENT);
+ expect.that(loggedStats.getResultCode()).isEqualTo(STATUS_SUCCESS);
}
@Test
public void testLogApiCallStats() {
- final String packageName = "com.android.test";
- final String sdkName = "com.android.container";
- final int latency = 100;
+ String packageName = "com.android.test";
+ String sdkName = "com.android.container";
+ int latency = 100;
ApiCallStats stats =
new ApiCallStats.Builder()
.setCode(AD_SERVICES_API_CALLED)
@@ -454,17 +406,16 @@ public class AdServicesLoggerImplTest {
adServicesLogger.logApiCallStats(stats);
ArgumentCaptor<ApiCallStats> argumentCaptor = ArgumentCaptor.forClass(ApiCallStats.class);
verify(mStatsdLoggerMock).logApiCallStats(argumentCaptor.capture());
- assertEquals(argumentCaptor.getValue().getCode(), AD_SERVICES_API_CALLED);
- assertEquals(
- argumentCaptor.getValue().getApiClass(),
- AD_SERVICES_API_CALLED__API_CLASS__TARGETING);
- assertEquals(
- argumentCaptor.getValue().getApiName(),
- AD_SERVICES_API_CALLED__API_NAME__GET_TOPICS);
- assertEquals(argumentCaptor.getValue().getAppPackageName(), packageName);
- assertEquals(argumentCaptor.getValue().getSdkPackageName(), sdkName);
- assertEquals(argumentCaptor.getValue().getLatencyMillisecond(), latency);
- assertEquals(argumentCaptor.getValue().getResultCode(), STATUS_SUCCESS);
+ ApiCallStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getCode()).isEqualTo(AD_SERVICES_API_CALLED);
+ expect.that(loggedStats.getApiClass())
+ .isEqualTo(AD_SERVICES_API_CALLED__API_CLASS__TARGETING);
+ expect.that(loggedStats.getApiName())
+ .isEqualTo(AD_SERVICES_API_CALLED__API_NAME__GET_TOPICS);
+ expect.that(loggedStats.getAppPackageName()).isEqualTo(packageName);
+ expect.that(loggedStats.getSdkPackageName()).isEqualTo(sdkName);
+ expect.that(loggedStats.getLatencyMillisecond()).isEqualTo(latency);
+ expect.that(loggedStats.getResultCode()).isEqualTo(STATUS_SUCCESS);
}
@Test
@@ -479,18 +430,18 @@ public class AdServicesLoggerImplTest {
adServicesLogger.logUIStats(stats);
ArgumentCaptor<UIStats> argumentCaptor = ArgumentCaptor.forClass(UIStats.class);
verify(mStatsdLoggerMock).logUIStats(argumentCaptor.capture());
- assertEquals(argumentCaptor.getValue().getCode(), AD_SERVICES_SETTINGS_USAGE_REPORTED);
- assertEquals(
- argumentCaptor.getValue().getRegion(),
- AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__ROW);
- assertEquals(
- argumentCaptor.getValue().getAction(),
- AD_SERVICES_SETTINGS_USAGE_REPORTED__ACTION__OPT_OUT_SELECTED);
+ UIStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getCode()).isEqualTo(AD_SERVICES_SETTINGS_USAGE_REPORTED);
+ expect.that(loggedStats.getRegion())
+ .isEqualTo(AD_SERVICES_SETTINGS_USAGE_REPORTED__REGION__ROW);
+ expect.that(loggedStats.getAction())
+ .isEqualTo(AD_SERVICES_SETTINGS_USAGE_REPORTED__ACTION__OPT_OUT_SELECTED);
}
@Test
public void testLogMsmtDebugKeyMatchStats() {
- final String enrollmentId = "EnrollmentId";
+ String sourceRegistrant = "android-app://com.registrant";
+ String enrollmentId = "EnrollmentId";
long hashedValue = 5000L;
long hashLimit = 10000L;
MsmtDebugKeysMatchStats stats =
@@ -501,19 +452,20 @@ public class AdServicesLoggerImplTest {
AD_SERVICES_MEASUREMENT_DEBUG_KEYS__ATTRIBUTION_TYPE__APP_WEB)
.setDebugJoinKeyHashedValue(hashedValue)
.setDebugJoinKeyHashLimit(hashLimit)
- .setSourceRegistrant(SOURCE_REGISTRANT)
+ .setSourceRegistrant(sourceRegistrant)
.build();
AdServicesLoggerImpl adServicesLogger = new AdServicesLoggerImpl(mStatsdLoggerMock);
adServicesLogger.logMeasurementDebugKeysMatch(stats);
ArgumentCaptor<MsmtDebugKeysMatchStats> argumentCaptor =
ArgumentCaptor.forClass(MsmtDebugKeysMatchStats.class);
verify(mStatsdLoggerMock).logMeasurementDebugKeysMatch(argumentCaptor.capture());
- assertEquals(stats, argumentCaptor.getValue());
+ expect.that(stats).isEqualTo(argumentCaptor.getValue());
}
@Test
public void testLogMsmtAdIdMatchForDebugKeysStats() {
- final String enrollmentId = "enrollmentId";
+ String sourceRegistrant = "android-app://com.registrant";
+ String enrollmentId = "enrollmentId";
long uniqueAdIds = 2L;
long uniqueAdIdLimit = 5L;
MsmtAdIdMatchForDebugKeysStats stats =
@@ -524,7 +476,7 @@ public class AdServicesLoggerImplTest {
AD_SERVICES_MEASUREMENT_DEBUG_KEYS__ATTRIBUTION_TYPE__APP_WEB)
.setNumUniqueAdIds(uniqueAdIds)
.setNumUniqueAdIdsLimit(uniqueAdIdLimit)
- .setSourceRegistrant(SOURCE_REGISTRANT)
+ .setSourceRegistrant(sourceRegistrant)
.build();
AdServicesLoggerImpl adServicesLogger = new AdServicesLoggerImpl(mStatsdLoggerMock);
@@ -533,7 +485,7 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor.forClass(MsmtAdIdMatchForDebugKeysStats.class);
verify(mStatsdLoggerMock)
.logMeasurementAdIdMatchForDebugKeysStats(argumentCaptor.capture());
- assertEquals(stats, argumentCaptor.getValue());
+ expect.that(stats).isEqualTo(argumentCaptor.getValue());
}
@Test
@@ -554,22 +506,19 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<MeasurementAttributionStats> argumentCaptor =
ArgumentCaptor.forClass(MeasurementAttributionStats.class);
verify(mStatsdLoggerMock).logMeasurementAttributionStats(argumentCaptor.capture());
- assertEquals(argumentCaptor.getValue().getCode(), AD_SERVICES_MEASUREMENT_ATTRIBUTION);
- assertEquals(
- argumentCaptor.getValue().getSourceType(),
- AttributionStatus.SourceType.VIEW.getValue());
- assertEquals(
- argumentCaptor.getValue().getSurfaceType(),
- AttributionStatus.AttributionSurface.APP_WEB.getValue());
- assertEquals(
- argumentCaptor.getValue().getResult(),
- AttributionStatus.AttributionResult.SUCCESS.getValue());
- assertEquals(
- argumentCaptor.getValue().getFailureType(),
- AttributionStatus.FailureType.UNKNOWN.getValue());
- assertEquals(argumentCaptor.getValue().isSourceDerived(), false);
- assertEquals(argumentCaptor.getValue().isInstallAttribution(), true);
- assertEquals(argumentCaptor.getValue().getAttributionDelay(), 100L);
+ MeasurementAttributionStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getCode()).isEqualTo(AD_SERVICES_MEASUREMENT_ATTRIBUTION);
+ expect.that(loggedStats.getSourceType())
+ .isEqualTo(AttributionStatus.SourceType.VIEW.getValue());
+ expect.that(loggedStats.getSurfaceType())
+ .isEqualTo(AttributionStatus.AttributionSurface.APP_WEB.getValue());
+ expect.that(loggedStats.getResult())
+ .isEqualTo(AttributionStatus.AttributionResult.SUCCESS.getValue());
+ expect.that(loggedStats.getFailureType())
+ .isEqualTo(AttributionStatus.FailureType.UNKNOWN.getValue());
+ expect.that(loggedStats.isSourceDerived()).isFalse();
+ expect.that(loggedStats.isInstallAttribution()).isTrue();
+ expect.that(loggedStats.getAttributionDelay()).isEqualTo(100L);
}
@Test
@@ -585,10 +534,10 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<MeasurementWipeoutStats> argumentCaptor =
ArgumentCaptor.forClass(MeasurementWipeoutStats.class);
verify(mStatsdLoggerMock).logMeasurementWipeoutStats(argumentCaptor.capture());
- assertEquals(argumentCaptor.getValue().getCode(), AD_SERVICES_MEASUREMENT_WIPEOUT);
- assertEquals(
- argumentCaptor.getValue().getWipeoutType(),
- WipeoutStatus.WipeoutType.CONSENT_FLIP.ordinal());
+ MeasurementWipeoutStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getCode()).isEqualTo(AD_SERVICES_MEASUREMENT_WIPEOUT);
+ expect.that(loggedStats.getWipeoutType())
+ .isEqualTo(WipeoutStatus.WipeoutType.CONSENT_FLIP.ordinal());
}
@Test
@@ -608,11 +557,11 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor.forClass(MeasurementDelayedSourceRegistrationStats.class);
verify(mStatsdLoggerMock)
.logMeasurementDelayedSourceRegistrationStats(argumentCaptor.capture());
- assertEquals(
- argumentCaptor.getValue().getCode(),
- AD_SERVICES_MEASUREMENT_DELAYED_SOURCE_REGISTRATION);
- assertEquals(argumentCaptor.getValue().getRegistrationStatus(), UnknownEnumValue);
- assertEquals(argumentCaptor.getValue().getRegistrationDelay(), registrationDelay);
+ MeasurementDelayedSourceRegistrationStats loggedStats = argumentCaptor.getValue();
+ expect.that(loggedStats.getCode())
+ .isEqualTo(AD_SERVICES_MEASUREMENT_DELAYED_SOURCE_REGISTRATION);
+ expect.that(loggedStats.getRegistrationStatus()).isEqualTo(UnknownEnumValue);
+ expect.that(loggedStats.getRegistrationDelay()).isEqualTo(registrationDelay);
}
@Test
@@ -621,22 +570,21 @@ public class AdServicesLoggerImplTest {
EnrollmentStatus.TransactionType.READ_TRANSACTION_TYPE.ordinal();
AdServicesLoggerImpl adServicesLogger = new AdServicesLoggerImpl(mStatsdLoggerMock);
adServicesLogger.logEnrollmentDataStats(transactionTypeEnumValue, true, 100);
- verify(mStatsdLoggerMock)
- .logEnrollmentDataStats(eq(transactionTypeEnumValue), eq(true), eq(100));
+ verify(mStatsdLoggerMock).logEnrollmentDataStats(transactionTypeEnumValue, true, 100);
}
@Test
public void testLogEnrollmentMatchStats() {
AdServicesLoggerImpl adServicesLogger = new AdServicesLoggerImpl(mStatsdLoggerMock);
adServicesLogger.logEnrollmentMatchStats(true, 100);
- verify(mStatsdLoggerMock).logEnrollmentMatchStats(eq(true), eq(100));
+ verify(mStatsdLoggerMock).logEnrollmentMatchStats(true, 100);
}
@Test
public void testLogEnrollmentFileDownloadStats() {
AdServicesLoggerImpl adServicesLogger = new AdServicesLoggerImpl(mStatsdLoggerMock);
adServicesLogger.logEnrollmentFileDownloadStats(true, 100);
- verify(mStatsdLoggerMock).logEnrollmentFileDownloadStats(eq(true), eq(100));
+ verify(mStatsdLoggerMock).logEnrollmentFileDownloadStats(true, 100);
}
@Test
@@ -650,11 +598,7 @@ public class AdServicesLoggerImplTest {
100, dataFileGroupStatusEnumValue, 10, "SomeSdkName", errorCauseEnumValue);
verify(mStatsdLoggerMock)
.logEnrollmentFailedStats(
- eq(100),
- eq(dataFileGroupStatusEnumValue),
- eq(10),
- eq("SomeSdkName"),
- eq(errorCauseEnumValue));
+ 100, dataFileGroupStatusEnumValue, 10, "SomeSdkName", errorCauseEnumValue);
}
@Test
@@ -683,14 +627,14 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<MeasurementClickVerificationStats> argumentCaptor =
ArgumentCaptor.forClass(MeasurementClickVerificationStats.class);
verify(mStatsdLoggerMock).logMeasurementClickVerificationStats(argumentCaptor.capture());
- assertEquals(stats, argumentCaptor.getValue());
+ expect.that(stats).isEqualTo(argumentCaptor.getValue());
}
@Test
public void testLogEncryptionKeyFetchedStats() {
- final String enrollmentId = "enrollmentId";
- final String companyId = "companyId";
- final String encryptionKeyUrl = "https://www.adtech1.com/.well-known/encryption-keys";
+ String enrollmentId = "enrollmentId";
+ String companyId = "companyId";
+ String encryptionKeyUrl = "https://www.adtech1.com/.well-known/encryption-keys";
AdServicesEncryptionKeyFetchedStats stats =
AdServicesEncryptionKeyFetchedStats.builder()
@@ -708,7 +652,7 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<AdServicesEncryptionKeyFetchedStats> argumentCaptor =
ArgumentCaptor.forClass(AdServicesEncryptionKeyFetchedStats.class);
verify(mStatsdLoggerMock).logEncryptionKeyFetchedStats(argumentCaptor.capture());
- assertEquals(stats, argumentCaptor.getValue());
+ expect.that(stats).isEqualTo(argumentCaptor.getValue());
}
@Test
@@ -726,7 +670,7 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<AdServicesEncryptionKeyDbTransactionEndedStats> argumentCaptor =
ArgumentCaptor.forClass(AdServicesEncryptionKeyDbTransactionEndedStats.class);
verify(mStatsdLoggerMock).logEncryptionKeyDbTransactionEndedStats(argumentCaptor.capture());
- assertEquals(stats, argumentCaptor.getValue());
+ expect.that(stats).isEqualTo(argumentCaptor.getValue());
}
@Test
@@ -760,7 +704,7 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor.forClass(DestinationRegisteredBeaconsReportedStats.class);
verify(mStatsdLoggerMock).logDestinationRegisteredBeaconsReportedStats(
argumentCaptor.capture());
- assertEquals(stats, argumentCaptor.getValue());
+ expect.that(stats).isEqualTo(argumentCaptor.getValue());
}
@Test
@@ -778,7 +722,7 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor<ReportInteractionApiCalledStats> argumentCaptor =
ArgumentCaptor.forClass(ReportInteractionApiCalledStats.class);
verify(mStatsdLoggerMock).logReportInteractionApiCalledStats(argumentCaptor.capture());
- assertEquals(stats, argumentCaptor.getValue());
+ expect.that(stats).isEqualTo(argumentCaptor.getValue());
}
@Test
@@ -796,6 +740,6 @@ public class AdServicesLoggerImplTest {
ArgumentCaptor.forClass(InteractionReportingTableClearedStats.class);
verify(mStatsdLoggerMock).logInteractionReportingTableClearedStats(
argumentCaptor.capture());
- assertEquals(stats, argumentCaptor.getValue());
+ expect.that(stats).isEqualTo(argumentCaptor.getValue());
}
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/StatsdAdServicesLoggerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/StatsdAdServicesLoggerTest.java
index 50dfe87be..8ef66086b 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/StatsdAdServicesLoggerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/stats/StatsdAdServicesLoggerTest.java
@@ -16,6 +16,7 @@
package com.android.adservices.service.stats;
+import static com.android.adservices.mockito.ExtendedMockitoExpectations.mockIsAtLeastT;
import static com.android.adservices.service.stats.AdServicesEncryptionKeyDbTransactionEndedStats.DbTransactionStatus.INSERT_EXCEPTION;
import static com.android.adservices.service.stats.AdServicesEncryptionKeyDbTransactionEndedStats.DbTransactionType.WRITE_TRANSACTION_TYPE;
import static com.android.adservices.service.stats.AdServicesEncryptionKeyDbTransactionEndedStats.MethodName.INSERT_KEY;
@@ -36,18 +37,18 @@ import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICE
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_MEASUREMENT_WIPEOUT;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_MEASUREMENT_CLICK_VERIFICATION;
import static com.android.adservices.service.stats.AdServicesStatsLog.DESTINATION_REGISTERED_BEACONS;
-import static com.android.adservices.service.stats.AdServicesStatsLog.DESTINATION_REGISTERED_BEACONS__DESTINATION__SELLER_DESTINATION;
import static com.android.adservices.service.stats.AdServicesStatsLog.INTERACTION_REPORTING_TABLE_CLEARED;
import static com.android.adservices.service.stats.AdServicesStatsLog.REPORT_INTERACTION_API_CALLED;
import static com.android.adservices.service.stats.EpochComputationClassifierStats.ClassifierType;
import static com.android.adservices.service.stats.EpochComputationClassifierStats.OnDeviceClassifierStatus;
import static com.android.adservices.service.stats.EpochComputationClassifierStats.PrecomputedClassifierStatus;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.staticMockMarker;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyIterable;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -57,28 +58,29 @@ import static org.mockito.Mockito.when;
import android.adservices.adselection.ReportEventRequest;
+import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
import com.android.adservices.service.Flags;
import com.android.adservices.service.enrollment.EnrollmentStatus;
import com.android.adservices.service.measurement.Source;
import com.android.adservices.service.measurement.WipeoutStatus;
import com.android.adservices.service.measurement.attribution.AttributionStatus;
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.dx.mockito.inline.extended.MockedVoidMethod;
import com.android.modules.utils.build.SdkLevel;
+import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic;
import com.google.common.collect.ImmutableList;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
import java.util.Arrays;
import java.util.List;
-public class StatsdAdServicesLoggerTest {
+@SpyStatic(SdkLevel.class)
+@SpyStatic(AdServicesStatsLog.class)
+public final class StatsdAdServicesLoggerTest extends AdServicesExtendedMockitoTestCase {
+
// Atom IDs
private static final int TOPICS_REPORTED_ATOM_ID = 535;
private static final int EPOCH_COMPUTATION_CLASSIFIER_ATOM_ID = 537;
@@ -119,39 +121,25 @@ public class StatsdAdServicesLoggerTest {
private static final int SELLER_DESTINATION =
ReportEventRequest.FLAG_REPORTING_DESTINATION_SELLER;
- private MockitoSession mMockitoSession;
private StatsdAdServicesLogger mLogger;
@Mock private Flags mFlags;
@Before
public void setUp() {
- mMockitoSession =
- ExtendedMockito.mockitoSession()
- .mockStatic(SdkLevel.class)
- .mockStatic(AdServicesStatsLog.class)
- .strictness(Strictness.LENIENT)
- .initMocks(this)
- .startMocking();
-
mLogger = new StatsdAdServicesLogger(mFlags);
}
- @After
- public void tearDown() {
- mMockitoSession.finishMocking();
- }
-
@Test
public void testLogGetTopicsReportedStats_tPlus() {
// Mocks
when(mFlags.getCompatLoggingKillSwitch()).thenReturn(false);
- ExtendedMockito.doReturn(true).when(SdkLevel::isAtLeastT);
- ExtendedMockito.doNothing()
+ mockIsAtLeastT(true);
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
anyInt(), anyInt(), anyInt(), anyInt(), any(byte[].class)));
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -161,7 +149,7 @@ public class StatsdAdServicesLoggerTest {
mLogger.logGetTopicsReportedStats(TOPICS_REPORTED_STATS_DATA);
// Verify compat logging
- ExtendedMockito.verify(
+ verify(
() ->
AdServicesStatsLog.write(
eq(TOPICS_REPORTED_COMPAT_ATOM_ID),
@@ -170,7 +158,7 @@ public class StatsdAdServicesLoggerTest {
eq(TOPIC_IDS_COUNT),
any(byte[].class)));
// Verify T+ logging
- ExtendedMockito.verify(
+ verify(
() ->
AdServicesStatsLog.write(
TOPICS_REPORTED_ATOM_ID,
@@ -186,8 +174,8 @@ public class StatsdAdServicesLoggerTest {
public void testLogGetTopicsReportedStats_tPlus_noCompatLoggingDueToKillSwitch() {
// Mocks
when(mFlags.getCompatLoggingKillSwitch()).thenReturn(true);
- ExtendedMockito.doReturn(true).when(SdkLevel::isAtLeastT);
- ExtendedMockito.doNothing()
+ mockIsAtLeastT(true);
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -197,7 +185,7 @@ public class StatsdAdServicesLoggerTest {
mLogger.logGetTopicsReportedStats(TOPICS_REPORTED_STATS_DATA);
// Verify T+ logging only
- ExtendedMockito.verify(
+ verify(
() ->
AdServicesStatsLog.write(
TOPICS_REPORTED_ATOM_ID,
@@ -213,8 +201,8 @@ public class StatsdAdServicesLoggerTest {
public void testLogGetTopicsReportedStats_sMinus() {
// Mocks
when(mFlags.getCompatLoggingKillSwitch()).thenReturn(false);
- ExtendedMockito.doReturn(false).when(SdkLevel::isAtLeastT);
- ExtendedMockito.doNothing()
+ mockIsAtLeastT(false);
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -224,7 +212,7 @@ public class StatsdAdServicesLoggerTest {
mLogger.logGetTopicsReportedStats(TOPICS_REPORTED_STATS_DATA);
// Verify only compat logging took place
- ExtendedMockito.verify(
+ verify(
() ->
AdServicesStatsLog.write(
eq(TOPICS_REPORTED_COMPAT_ATOM_ID),
@@ -240,7 +228,7 @@ public class StatsdAdServicesLoggerTest {
public void testLogGetTopicsReportedStats_sMinus_noLoggingDueToKillSwitch() {
// Mocks
when(mFlags.getCompatLoggingKillSwitch()).thenReturn(true);
- ExtendedMockito.doReturn(false).when(SdkLevel::isAtLeastT);
+ mockIsAtLeastT(false);
// Invoke logging call
mLogger.logGetTopicsReportedStats(TOPICS_REPORTED_STATS_DATA);
@@ -253,8 +241,8 @@ public class StatsdAdServicesLoggerTest {
public void testLogEpochComputationClassifierStats_tPlus() {
// Mocks
when(mFlags.getCompatLoggingKillSwitch()).thenReturn(false);
- ExtendedMockito.doReturn(true).when(SdkLevel::isAtLeastT);
- ExtendedMockito.doNothing()
+ mockIsAtLeastT(true);
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -265,7 +253,7 @@ public class StatsdAdServicesLoggerTest {
anyInt(),
anyInt(),
anyInt()));
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -281,7 +269,7 @@ public class StatsdAdServicesLoggerTest {
mLogger.logEpochComputationClassifierStats(EPOCH_COMPUTATION_CLASSIFIER_STATS_DATA);
// Verify compat logging
- ExtendedMockito.verify(
+ verify(
() ->
AdServicesStatsLog.write(
eq(EPOCH_COMPUTATION_CLASSIFIER_COMPAT_ATOM_ID),
@@ -297,7 +285,7 @@ public class StatsdAdServicesLoggerTest {
.PRECOMPUTED_CLASSIFIER_STATUS_NOT_INVOKED
.getCompatLoggingValue())));
// Verify T+ logging
- ExtendedMockito.verify(
+ verify(
() ->
AdServicesStatsLog.write(
EPOCH_COMPUTATION_CLASSIFIER_ATOM_ID,
@@ -318,8 +306,8 @@ public class StatsdAdServicesLoggerTest {
public void testLogEpochComputationClassifierStats_tPlus_noCompatLoggingDueToKillSwitch() {
// Mocks
when(mFlags.getCompatLoggingKillSwitch()).thenReturn(true);
- ExtendedMockito.doReturn(true).when(SdkLevel::isAtLeastT);
- ExtendedMockito.doNothing()
+ mockIsAtLeastT(true);
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -335,7 +323,7 @@ public class StatsdAdServicesLoggerTest {
mLogger.logEpochComputationClassifierStats(EPOCH_COMPUTATION_CLASSIFIER_STATS_DATA);
// Verify T+ logging
- ExtendedMockito.verify(
+ verify(
() ->
AdServicesStatsLog.write(
EPOCH_COMPUTATION_CLASSIFIER_ATOM_ID,
@@ -356,8 +344,8 @@ public class StatsdAdServicesLoggerTest {
public void testLogEpochComputationClassifierStats_sMinus() {
// Mocks
when(mFlags.getCompatLoggingKillSwitch()).thenReturn(false);
- ExtendedMockito.doReturn(false).when(SdkLevel::isAtLeastT);
- ExtendedMockito.doNothing()
+ mockIsAtLeastT(false);
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -373,7 +361,7 @@ public class StatsdAdServicesLoggerTest {
mLogger.logEpochComputationClassifierStats(EPOCH_COMPUTATION_CLASSIFIER_STATS_DATA);
// Verify only compat logging took place
- ExtendedMockito.verify(
+ verify(
() ->
AdServicesStatsLog.write(
eq(EPOCH_COMPUTATION_CLASSIFIER_COMPAT_ATOM_ID),
@@ -396,7 +384,7 @@ public class StatsdAdServicesLoggerTest {
public void testLogEpochComputationClassifierStats_sMinus_noLoggingDueToKillSwitch() {
// Mocks
when(mFlags.getCompatLoggingKillSwitch()).thenReturn(true);
- ExtendedMockito.doReturn(false).when(SdkLevel::isAtLeastT);
+ mockIsAtLeastT(false);
// Invoke logging call
mLogger.logEpochComputationClassifierStats(EPOCH_COMPUTATION_CLASSIFIER_STATS_DATA);
@@ -409,7 +397,7 @@ public class StatsdAdServicesLoggerTest {
public void logMeasurementDebugKeysMatch_success() {
when(mFlags.getMeasurementEnableAppPackageNameLogging()).thenReturn(true);
when(mFlags.getMeasurementAppPackageNameLoggingAllowlist()).thenReturn(SOURCE_REGISTRANT);
- final String enrollmentId = "EnrollmentId";
+ String enrollmentId = "EnrollmentId";
long hashedValue = 5000L;
long hashLimit = 10000L;
int attributionType = AD_SERVICES_MEASUREMENT_DEBUG_KEYS__ATTRIBUTION_TYPE__APP_WEB;
@@ -422,7 +410,7 @@ public class StatsdAdServicesLoggerTest {
.setDebugJoinKeyHashLimit(hashLimit)
.setSourceRegistrant(SOURCE_REGISTRANT)
.build();
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -449,7 +437,7 @@ public class StatsdAdServicesLoggerTest {
eq(hashedValue),
eq(hashLimit),
eq(SOURCE_REGISTRANT));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -474,7 +462,7 @@ public class StatsdAdServicesLoggerTest {
.setEventReportCount(3)
.setEventDebugReportCount(1)
.build();
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -515,7 +503,7 @@ public class StatsdAdServicesLoggerTest {
eq(1),
eq(0));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -530,8 +518,7 @@ public class StatsdAdServicesLoggerTest {
.setWipeoutType(WipeoutStatus.WipeoutType.CONSENT_FLIP.ordinal())
.setSourceRegistrant(SOURCE_REGISTRANT)
.build();
- ExtendedMockito.doNothing()
- .when(() -> AdServicesStatsLog.write(anyInt(), anyInt(), anyString()));
+ doNothing().when(() -> AdServicesStatsLog.write(anyInt(), anyInt(), anyString()));
// Invoke logging call
mLogger.logMeasurementWipeoutStats(stats);
@@ -544,7 +531,7 @@ public class StatsdAdServicesLoggerTest {
eq(WipeoutStatus.WipeoutType.CONSENT_FLIP.ordinal()),
eq(SOURCE_REGISTRANT));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -562,7 +549,7 @@ public class StatsdAdServicesLoggerTest {
.setRegistrationDelay(registrationDelay)
.setRegistrant(SOURCE_REGISTRANT)
.build();
- ExtendedMockito.doNothing()
+ doNothing()
.when(() -> AdServicesStatsLog.write(anyInt(), anyInt(), anyLong(), anyString()));
// Invoke logging call
@@ -577,7 +564,7 @@ public class StatsdAdServicesLoggerTest {
eq(registrationDelay),
eq(SOURCE_REGISTRANT));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -585,7 +572,7 @@ public class StatsdAdServicesLoggerTest {
@Test
public void logConsentMigrationStats_success() {
when(mFlags.getAdservicesConsentMigrationLoggingEnabled()).thenReturn(true);
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -627,7 +614,7 @@ public class StatsdAdServicesLoggerTest {
eq(2),
eq(2),
eq(2));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -660,7 +647,7 @@ public class StatsdAdServicesLoggerTest {
public void logMeasurementAdIdMatchForDebugKeys_success() {
when(mFlags.getMeasurementEnableAppPackageNameLogging()).thenReturn(true);
when(mFlags.getMeasurementAppPackageNameLoggingAllowlist()).thenReturn(SOURCE_REGISTRANT);
- final String enrollmentId = "EnrollmentId";
+ String enrollmentId = "EnrollmentId";
long uniqueAdIdValue = 1L;
long uniqueAdIdLimit = 5L;
int attributionType = AD_SERVICES_MEASUREMENT_DEBUG_KEYS__ATTRIBUTION_TYPE__APP_WEB;
@@ -673,7 +660,7 @@ public class StatsdAdServicesLoggerTest {
.setNumUniqueAdIdsLimit(uniqueAdIdLimit)
.setSourceRegistrant(SOURCE_REGISTRANT)
.build();
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -700,7 +687,7 @@ public class StatsdAdServicesLoggerTest {
eq(uniqueAdIdLimit),
eq(SOURCE_REGISTRANT));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -708,7 +695,7 @@ public class StatsdAdServicesLoggerTest {
@Test
public void logMeasurementAdIdMatchForDebugKeys_appLoggingDisabled_emptyString() {
when(mFlags.getMeasurementEnableAppPackageNameLogging()).thenReturn(false);
- final String enrollmentId = "EnrollmentId";
+ String enrollmentId = "EnrollmentId";
long uniqueAdIdValue = 1L;
long uniqueAdIdLimit = 5L;
int attributionType = AD_SERVICES_MEASUREMENT_DEBUG_KEYS__ATTRIBUTION_TYPE__APP_WEB;
@@ -721,7 +708,7 @@ public class StatsdAdServicesLoggerTest {
.setNumUniqueAdIdsLimit(uniqueAdIdLimit)
.setSourceRegistrant(SOURCE_REGISTRANT)
.build();
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -748,7 +735,7 @@ public class StatsdAdServicesLoggerTest {
eq(uniqueAdIdLimit),
eq(""));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -757,7 +744,7 @@ public class StatsdAdServicesLoggerTest {
public void logMeasurementAdIdMatchForDebugKeys_appNotAllowlisted_emptyString() {
when(mFlags.getMeasurementEnableAppPackageNameLogging()).thenReturn(true);
when(mFlags.getMeasurementAppPackageNameLoggingAllowlist()).thenReturn("");
- final String enrollmentId = "EnrollmentId";
+ String enrollmentId = "EnrollmentId";
long uniqueAdIdValue = 1L;
long uniqueAdIdLimit = 5L;
int attributionType = AD_SERVICES_MEASUREMENT_DEBUG_KEYS__ATTRIBUTION_TYPE__APP_WEB;
@@ -770,7 +757,7 @@ public class StatsdAdServicesLoggerTest {
.setNumUniqueAdIdsLimit(uniqueAdIdLimit)
.setSourceRegistrant(SOURCE_REGISTRANT)
.build();
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -797,7 +784,7 @@ public class StatsdAdServicesLoggerTest {
eq(uniqueAdIdLimit),
eq(""));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -806,7 +793,7 @@ public class StatsdAdServicesLoggerTest {
public void logEnrollmentData_success() {
int transactionTypeEnumValue =
EnrollmentStatus.TransactionType.WRITE_TRANSACTION_TYPE.ordinal();
- ExtendedMockito.doNothing()
+ doNothing()
.when(() -> AdServicesStatsLog.write(anyInt(), anyInt(), anyBoolean(), anyInt()));
// Invoke logging call
@@ -821,15 +808,14 @@ public class StatsdAdServicesLoggerTest {
eq(true),
eq(100));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@Test
public void logEnrollmentMatch_success() {
- ExtendedMockito.doNothing()
- .when(() -> AdServicesStatsLog.write(anyInt(), anyBoolean(), anyInt()));
+ doNothing().when(() -> AdServicesStatsLog.write(anyInt(), anyBoolean(), anyInt()));
// Invoke logging call
mLogger.logEnrollmentMatchStats(true, 100);
@@ -840,15 +826,14 @@ public class StatsdAdServicesLoggerTest {
AdServicesStatsLog.write(
eq(AD_SERVICES_ENROLLMENT_MATCHED), eq(true), eq(100));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@Test
public void logEnrollmentFileDownload_success() {
- ExtendedMockito.doNothing()
- .when(() -> AdServicesStatsLog.write(anyInt(), anyBoolean(), anyInt()));
+ doNothing().when(() -> AdServicesStatsLog.write(anyInt(), anyBoolean(), anyInt()));
// Invoke logging call
mLogger.logEnrollmentFileDownloadStats(true, 100);
@@ -859,7 +844,7 @@ public class StatsdAdServicesLoggerTest {
AdServicesStatsLog.write(
eq(AD_SERVICES_ENROLLMENT_FILE_DOWNLOADED), eq(true), eq(100));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -870,7 +855,7 @@ public class StatsdAdServicesLoggerTest {
EnrollmentStatus.DataFileGroupStatus.PENDING_CUSTOM_VALIDATION.ordinal();
int errorCauseEnumValue =
EnrollmentStatus.ErrorCause.ENROLLMENT_BLOCKLISTED_ERROR_CAUSE.ordinal();
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -896,7 +881,7 @@ public class StatsdAdServicesLoggerTest {
eq("SomeSdkName"),
eq(errorCauseEnumValue));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -922,7 +907,7 @@ public class StatsdAdServicesLoggerTest {
.setSourceRegistrant(sourceRegistrant)
.build();
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -951,16 +936,16 @@ public class StatsdAdServicesLoggerTest {
eq(validDelayWindowMs),
eq("")); // App package name not in allow list.
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@Test
public void logEncryptionKeyFetchedStats_success() {
- final String enrollmentId = "enrollmentId";
- final String companyId = "companyId";
- final String encryptionKeyUrl = "https://www.adtech1.com/.well-known/encryption-keys";
+ String enrollmentId = "enrollmentId";
+ String companyId = "companyId";
+ String encryptionKeyUrl = "https://www.adtech1.com/.well-known/encryption-keys";
AdServicesEncryptionKeyFetchedStats stats =
AdServicesEncryptionKeyFetchedStats.builder()
@@ -972,7 +957,7 @@ public class StatsdAdServicesLoggerTest {
.setEncryptionKeyUrl(encryptionKeyUrl)
.build();
- ExtendedMockito.doNothing()
+ doNothing()
.when(
() ->
AdServicesStatsLog.write(
@@ -999,7 +984,7 @@ public class StatsdAdServicesLoggerTest {
eq(companyId),
eq(encryptionKeyUrl));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -1013,8 +998,7 @@ public class StatsdAdServicesLoggerTest {
.setMethodName(INSERT_KEY)
.build();
- ExtendedMockito.doNothing()
- .when(() -> AdServicesStatsLog.write(anyInt(), anyInt(), anyInt(), anyInt()));
+ doNothing().when(() -> AdServicesStatsLog.write(anyInt(), anyInt(), anyInt(), anyInt()));
// Invoke logging call.
mLogger.logEncryptionKeyDbTransactionEndedStats(stats);
@@ -1028,7 +1012,7 @@ public class StatsdAdServicesLoggerTest {
eq(INSERT_EXCEPTION.getValue()),
eq(INSERT_KEY.getValue()));
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -1060,9 +1044,11 @@ public class StatsdAdServicesLoggerTest {
.setAdServicesStatusCode(0)
.build();
- ExtendedMockito.doNothing()
- .when(() -> AdServicesStatsLog.write(
- anyInt(), anyInt(), anyInt(), any(), anyInt(), anyInt()));
+ doNothing()
+ .when(
+ () ->
+ AdServicesStatsLog.write(
+ anyInt(), anyInt(), anyInt(), any(), anyInt(), anyInt()));
// Invoke logging call.
mLogger.logDestinationRegisteredBeaconsReportedStats(stats);
@@ -1079,7 +1065,7 @@ public class StatsdAdServicesLoggerTest {
eq(/* adServicesStatusCode */ 0)
);
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -1092,9 +1078,7 @@ public class StatsdAdServicesLoggerTest {
.setNumMatchingUris(5)
.build();
- ExtendedMockito.doNothing()
- .when(() -> AdServicesStatsLog.write(
- anyInt(), anyInt(), anyInt()));
+ doNothing().when(() -> AdServicesStatsLog.write(anyInt(), anyInt(), anyInt()));
// Invoke logging call.
mLogger.logReportInteractionApiCalledStats(stats);
@@ -1108,7 +1092,7 @@ public class StatsdAdServicesLoggerTest {
eq(/* numMatchingUris */ 5)
);
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
@@ -1121,9 +1105,7 @@ public class StatsdAdServicesLoggerTest {
.setNumUnreportedUris(5)
.build();
- ExtendedMockito.doNothing()
- .when(() -> AdServicesStatsLog.write(
- anyInt(), anyInt(), anyInt()));
+ doNothing().when(() -> AdServicesStatsLog.write(anyInt(), anyInt(), anyInt()));
// Invoke logging call.
mLogger.logInteractionReportingTableClearedStats(stats);
@@ -1137,7 +1119,7 @@ public class StatsdAdServicesLoggerTest {
eq(/* numUnreportedUris */ 5)
);
- ExtendedMockito.verify(writeInvocation);
+ verify(writeInvocation);
verifyNoMoreInteractions(staticMockMarker(AdServicesStatsLog.class));
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/EncryptionManagerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/EncryptionManagerTest.java
index 23b349405..afc827a75 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/EncryptionManagerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/EncryptionManagerTest.java
@@ -127,6 +127,7 @@ public final class EncryptionManagerTest {
when(mFlags.getEnableDatabaseSchemaVersion9()).thenReturn(true);
when(mFlags.getTopicsEncryptionEnabled()).thenReturn(true);
+ when(mFlags.getTopicsTestEncryptionPublicKey()).thenReturn("");
}
@Test
@@ -184,6 +185,23 @@ public final class EncryptionManagerTest {
}
@Test
+ public void testEncryption_useTestingKeys() {
+ String overrideTestKey = "YVfr8K7rpuv45LtaCv9L1eIGxBv/UK22WugJBjg53fo";
+ when(mFlags.getTopicsTestEncryptionPublicKey()).thenReturn(overrideTestKey);
+ Topic topic = Topic.create(/* topic */ 5, /* taxonomyVersion */ 6L, /* modelVersion */ 7L);
+
+ Optional<EncryptedTopic> optionalEncryptedTopic =
+ mEncryptionManager.encryptTopic(topic, SDK_NAME);
+
+ // Verify EncryptedTopic is not empty.
+ assertThat(optionalEncryptedTopic.isPresent()).isTrue();
+ assertThat(optionalEncryptedTopic.get().getEncryptedTopic()).isNotEmpty();
+ // Verify test key used to override has been used.
+ assertThat(optionalEncryptedTopic.get().getKeyIdentifier()).isEqualTo(overrideTestKey);
+ assertThat(optionalEncryptedTopic.get().getEncapsulatedKey()).isNotEmpty();
+ }
+
+ @Test
public void testEncryption_missingKeys() {
doNothingOnErrorLogUtilError();
when(mEnrollmentDao.getEnrollmentDataFromSdkName(SDK_NAME)).thenReturn(ENROLLMENT_DATA);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/TopicsServiceImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/TopicsServiceImplTest.java
index fbd5fb26d..16f20a54e 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/TopicsServiceImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/TopicsServiceImplTest.java
@@ -32,6 +32,7 @@ import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICE
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__GET_TOPICS;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__GET_TOPICS_PREVIEW_API;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PACKAGE_NAME_NOT_FOUND_EXCEPTION;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__TOPICS_REQUEST_EMPTY_SDK_NAME;
import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__TOPICS;
import static com.google.common.truth.Truth.assertThat;
@@ -287,6 +288,7 @@ public final class TopicsServiceImplTest extends AdServicesExtendedMockitoTestCa
}
@Test
public void checkEmptySdkNameRequests() throws Exception {
+ ExtendedMockito.doNothing().when(() -> ErrorLogUtil.e(anyInt(), anyInt()));
mockGetTopicsDisableDirectAppCalls(true);
GetTopicsParam request =
@@ -297,6 +299,12 @@ public final class TopicsServiceImplTest extends AdServicesExtendedMockitoTestCa
.build();
invokeGetTopicsAndVerifyError(mSpyContext, STATUS_INVALID_ARGUMENT, request, false);
+ ExtendedMockito.verify(
+ () ->
+ ErrorLogUtil.e(
+ eq(
+ AD_SERVICES_ERROR_REPORTED__ERROR_CODE__TOPICS_REQUEST_EMPTY_SDK_NAME),
+ eq(AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__TOPICS)));
}
@Test
diff --git a/adservices/tests/unittest/system-service/src/com/android/server/adservices/AdServicesShellCommandTest.java b/adservices/tests/unittest/system-service/src/com/android/server/adservices/AdServicesShellCommandTest.java
index 779358be3..ca52afb01 100644
--- a/adservices/tests/unittest/system-service/src/com/android/server/adservices/AdServicesShellCommandTest.java
+++ b/adservices/tests/unittest/system-service/src/com/android/server/adservices/AdServicesShellCommandTest.java
@@ -18,10 +18,19 @@ package com.android.server.adservices;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
+import android.adservices.shell.IShellCommand;
+import android.adservices.shell.IShellCommandCallback;
+import android.adservices.shell.ShellCommandResult;
+import android.content.Context;
import android.os.Process;
+import android.os.RemoteException;
+import com.android.adservices.common.AdServicesMockitoTestCase;
import com.android.server.adservices.AdServicesShellCommand.Injector;
import com.google.common.truth.Expect;
@@ -31,18 +40,15 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
-public final class AdServicesShellCommandTest {
+public final class AdServicesShellCommandTest extends AdServicesMockitoTestCase {
private static final String[] ALL_COMMANDS = new String[] {"help", "is-system-service-enabled"};
- @Rule public final MockitoRule rule = MockitoJUnit.rule();
@Rule public final Expect expect = Expect.create();
private final StringWriter mOutStringWriter = new StringWriter();
@@ -52,20 +58,30 @@ public final class AdServicesShellCommandTest {
private final PrintWriter mErr = new PrintWriter(mErrStringWriter);
@Mock private Flags mFlags;
+ @Mock private Context mContext;
+
+ @Mock private IShellCommand mIShellCommand;
private AdServicesShellCommand mShellCmd;
+ private Injector mInjector;
+
@Before
public void setFixtures() {
+ mInjector =
+ new Injector() {
+ @Override
+ int getCallingUid() {
+ return Process.SHELL_UID;
+ }
+
+ @Override
+ IShellCommand getShellCommandService(Context context) {
+ return mIShellCommand;
+ }
+ };
mShellCmd =
- new AdServicesShellCommand(
- new Injector() {
- @Override
- int getCallingUid() {
- return Process.SHELL_UID;
- }
- },
- mFlags) {
+ new AdServicesShellCommand(mInjector, mFlags, mContext) {
@Override
public PrintWriter getOutPrintWriter() {
return mOut;
@@ -108,7 +124,8 @@ public final class AdServicesShellCommandTest {
return 42;
}
},
- mFlags)
+ mFlags,
+ mContext)
.onCommand("D'OH"));
assertThat(e)
.hasMessageThat()
@@ -152,14 +169,60 @@ public final class AdServicesShellCommandTest {
}
@Test
- public void testExec_invalidCommand() {
- int result = runCmd("D'OH!");
- expect.withMessage("result").that(result).isEqualTo(-1);
+ public void testExec_invalidCommand() throws Exception {
+ String cmd = "D'OH!";
+ ShellCommandResult responseInvalidShellCommand =
+ new ShellCommandResult.Builder()
+ .setErr(String.format("Unsupported command: %s", cmd))
+ .setResultCode(-1)
+ .build();
+ mockRunShellCommand(responseInvalidShellCommand);
+ int result = runCmd(cmd);
+
+ expect.withMessage("result").that(result).isEqualTo(-1);
expect.withMessage("out").that(getOut()).isEmpty();
String err = getErr();
expectHelpOutputHasAllCommands(err);
- expectHelpOutputHasMessages(err, "D'OH!");
+ expectHelpOutputHasMessages(err, cmd);
+ }
+
+ @Test
+ public void testExec_validAdServicesShellCommand() throws Exception {
+ String cmd = "echo";
+ ShellCommandResult response =
+ new ShellCommandResult.Builder().setOut(cmd).setResultCode(0).build();
+ mockRunShellCommand(response);
+
+ int result = runCmd(cmd);
+
+ expect.withMessage("result").that(result).isEqualTo(0);
+ expect.withMessage("out").that(getOut()).contains(cmd);
+ expect.withMessage("err").that(getErr()).isEmpty();
+ }
+
+ @Test
+ public void testExec_adServicesCommand_throwsRemoteException() throws Exception {
+ String cmd = "echo";
+
+ doThrow(new RemoteException()).when(mIShellCommand).runShellCommand(any(), any());
+
+ int result = runCmd(cmd);
+
+ expect.withMessage("result").that(result).isEqualTo(-1);
+ expect.withMessage("out").that(getOut()).isEmpty();
+ expect.withMessage("err").that(getErr()).contains("Remote exception occurred");
+ }
+
+ @Test
+ public void testExec_adServicesCommand_timeoutHappens() throws Exception {
+ String cmd = "xxx";
+
+ int result = runCmd(cmd);
+
+ expect.withMessage("result").that(result).isEqualTo(-1);
+ expect.withMessage("out").that(getOut()).isEmpty();
+ expect.withMessage("err").that(getErr()).contains("Timeout occurred");
}
@Test
@@ -307,4 +370,14 @@ public final class AdServicesShellCommandTest {
private void mockAdServicesSystemServiceEnabled(boolean value) {
when(mFlags.getAdServicesSystemServiceEnabled()).thenReturn(value);
}
+
+ private void mockRunShellCommand(ShellCommandResult response) throws Exception {
+ doAnswer(
+ invocation -> {
+ ((IShellCommandCallback) invocation.getArgument(1)).onResult(response);
+ return null;
+ })
+ .when(mIShellCommand)
+ .runShellCommand(any(), any());
+ }
}
diff --git a/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/AppConsentForRStorageManagerTest.java b/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/AppConsentForRStorageManagerTest.java
new file mode 100644
index 000000000..2569bc5c0
--- /dev/null
+++ b/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/AppConsentForRStorageManagerTest.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2023 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.service.consent;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+
+import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
+import com.android.adservices.data.common.BooleanFileDatastore;
+import com.android.adservices.data.consent.AppConsentDao;
+import com.android.adservices.service.FlagsFactory;
+import com.android.adservices.service.common.compat.PackageManagerCompatUtils;
+import com.android.adservices.service.extdata.AdServicesExtDataStorageServiceManager;
+import com.android.adservices.service.ui.data.UxStatesDao;
+import com.android.modules.utils.build.SdkLevel;
+import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import java.io.IOException;
+
+@SpyStatic(PackageManagerCompatUtils.class)
+@SpyStatic(SdkLevel.class)
+@SpyStatic(FlagsFactory.class)
+public final class AppConsentForRStorageManagerTest extends AdServicesExtendedMockitoTestCase {
+
+ private Context mContextSpy;
+ private BooleanFileDatastore mAppDaoDatastore;
+ private BooleanFileDatastore mConsentDatastore;
+ private AppConsentDao mAppConsentDaoSpy;
+ private AppConsentForRStorageManager mAppConsentForRStorageManager;
+ @Mock private UxStatesDao mUxStatesDaoMock;
+
+ @Mock private AdServicesExtDataStorageServiceManager mAdExtDataManager;
+
+ @Before
+ public void setup() {
+ mContextSpy = Mockito.spy(appContext.get());
+ mConsentDatastore =
+ new BooleanFileDatastore(
+ mContextSpy,
+ ConsentConstants.STORAGE_XML_IDENTIFIER,
+ ConsentConstants.STORAGE_VERSION);
+
+ mAppDaoDatastore =
+ new BooleanFileDatastore(
+ mContextSpy, AppConsentDao.DATASTORE_NAME, AppConsentDao.DATASTORE_VERSION);
+
+ mAppConsentDaoSpy =
+ spy(new AppConsentDao(mAppDaoDatastore, mContextSpy.getPackageManager()));
+ mAppConsentForRStorageManager =
+ spy(
+ new AppConsentForRStorageManager(
+ mConsentDatastore,
+ mAppConsentDaoSpy,
+ mUxStatesDaoMock,
+ mAdExtDataManager));
+ }
+
+ @After
+ public void teardown() throws IOException {
+ mAppDaoDatastore.clear();
+ mConsentDatastore.clear();
+ }
+
+ @Test
+ public void testNotSupportMethodException() {
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.setConsentForApp("", false));
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.clearAllAppConsentData());
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.clearConsentForUninstalledApp("", 0));
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.clearConsentForUninstalledApp(""));
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.clearKnownAppsWithConsent());
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.recordGaUxNotificationDisplayed(true));
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.recordNotificationDisplayed(true));
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.getAppsWithRevokedConsent());
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.getKnownAppsWithConsent());
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.isConsentRevokedForApp(""));
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.setConsentForAppIfNew("", true));
+ }
+
+ @Test
+ public void testGetMeasurementConsent() {
+ when(mAdExtDataManager.getMsmtConsent()).thenReturn(true);
+ for (AdServicesApiType apiType : AdServicesApiType.values()) {
+ AdServicesApiConsent apiConsent = mAppConsentForRStorageManager.getConsent(apiType);
+ if (apiType == AdServicesApiType.MEASUREMENTS) {
+
+ assertThat(apiConsent.isGiven()).isTrue();
+ } else {
+ assertThat(apiConsent.isGiven()).isFalse();
+ }
+ }
+ }
+
+ @Test
+ public void testSetMeasurementConsent() throws IOException {
+ mAppConsentForRStorageManager.setConsent(AdServicesApiType.MEASUREMENTS, true);
+ verify(mAdExtDataManager).setMsmtConsent(eq(true));
+ }
+
+ @Test
+ public void testGetUserManualInteractionWithConsent() {
+ mAppConsentForRStorageManager.getUserManualInteractionWithConsent();
+ verify(mAdExtDataManager).getManualInteractionWithConsentStatus();
+ }
+
+ @Test
+ public void testSetUserManualInteractionWithConsent() {
+ int userInteraction = 1;
+ mAppConsentForRStorageManager.recordUserManualInteractionWithConsent(userInteraction);
+ verify(mAdExtDataManager).setManualInteractionWithConsentStatus(eq(userInteraction));
+ }
+
+ @Test
+ public void testIsAdultAccount() {
+ mAppConsentForRStorageManager.isAdultAccount();
+ verify(mAdExtDataManager).getIsAdultAccount();
+ }
+
+ @Test
+ public void testSetIsAdultAccount() {
+ mAppConsentForRStorageManager.setAdultAccount(true);
+ verify(mAdExtDataManager).setIsAdultAccount(eq(true));
+ }
+
+ @Test
+ public void testIsU18Account() {
+ mAppConsentForRStorageManager.isU18Account();
+ verify(mAdExtDataManager).getIsU18Account();
+ }
+
+ @Test
+ public void testGetU18Notification() {
+ mAppConsentForRStorageManager.wasU18NotificationDisplayed();
+ verify(mAdExtDataManager).getNotificationDisplayed();
+ }
+
+ @Test
+ public void testSetU18Notification() {
+ mAppConsentForRStorageManager.setU18NotificationDisplayed(true);
+ verify(mAdExtDataManager).setNotificationDisplayed(eq(true));
+ }
+
+ @Test
+ public void testSetIsU18Account() {
+ mAppConsentForRStorageManager.setU18Account(true);
+ verify(mAdExtDataManager).setIsU18Account(eq(true));
+ }
+
+ @Test
+ public void testGAAndBetaNotificationFlag() {
+ boolean gaDisplayedFlag = mAppConsentForRStorageManager.wasGaUxNotificationDisplayed();
+
+ boolean betaDisplayedFlag = mAppConsentForRStorageManager.wasNotificationDisplayed();
+ assertThat(gaDisplayedFlag).isFalse();
+ assertThat(betaDisplayedFlag).isFalse();
+ }
+
+ @Test
+ public void testSetMeasurementConsentException() {
+ assertThrows(
+ IllegalStateException.class,
+ () -> mAppConsentForRStorageManager.setConsent(AdServicesApiType.FLEDGE, true));
+ }
+}
diff --git a/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/ConsentCompositeStorageTest.java b/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/ConsentCompositeStorageTest.java
index baca04901..e9bca8c57 100644
--- a/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/ConsentCompositeStorageTest.java
+++ b/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/ConsentCompositeStorageTest.java
@@ -50,14 +50,14 @@ public class ConsentCompositeStorageTest {
}
@Test
- public void testAllReadMethodsAppStorage() {
+ public void testAllReadMethodsAppStorage() throws IOException {
ConsentCompositeStorage consentCompositeStorage =
new ConsentCompositeStorage(ImmutableList.of(mAppConsentStorageManager));
testAllReadMethods(consentCompositeStorage);
}
@Test
- public void testAllReadMethodsPPAPIAndSystem() {
+ public void testAllReadMethodsPPAPIAndSystem() throws IOException {
ConsentCompositeStorage consentCompositeStorage =
new ConsentCompositeStorage(
ImmutableList.of(mAppConsentStorageManager, mAdServicesStorageManager));
@@ -79,14 +79,15 @@ public class ConsentCompositeStorageTest {
testAllWriteMethods(consentCompositeStorage);
}
- private void testAllReadMethods(ConsentCompositeStorage consentCompositeStorage) {
+ private void testAllReadMethods(ConsentCompositeStorage consentCompositeStorage)
+ throws IOException {
consentCompositeStorage.isAdIdEnabled();
consentCompositeStorage.isAdultAccount();
consentCompositeStorage.isConsentRevokedForApp(MOCK_PACKAGE_NAME);
consentCompositeStorage.isEntryPointEnabled();
consentCompositeStorage.isU18Account();
- verifyReadMethods(consentCompositeStorage.getPrimaryStorage());
+ verifyReadMethods(consentCompositeStorage.getConsentStorageList().get(0));
}
private void testAllWriteMethods(ConsentCompositeStorage consentCompositeStorage)
@@ -122,7 +123,7 @@ public class ConsentCompositeStorageTest {
}
}
- private void verifyReadMethods(IConsentStorage consentStorage) {
+ private void verifyReadMethods(IConsentStorage consentStorage) throws IOException {
Mockito.verify(consentStorage).isAdIdEnabled();
Mockito.verify(consentStorage).isAdultAccount();
Mockito.verify(consentStorage).isConsentRevokedForApp(eq(MOCK_PACKAGE_NAME));
diff --git a/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/ConsentManagerV2Test.java b/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/ConsentManagerV2Test.java
new file mode 100644
index 000000000..5a6cbdbcc
--- /dev/null
+++ b/adservices/tests/unittest/ui/src/com/android/adservices/service/consent/ConsentManagerV2Test.java
@@ -0,0 +1,4635 @@
+/*
+ * 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.service.consent;
+
+import static com.android.adservices.service.consent.ConsentConstants.CONSENT_KEY;
+import static com.android.adservices.service.consent.ConsentConstants.DEFAULT_CONSENT;
+import static com.android.adservices.service.consent.ConsentConstants.GA_UX_NOTIFICATION_DISPLAYED_ONCE;
+import static com.android.adservices.service.consent.ConsentConstants.MANUAL_INTERACTION_WITH_CONSENT_RECORDED;
+import static com.android.adservices.service.consent.ConsentConstants.NOTIFICATION_DISPLAYED_ONCE;
+import static com.android.adservices.service.consent.ConsentConstants.SHARED_PREFS_CONSENT;
+import static com.android.adservices.service.consent.ConsentConstants.SHARED_PREFS_KEY_APPSEARCH_HAS_MIGRATED;
+import static com.android.adservices.service.consent.ConsentConstants.SHARED_PREFS_KEY_HAS_MIGRATED;
+import static com.android.adservices.service.consent.ConsentConstants.SHARED_PREFS_KEY_PPAPI_HAS_CLEARED;
+import static com.android.adservices.service.consent.ConsentManagerV2.MANUAL_INTERACTIONS_RECORDED;
+import static com.android.adservices.service.consent.ConsentManagerV2.UNKNOWN;
+import static com.android.adservices.service.consent.ConsentManagerV2.resetSharedPreference;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PRIVACY_SANDBOX_SAVE_FAILURE;
+import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX;
+import static com.android.adservices.spe.AdservicesJobInfo.COBALT_LOGGING_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.CONSENT_NOTIFICATION_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.ENCRYPTION_KEY_PERIODIC_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.FLEDGE_AD_SELECTION_DEBUG_REPORT_SENDER_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.FLEDGE_BACKGROUND_FETCH_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MAINTENANCE_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MDD_CELLULAR_CHARGING_PERIODIC_TASK_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MDD_CHARGING_PERIODIC_TASK_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MDD_MAINTENANCE_PERIODIC_TASK_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MDD_WIFI_CHARGING_PERIODIC_TASK_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_AGGREGATE_FALLBACK_REPORTING_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_AGGREGATE_MAIN_REPORTING_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_ASYNC_REGISTRATION_FALLBACK_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_ASYNC_REGISTRATION_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_ATTRIBUTION_FALLBACK_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_ATTRIBUTION_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_DEBUG_REPORTING_FALLBACK_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_DELETE_EXPIRED_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_DELETE_UNINSTALLED_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_EVENT_FALLBACK_REPORTING_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_EVENT_MAIN_REPORTING_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.MEASUREMENT_VERBOSE_DEBUG_REPORTING_FALLBACK_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.PERIODIC_SIGNALS_ENCODING_JOB;
+import static com.android.adservices.spe.AdservicesJobInfo.TOPICS_EPOCH_JOB;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.argThat;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeastOnce;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.adservices.AdServicesManager;
+import android.app.adservices.IAdServicesManager;
+import android.app.adservices.consent.ConsentParcel;
+import android.app.job.JobScheduler;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+
+import androidx.test.core.content.pm.ApplicationInfoBuilder;
+import androidx.test.filters.SmallTest;
+
+import com.android.adservices.AdServicesCommon;
+import com.android.adservices.cobalt.CobaltJobService;
+import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
+import com.android.adservices.data.DbTestUtil;
+import com.android.adservices.data.adselection.AppInstallDao;
+import com.android.adservices.data.adselection.FrequencyCapDao;
+import com.android.adservices.data.common.BooleanFileDatastore;
+import com.android.adservices.data.consent.AppConsentDao;
+import com.android.adservices.data.consent.AppConsentDaoFixture;
+import com.android.adservices.data.customaudience.CustomAudienceDao;
+import com.android.adservices.data.enrollment.EnrollmentDao;
+import com.android.adservices.data.topics.Topic;
+import com.android.adservices.data.topics.TopicsTables;
+import com.android.adservices.download.MddJobService;
+import com.android.adservices.errorlogging.ErrorLogUtil;
+import com.android.adservices.service.Flags;
+import com.android.adservices.service.FlagsFactory;
+import com.android.adservices.service.MaintenanceJobService;
+import com.android.adservices.service.appsearch.AppSearchConsentStorageManager;
+import com.android.adservices.service.common.BackgroundJobsManager;
+import com.android.adservices.service.common.UserProfileIdManager;
+import com.android.adservices.service.common.compat.FileCompatUtils;
+import com.android.adservices.service.common.compat.PackageManagerCompatUtils;
+import com.android.adservices.service.common.feature.PrivacySandboxFeatureType;
+import com.android.adservices.service.encryptionkey.EncryptionKeyJobService;
+import com.android.adservices.service.extdata.AdServicesExtDataStorageServiceManager;
+import com.android.adservices.service.measurement.DeleteExpiredJobService;
+import com.android.adservices.service.measurement.DeleteUninstalledJobService;
+import com.android.adservices.service.measurement.MeasurementImpl;
+import com.android.adservices.service.measurement.attribution.AttributionFallbackJobService;
+import com.android.adservices.service.measurement.attribution.AttributionJobService;
+import com.android.adservices.service.measurement.registration.AsyncRegistrationFallbackJobService;
+import com.android.adservices.service.measurement.registration.AsyncRegistrationQueueJobService;
+import com.android.adservices.service.measurement.reporting.AggregateFallbackReportingJobService;
+import com.android.adservices.service.measurement.reporting.AggregateReportingJobService;
+import com.android.adservices.service.measurement.reporting.DebugReportingFallbackJobService;
+import com.android.adservices.service.measurement.reporting.EventFallbackReportingJobService;
+import com.android.adservices.service.measurement.reporting.EventReportingJobService;
+import com.android.adservices.service.measurement.reporting.VerboseDebugReportingFallbackJobService;
+import com.android.adservices.service.stats.AdServicesLoggerImpl;
+import com.android.adservices.service.stats.ConsentMigrationStats;
+import com.android.adservices.service.stats.StatsdAdServicesLogger;
+import com.android.adservices.service.stats.UiStatsLogger;
+import com.android.adservices.service.topics.AppUpdateManager;
+import com.android.adservices.service.topics.BlockedTopicsManager;
+import com.android.adservices.service.topics.CacheManager;
+import com.android.adservices.service.topics.EpochJobService;
+import com.android.adservices.service.topics.EpochManager;
+import com.android.adservices.service.topics.TopicsWorker;
+import com.android.adservices.service.ui.data.UxStatesDao;
+import com.android.adservices.service.ui.enrollment.collection.PrivacySandboxEnrollmentChannelCollection;
+import com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.dx.mockito.inline.extended.MockedVoidMethod;
+import com.android.modules.utils.build.SdkLevel;
+import com.android.modules.utils.testing.ExtendedMockitoRule.MockStatic;
+import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.verification.VerificationMode;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@SpyStatic(AdServicesLoggerImpl.class)
+@SpyStatic(AggregateFallbackReportingJobService.class)
+@SpyStatic(AggregateReportingJobService.class)
+@SpyStatic(AsyncRegistrationQueueJobService.class)
+@SpyStatic(AsyncRegistrationFallbackJobService.class)
+@SpyStatic(AttributionJobService.class)
+@SpyStatic(AttributionFallbackJobService.class)
+@SpyStatic(BackgroundJobsManager.class)
+@SpyStatic(ConsentManagerV2.class)
+@SpyStatic(DeleteExpiredJobService.class)
+@SpyStatic(DeleteUninstalledJobService.class)
+@SpyStatic(DeviceRegionProvider.class)
+@SpyStatic(EpochJobService.class)
+@SpyStatic(ErrorLogUtil.class)
+@SpyStatic(EventFallbackReportingJobService.class)
+@SpyStatic(EventReportingJobService.class)
+@SpyStatic(DebugReportingFallbackJobService.class)
+@SpyStatic(VerboseDebugReportingFallbackJobService.class)
+@SpyStatic(FlagsFactory.class)
+@SpyStatic(MaintenanceJobService.class)
+@SpyStatic(MddJobService.class)
+@SpyStatic(EncryptionKeyJobService.class)
+@SpyStatic(CobaltJobService.class)
+@SpyStatic(UiStatsLogger.class)
+@SpyStatic(StatsdAdServicesLogger.class)
+@MockStatic(PackageManagerCompatUtils.class)
+@MockStatic(SdkLevel.class)
+@SmallTest
+public final class ConsentManagerV2Test extends AdServicesExtendedMockitoTestCase {
+
+ @Spy private Context mContextSpy;
+ private BooleanFileDatastore mDatastore;
+ private BooleanFileDatastore mConsentDatastore;
+ private ConsentManagerV2 mConsentManager;
+ private AppConsentDao mAppConsentDaoSpy;
+ private EnrollmentDao mEnrollmentDaoSpy;
+ private AdServicesStorageManager mAdServicesStorageManager;
+
+ private AdServicesManager mAdServicesManager;
+
+ private AppConsentStorageManager mAppConsentStorageManager;
+ private AppConsentForRStorageManager mAppConsentForRStorageManager;
+
+ @Mock private AdServicesExtDataStorageServiceManager mAdServicesExtDataManager;
+
+ @Mock private AdServicesLoggerImpl mAdServicesLoggerImplMock;
+
+ @Mock private TopicsWorker mTopicsWorkerMock;
+ @Mock private MeasurementImpl mMeasurementImplMock;
+ @Mock private CustomAudienceDao mCustomAudienceDaoMock;
+ @Mock private AppInstallDao mAppInstallDaoMock;
+ @Mock private FrequencyCapDao mFrequencyCapDaoMock;
+ @Mock private UiStatsLogger mUiStatsLoggerMock;
+
+ @Mock private AppUpdateManager mAppUpdateManagerMock;
+ @Mock private CacheManager mCacheManagerMock;
+ @Mock private BlockedTopicsManager mBlockedTopicsManagerMock;
+ @Mock private EpochManager mMockEpochManager;
+
+ @Mock private PackageManager mPackageManager;
+ @Mock private Flags mMockFlags;
+ @Mock private JobScheduler mJobSchedulerMock;
+ @Mock private IAdServicesManager mMockIAdServicesManager;
+ @Mock private AppSearchConsentStorageManager mAppSearchConsentManagerMock;
+
+ @Mock private UserProfileIdManager mUserProfileIdManagerMock;
+ @Mock private UxStatesDao mUxStatesDaoMock;
+ @Mock private StatsdAdServicesLogger mStatsdAdServicesLoggerMock;
+
+ @Before
+ public void setup() throws IOException {
+ mContextSpy = spy(appContext.get());
+ doReturn(mStatsdAdServicesLoggerMock).when(StatsdAdServicesLogger::getInstance);
+ mDatastore =
+ spy(
+ new BooleanFileDatastore(
+ mContextSpy,
+ AppConsentDao.DATASTORE_NAME,
+ AppConsentDao.DATASTORE_VERSION));
+ // For each file, we should ensure there is only one instance of datastore that is able to
+ // access it. (Refer to BooleanFileDatastore.class)
+ mConsentDatastore = spy(ConsentManagerV2.createAndInitializeDataStore(mContextSpy));
+ mAppConsentDaoSpy = spy(new AppConsentDao(mDatastore, mContextSpy.getPackageManager()));
+ mEnrollmentDaoSpy =
+ spy(
+ new EnrollmentDao(
+ mContextSpy, DbTestUtil.getSharedDbHelperForTest(), mMockFlags));
+ mAppConsentStorageManager =
+ spy(
+ new AppConsentStorageManager(
+ mConsentDatastore, mAppConsentDaoSpy, mUxStatesDaoMock));
+
+ mAppConsentForRStorageManager =
+ spy(
+ new AppConsentForRStorageManager(
+ mConsentDatastore,
+ mAppConsentDaoSpy,
+ mUxStatesDaoMock,
+ mAdServicesExtDataManager));
+ mAdServicesManager = new AdServicesManager(mMockIAdServicesManager);
+ doReturn(mAdServicesManager).when(mContextSpy).getSystemService(AdServicesManager.class);
+
+ doReturn(mAdServicesLoggerImplMock).when(AdServicesLoggerImpl::getInstance);
+ mAdServicesStorageManager =
+ spy(new AdServicesStorageManager(mAdServicesManager, mPackageManager));
+ // Default to use PPAPI consent to test migration-irrelevant logic.
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_ONLY);
+ doReturn(mMockFlags).when(FlagsFactory::getFlags);
+ doReturn(true).when(mMockFlags).getFledgeAdSelectionFilteringEnabled();
+ doReturn(true).when(mMockFlags).getAdservicesConsentMigrationLoggingEnabled();
+ doReturn(true).when(mMockFlags).getEnrollmentEnableLimitedLogging();
+ doReturn(mAdServicesLoggerImplMock).when(AdServicesLoggerImpl::getInstance);
+ doReturn(true).when(() -> EpochJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ doReturn(true)
+ .when(() -> MaintenanceJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ doReturn(true).when(() -> MddJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ doReturn(true)
+ .when(
+ () ->
+ EncryptionKeyJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)));
+ doNothing().when(() -> AggregateReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doNothing()
+ .when(
+ () ->
+ AggregateFallbackReportingJobService.scheduleIfNeeded(
+ any(), anyBoolean()));
+ doNothing().when(() -> AttributionFallbackJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doNothing()
+ .when(
+ () ->
+ AsyncRegistrationFallbackJobService.scheduleIfNeeded(
+ any(), anyBoolean()));
+ doNothing()
+ .when(
+ () ->
+ VerboseDebugReportingFallbackJobService.scheduleIfNeeded(
+ any(), anyBoolean()));
+ doNothing()
+ .when(() -> DebugReportingFallbackJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doNothing().when(() -> AttributionJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doReturn(true).when(() -> EpochJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doReturn(true).when(() -> MddJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doNothing().when(() -> EventReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doNothing()
+ .when(() -> EventFallbackReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doNothing().when(() -> DeleteExpiredJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doNothing().when(() -> DeleteUninstalledJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doReturn(true).when(() -> MaintenanceJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doNothing()
+ .when(() -> AsyncRegistrationQueueJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doReturn(true).when(() -> CobaltJobService.scheduleIfNeeded(any(), anyBoolean()));
+ doNothing().when(() -> UiStatsLogger.logOptInSelected());
+ doNothing().when(() -> UiStatsLogger.logOptOutSelected());
+ doNothing().when(() -> UiStatsLogger.logOptInSelected(any()));
+ doNothing().when(() -> UiStatsLogger.logOptOutSelected(any()));
+ // The consent_source_of_truth=APPSEARCH_ONLY value is overridden on T+, so ignore level.
+ doReturn(false).when(() -> SdkLevel.isAtLeastT());
+ }
+
+ @After
+ public void teardown() throws IOException {
+ mDatastore.clear();
+ mConsentDatastore.clear();
+ }
+
+ @Test
+ public void testConsentIsGivenAfterEnabling_PpApiOnly() throws RemoteException, IOException {
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.enable(mContextSpy);
+
+ assertThat(spyConsentManager.getConsent().isGiven()).isTrue();
+
+ verifyConsentMigration(
+ /* isGiven */ isGiven,
+ /* hasWrittenToPpApi */ true,
+ /* hasWrittenToSystemServer */ false,
+ /* hasReadFromSystemServer */ false);
+ verifyDataCleanup(spyConsentManager);
+ }
+
+ @Test
+ public void testConsentIsGivenAfterEnabling_SystemServerOnly()
+ throws RemoteException, IOException {
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.enable(mContextSpy);
+
+ assertThat(spyConsentManager.getConsent().isGiven()).isTrue();
+
+ verifyConsentMigration(
+ /* isGiven */ isGiven,
+ /* hasWrittenToPpApi */ false,
+ /* hasWrittenToSystemServer */ true,
+ /* hasReadFromSystemServer */ true);
+ verifyDataCleanup(spyConsentManager);
+ }
+
+ @Test
+ public void testConsentIsGivenAfterEnabling_PPAPIAndSystemServer()
+ throws RemoteException, IOException {
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.enable(mContextSpy);
+
+ assertThat(spyConsentManager.getConsent().isGiven()).isTrue();
+
+ verifyConsentMigration(
+ /* isGiven */ isGiven,
+ /* hasWrittenToPpApi */ true,
+ /* hasWrittenToSystemServer */ true,
+ /* hasReadFromSystemServer */ true);
+ verifyDataCleanup(spyConsentManager);
+ }
+
+ @Test
+ public void testConsentIsGivenAfterEnabling_AppSearchOnly() throws Exception {
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.enable(mContextSpy);
+
+ assertThat(spyConsentManager.getConsent().isGiven()).isTrue();
+
+ verifyConsentMigration(
+ /* isGiven */ isGiven,
+ /* hasWrittenToPpApi */ false,
+ /* hasWrittenToSystemServer */ false,
+ /* hasReadFromSystemServer */ false);
+ verify(mAppSearchConsentManagerMock, atLeastOnce()).getConsent(AdServicesApiType.ALL_API);
+ verifyDataCleanup(spyConsentManager);
+ }
+
+ @Test
+ public void testConsentManager_LazyEnable() throws Exception {
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.ALL_API))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.ALL_API);
+
+ doReturn(true).when(mMockFlags).getConsentManagerLazyEnableMode();
+ spyConsentManager.enable(mContextSpy);
+ spyConsentManager.enable(mContextSpy);
+ assertThat(spyConsentManager.getConsent().isGiven()).isTrue();
+ verify(spyConsentManager, times(0)).setConsentToSourceOfTruth(isGiven);
+ verifyResetApiCalled(spyConsentManager, 0);
+ }
+
+ @Test
+ public void testConsentManager_LazyDisabled() throws Exception {
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.ALL_API))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.ALL_API);
+ doReturn(false).when(mMockFlags).getConsentManagerLazyEnableMode();
+ spyConsentManager.enable(mContextSpy);
+
+ assertThat(spyConsentManager.getConsent().isGiven()).isTrue();
+ verify(spyConsentManager).setConsentToSourceOfTruth(isGiven);
+ verifyResetApiCalled(spyConsentManager, 1);
+ }
+
+ @Test
+ public void testConsentManagerPreApi_LazyEnable() throws Exception {
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.MEASUREMENT))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.MEASUREMENT);
+
+ doReturn(true).when(mMockFlags).getConsentManagerLazyEnableMode();
+ doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
+ spyConsentManager.setPerApiConsentToSourceOfTruth(true, AdServicesApiType.ALL_API);
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.MEASUREMENTS);
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven()).isTrue();
+ verify(spyConsentManager, never()).resetByApi(eq(AdServicesApiType.MEASUREMENTS));
+ }
+
+ @Test
+ public void testConsentManagerPreApi_LazyDisabled() throws Exception {
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ doReturn(PrivacySandboxUxCollection.UNSUPPORTED_UX).when(mAdServicesStorageManager).getUx();
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.MEASUREMENT))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.MEASUREMENT);
+ doReturn(false).when(mMockFlags).getConsentManagerLazyEnableMode();
+ doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.MEASUREMENTS);
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven()).isTrue();
+
+ verify(spyConsentManager).resetByApi(eq(AdServicesApiType.MEASUREMENTS));
+ }
+
+ private static void verifyResetApiCalled(
+ ConsentManagerV2 spyConsentManager, int wantedNumOfInvocations) throws IOException {
+ verify(spyConsentManager, times(wantedNumOfInvocations)).resetTopicsAndBlockedTopics();
+ verify(spyConsentManager, times(wantedNumOfInvocations)).clearAllAppConsentData();
+ verify(spyConsentManager, times(wantedNumOfInvocations)).resetMeasurement();
+ }
+
+ @Test
+ public void testConsentIsRevokedAfterDisabling_PpApiOnly() throws RemoteException, IOException {
+ boolean isGiven = false;
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.disable(mContextSpy);
+
+ assertThat(spyConsentManager.getConsent().isGiven()).isFalse();
+
+ verifyConsentMigration(
+ /* isGiven */ isGiven,
+ /* hasWrittenToPpApi */ true,
+ /* hasWrittenToSystemServer */ false,
+ /* hasReadFromSystemServer */ false);
+ verifyDataCleanup(spyConsentManager);
+ }
+
+ @Test
+ public void testConsentIsRevokedAfterDisabling_SystemServerOnly()
+ throws RemoteException, IOException {
+ boolean isGiven = false;
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.disable(mContextSpy);
+
+ assertThat(spyConsentManager.getConsent().isGiven()).isFalse();
+
+ verifyConsentMigration(
+ /* isGiven */ isGiven,
+ /* hasWrittenToPpApi */ false,
+ /* hasWrittenToSystemServer */ true,
+ /* hasReadFromSystemServer */ true);
+ verifyDataCleanup(spyConsentManager);
+ }
+
+ @Test
+ public void testConsentIsRevokedAfterDisabling_PpApiAndSystemServer()
+ throws RemoteException, IOException {
+ boolean isGiven = false;
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.disable(mContextSpy);
+
+ assertThat(spyConsentManager.getConsent().isGiven()).isFalse();
+
+ verifyConsentMigration(
+ /* isGiven */ isGiven,
+ /* hasWrittenToPpApi */ true,
+ /* hasWrittenToSystemServer */ true,
+ /* hasReadFromSystemServer */ true);
+ verifyDataCleanup(spyConsentManager);
+ }
+
+ @Test
+ public void testConsentIsRevokedAfterDisabling_AppSearchOnly()
+ throws RemoteException, IOException {
+ boolean isGiven = false;
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+ assertThat(spyConsentManager.getConsent().isGiven()).isFalse();
+ spyConsentManager.disable(mContextSpy);
+
+ assertThat(spyConsentManager.getConsent().isGiven()).isFalse();
+
+ verifyConsentMigration(
+ /* isGiven */ isGiven,
+ /* hasWrittenToPpApi */ false,
+ /* hasWrittenToSystemServer */ false,
+ /* hasReadFromSystemServer */ false);
+ verify(mAppSearchConsentManagerMock, atLeastOnce()).getConsent(AdServicesApiType.ALL_API);
+ verifyDataCleanup(spyConsentManager);
+ }
+
+ @Test
+ public void testConsentIsRevokedAfterDisabling_notSupportedFlag() throws RemoteException {
+ boolean isGiven = true;
+ int invalidConsentSourceOfTruth = 5;
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ isGiven, invalidConsentSourceOfTruth));
+ }
+
+ @Test
+ public void testJobsAreScheduledAfterEnablingKillSwitchOff() {
+ doReturn(false).when(mMockFlags).getTopicsKillSwitch();
+ doReturn(false).when(mMockFlags).getFledgeSelectAdsKillSwitch();
+ doReturn(false).when(mMockFlags).getMeasurementKillSwitch();
+ doReturn(false).when(mMockFlags).getMddBackgroundTaskKillSwitch();
+ doReturn(true).when(mMockFlags).getCobaltLoggingEnabled();
+
+ mConsentManager.enable(mContextSpy);
+
+ verify(() -> BackgroundJobsManager.scheduleAllBackgroundJobs(any(Context.class)));
+ verify(() -> EpochJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ verify(() -> MddJobService.scheduleIfNeeded(any(Context.class), eq(false)), times(3));
+ verify(
+ () -> EncryptionKeyJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ times(2));
+ verify(
+ () -> MaintenanceJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ times(2));
+ verify(() -> AggregateReportingJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ verify(
+ () ->
+ AggregateFallbackReportingJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)));
+ verify(() -> AttributionFallbackJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ verify(
+ () ->
+ AsyncRegistrationFallbackJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)));
+ verify(
+ () ->
+ VerboseDebugReportingFallbackJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)));
+ verify(
+ () ->
+ DebugReportingFallbackJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)));
+ verify(() -> AttributionJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ verify(() -> EventReportingJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ verify(
+ () ->
+ EventFallbackReportingJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)));
+ verify(() -> DeleteExpiredJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ verify(() -> DeleteUninstalledJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ verify(
+ () ->
+ AsyncRegistrationQueueJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)));
+ verify(() -> CobaltJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ }
+
+ @Test
+ public void testJobsAreNotScheduledAfterEnablingKillSwitchOn() {
+ doReturn(true).when(mMockFlags).getTopicsKillSwitch();
+ doReturn(true).when(mMockFlags).getFledgeSelectAdsKillSwitch();
+ doReturn(true).when(mMockFlags).getMeasurementKillSwitch();
+ doReturn(true).when(mMockFlags).getMddBackgroundTaskKillSwitch();
+ doReturn(false).when(mMockFlags).getCobaltLoggingEnabled();
+
+ mConsentManager.enable(mContextSpy);
+
+ verify(() -> BackgroundJobsManager.scheduleAllBackgroundJobs(any(Context.class)));
+ verify(() -> EpochJobService.scheduleIfNeeded(any(Context.class), eq(false)), never());
+ verify(
+ () -> MaintenanceJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ never());
+ verify(() -> MddJobService.scheduleIfNeeded(any(Context.class), eq(false)), never());
+ verify(
+ () -> EncryptionKeyJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ never());
+ verify(
+ () -> AggregateReportingJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ never());
+ verify(
+ () ->
+ AggregateFallbackReportingJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)),
+ never());
+ verify(
+ () -> AttributionFallbackJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ never());
+ verify(
+ () ->
+ AsyncRegistrationFallbackJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)),
+ never());
+ verify(
+ () ->
+ VerboseDebugReportingFallbackJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)),
+ never());
+ verify(
+ () ->
+ DebugReportingFallbackJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)),
+ never());
+ verify(
+ () -> AttributionJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ never());
+ verify(
+ () -> EventReportingJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ never());
+ verify(
+ () ->
+ EventFallbackReportingJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)),
+ never());
+ verify(
+ () -> DeleteExpiredJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ never());
+ verify(
+ () -> DeleteUninstalledJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ never());
+ verify(
+ () ->
+ AsyncRegistrationQueueJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)),
+ never());
+ verify(() -> CobaltJobService.scheduleIfNeeded(any(Context.class), eq(false)), never());
+ }
+
+ @Test
+ public void testJobsAreUnscheduledAfterDisabling() {
+ doReturn(mJobSchedulerMock).when(mContextSpy).getSystemService(JobScheduler.class);
+ mConsentManager.disable(mContextSpy);
+
+ verify(() -> UiStatsLogger.logOptOutSelected());
+
+ verify(mJobSchedulerMock).cancel(MAINTENANCE_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(TOPICS_EPOCH_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_EVENT_MAIN_REPORTING_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_DELETE_EXPIRED_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_DELETE_UNINSTALLED_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_ATTRIBUTION_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_EVENT_FALLBACK_REPORTING_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_AGGREGATE_MAIN_REPORTING_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_AGGREGATE_FALLBACK_REPORTING_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_ASYNC_REGISTRATION_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_ATTRIBUTION_FALLBACK_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_ASYNC_REGISTRATION_FALLBACK_JOB.getJobId());
+ verify(mJobSchedulerMock)
+ .cancel(MEASUREMENT_VERBOSE_DEBUG_REPORTING_FALLBACK_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MEASUREMENT_DEBUG_REPORTING_FALLBACK_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(FLEDGE_BACKGROUND_FETCH_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(FLEDGE_AD_SELECTION_DEBUG_REPORT_SENDER_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(PERIODIC_SIGNALS_ENCODING_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(CONSENT_NOTIFICATION_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MDD_MAINTENANCE_PERIODIC_TASK_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MDD_CHARGING_PERIODIC_TASK_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MDD_CELLULAR_CHARGING_PERIODIC_TASK_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(MDD_WIFI_CHARGING_PERIODIC_TASK_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(ENCRYPTION_KEY_PERIODIC_JOB.getJobId());
+ verify(mJobSchedulerMock).cancel(COBALT_LOGGING_JOB.getJobId());
+
+ verifyNoMoreInteractions(mJobSchedulerMock);
+ }
+
+ @Test
+ public void testDataIsResetAfterConsentIsRevoked() throws IOException {
+ mConsentManager.disable(mContextSpy);
+
+ verify(() -> UiStatsLogger.logOptOutSelected());
+
+ SystemClock.sleep(1000);
+ verify(mTopicsWorkerMock).clearAllTopicsData(any());
+ // TODO(b/240988406): change to test for correct method call
+ verify(mAppConsentDaoSpy).clearAllConsentData();
+ verify(mEnrollmentDaoSpy).deleteAll();
+ verify(mMeasurementImplMock).deleteAllMeasurementData(any());
+ verify(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+ verify(mAppInstallDaoMock).deleteAllAppInstallData();
+ verify(mFrequencyCapDaoMock).deleteAllHistogramData();
+ verify(mUserProfileIdManagerMock).deleteId();
+ }
+
+ @Test
+ public void testDataIsResetAfterConsentIsRevokedFilteringDisabled() throws IOException {
+ doReturn(false).when(mMockFlags).getFledgeAdSelectionFilteringEnabled();
+ mConsentManager.disable(mContextSpy);
+
+ verify(() -> UiStatsLogger.logOptOutSelected());
+
+ SystemClock.sleep(1000);
+ verify(mTopicsWorkerMock).clearAllTopicsData(any());
+ // TODO(b/240988406): change to test for correct method call
+ verify(mAppConsentDaoSpy).clearAllConsentData();
+ verify(mEnrollmentDaoSpy).deleteAll();
+ verify(mMeasurementImplMock).deleteAllMeasurementData(any());
+ verify(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+ verifyZeroInteractions(mAppInstallDaoMock, mFrequencyCapDaoMock);
+ verify(mUserProfileIdManagerMock).deleteId();
+ }
+
+ @Test
+ public void testDataIsResetAfterConsentIsGiven() throws IOException {
+ mConsentManager.enable(mContextSpy);
+
+ verify(() -> UiStatsLogger.logOptInSelected());
+
+ SystemClock.sleep(1000);
+ verify(mTopicsWorkerMock).clearAllTopicsData(any());
+ // TODO(b/240988406): change to test for correct method call
+ verify(mAppConsentDaoSpy).clearAllConsentData();
+ verify(mMeasurementImplMock).deleteAllMeasurementData(any());
+ verify(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+ verify(mAppInstallDaoMock).deleteAllAppInstallData();
+ verify(mFrequencyCapDaoMock).deleteAllHistogramData();
+ verify(mUserProfileIdManagerMock).deleteId();
+ verify(mUserProfileIdManagerMock).getOrCreateId();
+ }
+
+ @Test
+ public void testDataIsResetAfterConsentIsGivenFilteringDisabled() throws IOException {
+ doReturn(false).when(mMockFlags).getFledgeAdSelectionFilteringEnabled();
+ mConsentManager.enable(mContextSpy);
+
+ verify(() -> UiStatsLogger.logOptInSelected());
+
+ SystemClock.sleep(1000);
+ verify(mTopicsWorkerMock).clearAllTopicsData(any());
+ // TODO(b/240988406): change to test for correct method call
+ verify(mAppConsentDaoSpy).clearAllConsentData();
+ verify(mMeasurementImplMock).deleteAllMeasurementData(any());
+ verify(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+ verifyZeroInteractions(mAppInstallDaoMock, mFrequencyCapDaoMock);
+ verify(mUserProfileIdManagerMock).deleteId();
+ verify(mUserProfileIdManagerMock).getOrCreateId();
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppWithFullApiConsentGaUxEnabled_ppApiOnly()
+ throws IOException, PackageManager.NameNotFoundException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager.enable(mContextSpy, AdServicesApiType.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ verify(() -> UiStatsLogger.logOptInSelected(AdServicesApiType.FLEDGE));
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, true);
+
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppWithFullApiConsentGaUxEnabled_systemServerOnly()
+ throws PackageManager.NameNotFoundException, RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(consentSourceOfTruth);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ doReturn(false)
+ .when(mMockIAdServicesManager)
+ .isConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ doReturn(true)
+ .when(mMockIAdServicesManager)
+ .isConsentRevokedForApp(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ doReturn(false)
+ .when(mMockIAdServicesManager)
+ .isConsentRevokedForApp(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppWithFullApiConsentGaUxEnabled_appSearchOnly()
+ throws Exception {
+ runTestIsFledgeConsentRevokedForAppWithFullApiConsentAppSearchOnly(true);
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppWithFullApiConsentGaUxDisabled_appSearchOnly()
+ throws Exception {
+ runTestIsFledgeConsentRevokedForAppWithFullApiConsentAppSearchOnly(false);
+ }
+
+ private void runTestIsFledgeConsentRevokedForAppWithFullApiConsentAppSearchOnly(
+ boolean isGaUxEnabled) throws Exception {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(isGaUxEnabled);
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(consentSourceOfTruth);
+ when(mAppSearchConsentManagerMock.getConsent(any())).thenReturn(AdServicesApiConsent.GIVEN);
+
+ mConsentManager.enable(mContextSpy, AdServicesApiType.FLEDGE);
+ verify(() -> UiStatsLogger.logOptInSelected(AdServicesApiType.FLEDGE));
+
+ String app1 = AppConsentDaoFixture.APP10_PACKAGE_NAME;
+ String app2 = AppConsentDaoFixture.APP20_PACKAGE_NAME;
+ String app3 = AppConsentDaoFixture.APP30_PACKAGE_NAME;
+ mockGetPackageUid(app1, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(app2, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(app3, AppConsentDaoFixture.APP30_UID);
+
+ when(mAppSearchConsentManagerMock.isConsentRevokedForApp(app1)).thenReturn(false);
+ when(mAppSearchConsentManagerMock.isConsentRevokedForApp(app2)).thenReturn(true);
+ when(mAppSearchConsentManagerMock.isConsentRevokedForApp(app3)).thenReturn(false);
+
+ assertFalse(mConsentManager.isFledgeConsentRevokedForApp(app1));
+ assertTrue(mConsentManager.isFledgeConsentRevokedForApp(app2));
+ assertFalse(mConsentManager.isFledgeConsentRevokedForApp(app3));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppWithFullApiConsentGaUxEnabled_ppApiAndSystemServer()
+ throws PackageManager.NameNotFoundException, RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(consentSourceOfTruth);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ doReturn(false)
+ .when(mMockIAdServicesManager)
+ .isConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ doReturn(true)
+ .when(mMockIAdServicesManager)
+ .isConsentRevokedForApp(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ doReturn(false)
+ .when(mMockIAdServicesManager)
+ .isConsentRevokedForApp(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppWithoutPrivacySandboxConsentGaUxEnabled_ppApiOnly()
+ throws PackageManager.NameNotFoundException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager.disable(mContextSpy, AdServicesApiType.FLEDGE);
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ verify(() -> UiStatsLogger.logOptOutSelected(AdServicesApiType.FLEDGE));
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppWithoutPrivacySandboxConsentGaUxEnabled_sysServer()
+ throws RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+ doReturn(ConsentParcel.createRevokedConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppWithoutPrivacySandboxConsentGaUxEnabled_bothSrc()
+ throws RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ doReturn(ConsentParcel.createRevokedConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForNotFoundAppGaUxEnabledThrows_ppApiOnly()
+ throws PackageManager.NameNotFoundException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager.enable(mContextSpy, AdServicesApiType.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ verify(() -> UiStatsLogger.logOptInSelected(AdServicesApiType.FLEDGE));
+
+ mockThrowExceptionOnGetPackageUid(AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME);
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForNotFoundAppGaUxEnabledThrows_systemServerOnly()
+ throws PackageManager.NameNotFoundException, RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ mockThrowExceptionOnGetPackageUid(AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME);
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForNotFoundAppGaUxEnabledThrows_ppApiAndSystemServer()
+ throws PackageManager.NameNotFoundException, RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ mockThrowExceptionOnGetPackageUid(AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME);
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME));
+ }
+
+ // AppSearch test for isFledgeConsentRevokedForAppAfterSettingFledgeUse with GA UX enabled.
+ @Test
+ public void testIsFledgeConsentRevokedForAppAfterSetFledgeUseWithFullApiConsentGaUxEnabled_as()
+ throws Exception {
+ runTestIsFledgeConsentRevokedForAppAfterSetFledgeUseWithFullApiConsentAppSearch(true);
+ }
+
+ private void runTestIsFledgeConsentRevokedForAppAfterSetFledgeUseWithFullApiConsentAppSearch(
+ boolean isGaUxEnabled) throws Exception {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.APPSEARCH_ONLY);
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(isGaUxEnabled);
+ when(mAppSearchConsentManagerMock.getConsent(any())).thenReturn(AdServicesApiConsent.GIVEN);
+ mConsentManager.enable(mContextSpy);
+ verify(() -> UiStatsLogger.logOptInSelected());
+
+ String app1 = AppConsentDaoFixture.APP10_PACKAGE_NAME;
+ String app2 = AppConsentDaoFixture.APP20_PACKAGE_NAME;
+ String app3 = AppConsentDaoFixture.APP30_PACKAGE_NAME;
+ mockGetPackageUid(app1, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(app2, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(app3, AppConsentDaoFixture.APP30_UID);
+
+ when(mAppSearchConsentManagerMock.setConsentForAppIfNew(app1, false)).thenReturn(false);
+ when(mAppSearchConsentManagerMock.setConsentForAppIfNew(app2, false)).thenReturn(true);
+ when(mAppSearchConsentManagerMock.setConsentForAppIfNew(app3, false)).thenReturn(false);
+
+ assertFalse(mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(app1));
+ assertTrue(mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(app2));
+ assertFalse(mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(app3));
+ }
+
+ @Test
+ public void
+ testIsFledgeConsentRevokedForAppAfterSetFledgeUseWithFullApiConsentGaUxEnabled_ppApi()
+ throws IOException, PackageManager.NameNotFoundException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager.enable(mContextSpy, AdServicesApiType.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ verify(() -> UiStatsLogger.logOptInSelected(AdServicesApiType.FLEDGE));
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, true);
+
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME));
+ }
+
+ @Test
+ public void
+ testIsFledgeConsentRevokedForAppAfterSetFledgeUseWithFullApiConsentGaUxEnabled_sysSer()
+ throws PackageManager.NameNotFoundException, RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ doReturn(false)
+ .when(mMockIAdServicesManager)
+ .setConsentForAppIfNew(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP10_UID,
+ false);
+ doReturn(true)
+ .when(mMockIAdServicesManager)
+ .setConsentForAppIfNew(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_UID,
+ false);
+ doReturn(false)
+ .when(mMockIAdServicesManager)
+ .setConsentForAppIfNew(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_UID,
+ false);
+
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME));
+ }
+
+ @Test
+ public void
+ testIsFledgeConsentRevokedForAppAfterSetFledgeUseWithFullApiConsentGaUxEnabled_both()
+ throws PackageManager.NameNotFoundException, RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ doReturn(false)
+ .when(mMockIAdServicesManager)
+ .setConsentForAppIfNew(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP10_UID,
+ false);
+ doReturn(true)
+ .when(mMockIAdServicesManager)
+ .setConsentForAppIfNew(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_UID,
+ false);
+ doReturn(false)
+ .when(mMockIAdServicesManager)
+ .setConsentForAppIfNew(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_UID,
+ false);
+
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP30_PACKAGE_NAME));
+ }
+
+ @Test
+ public void
+ testIsFledgeConsentRevokedForAppSetFledgeUseNoPrivacySandboxConsentGaUxEnabled_ppApi()
+ throws PackageManager.NameNotFoundException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+
+ mConsentManager.disable(mContextSpy, AdServicesApiType.FLEDGE);
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ }
+
+ @Test
+ public void
+ testIsFledgeConsentRevokedForAppSetFledgeUseNoPrivacySandboxConsentGaUxEnabled_sysSer()
+ throws RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+ doReturn(ConsentParcel.createRevokedConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ }
+
+ @Test
+ public void
+ testIsFledgeConsentRevokedForAppSetFledgeUseNoPrivacySandboxConsentGaUxEnabled_both()
+ throws RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ doReturn(ConsentParcel.createRevokedConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppAfterSettingFledgeUseThrows_ppApiOnly()
+ throws PackageManager.NameNotFoundException {
+ mConsentManager.enable(mContextSpy, AdServicesApiType.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ verify(() -> UiStatsLogger.logOptInSelected(AdServicesApiType.FLEDGE));
+
+ mockThrowExceptionOnGetPackageUid(AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME);
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppAfterSettingFledgeUseThrows_systemServerOnly()
+ throws PackageManager.NameNotFoundException, RemoteException {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ mockThrowExceptionOnGetPackageUid(AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME);
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testIsFledgeConsentRevokedForAppAfterSettingFledgeUseThrows_ppApiAndSystemServer()
+ throws PackageManager.NameNotFoundException, RemoteException {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ mockThrowExceptionOnGetPackageUid(AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME);
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ mConsentManager.isFledgeConsentRevokedForAppAfterSettingFledgeUse(
+ AppConsentDaoFixture.APP_NOT_FOUND_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testGetKnownAppsWithConsent_ppApiOnly()
+ throws IOException, PackageManager.NameNotFoundException {
+ mConsentManager.enable(mContextSpy);
+ assertTrue(mConsentManager.getConsent().isGiven());
+
+ verify(() -> UiStatsLogger.logOptInSelected());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP30_DATASTORE_KEY, false);
+ List<ApplicationInfo> applicationsInstalled =
+ createApplicationInfos(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ mockInstalledApplications(applicationsInstalled);
+
+ ImmutableList<App> knownAppsWithConsent = mConsentManager.getKnownAppsWithConsent();
+ ImmutableList<App> appsWithRevokedConsent = mConsentManager.getAppsWithRevokedConsent();
+
+ // all apps have received a consent
+ assertThat(knownAppsWithConsent).hasSize(3);
+ assertThat(appsWithRevokedConsent).isEmpty();
+ }
+
+ @Test
+ public void testGetKnownAppsWithConsent_systemServerOnly() throws RemoteException {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.ALL_API))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.ALL_API);
+ assertTrue(mConsentManager.getConsent().isGiven());
+
+ List<ApplicationInfo> applicationsInstalled =
+ createApplicationInfos(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ List<String> applicationsInstalledNames =
+ applicationsInstalled.stream()
+ .map(applicationInfo -> applicationInfo.packageName)
+ .collect(Collectors.toList());
+ mockInstalledApplications(applicationsInstalled);
+
+ doReturn(applicationsInstalledNames)
+ .when(mMockIAdServicesManager)
+ .getKnownAppsWithConsent(
+ argThat(new ListMatcherIgnoreOrder(applicationsInstalledNames)));
+ doReturn(List.of())
+ .when(mMockIAdServicesManager)
+ .getAppsWithRevokedConsent(
+ argThat(new ListMatcherIgnoreOrder(applicationsInstalledNames)));
+
+ ImmutableList<App> knownAppsWithConsent = mConsentManager.getKnownAppsWithConsent();
+ ImmutableList<App> appsWithRevokedConsent = mConsentManager.getAppsWithRevokedConsent();
+
+ verify(mMockIAdServicesManager)
+ .getKnownAppsWithConsent(
+ argThat(new ListMatcherIgnoreOrder(applicationsInstalledNames)));
+ verify(mMockIAdServicesManager)
+ .getAppsWithRevokedConsent(
+ argThat(new ListMatcherIgnoreOrder(applicationsInstalledNames)));
+
+ verify(mAdServicesStorageManager, times(2)).getInstalledPackages();
+ verifyNoMoreInteractions(mAppConsentDaoSpy);
+
+ // all apps have received a consent
+ assertThat(knownAppsWithConsent).hasSize(3);
+ assertThat(appsWithRevokedConsent).isEmpty();
+ }
+
+ @Test
+ public void testGetKnownAppsWithConsent_ppApiAndSystemServer() throws RemoteException {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.ALL_API))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.ALL_API);
+ assertTrue(mConsentManager.getConsent().isGiven());
+
+ List<ApplicationInfo> applicationsInstalled =
+ createApplicationInfos(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ List<String> applicationsInstalledNames =
+ applicationsInstalled.stream()
+ .map(applicationInfo -> applicationInfo.packageName)
+ .collect(Collectors.toList());
+ mockInstalledApplications(applicationsInstalled);
+
+ doReturn(applicationsInstalledNames)
+ .when(mMockIAdServicesManager)
+ .getKnownAppsWithConsent(
+ argThat(new ListMatcherIgnoreOrder(applicationsInstalledNames)));
+ doReturn(List.of())
+ .when(mMockIAdServicesManager)
+ .getAppsWithRevokedConsent(
+ argThat(new ListMatcherIgnoreOrder(applicationsInstalledNames)));
+
+ ImmutableList<App> knownAppsWithConsent = mConsentManager.getKnownAppsWithConsent();
+ ImmutableList<App> appsWithRevokedConsent = mConsentManager.getAppsWithRevokedConsent();
+
+ verify(mMockIAdServicesManager)
+ .getKnownAppsWithConsent(
+ argThat(new ListMatcherIgnoreOrder(applicationsInstalledNames)));
+ verify(mMockIAdServicesManager)
+ .getAppsWithRevokedConsent(
+ argThat(new ListMatcherIgnoreOrder(applicationsInstalledNames)));
+
+ verify(mAdServicesStorageManager, times(2)).getInstalledPackages();
+ verifyNoMoreInteractions(mAppConsentDaoSpy);
+
+ // all apps have received a consent
+ assertThat(knownAppsWithConsent).hasSize(3);
+ assertThat(appsWithRevokedConsent).isEmpty();
+ }
+
+ @Test
+ public void testGetKnownAppsWithConsent_appSearchOnly() {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.APPSEARCH_ONLY);
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+
+ ImmutableList<String> consentedAppsList =
+ ImmutableList.of(AppConsentDaoFixture.APP10_PACKAGE_NAME);
+ ImmutableList<String> revokedAppsList =
+ ImmutableList.of(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+
+ doReturn(consentedAppsList).when(mAppSearchConsentManagerMock).getKnownAppsWithConsent();
+ doReturn(revokedAppsList).when(mAppSearchConsentManagerMock).getAppsWithRevokedConsent();
+
+ ImmutableList<App> knownAppsWithConsent = mConsentManager.getKnownAppsWithConsent();
+ ImmutableList<App> appsWithRevokedConsent = mConsentManager.getAppsWithRevokedConsent();
+
+ verify(mAppSearchConsentManagerMock).getKnownAppsWithConsent();
+ verify(mAppSearchConsentManagerMock).getAppsWithRevokedConsent();
+
+ // Correct apps have received consent.
+ assertThat(knownAppsWithConsent).hasSize(1);
+ assertThat(knownAppsWithConsent.get(0).getPackageName())
+ .isEqualTo(AppConsentDaoFixture.APP10_PACKAGE_NAME);
+ assertThat(appsWithRevokedConsent).hasSize(2);
+ assertThat(
+ appsWithRevokedConsent.stream()
+ .map(app -> app.getPackageName())
+ .collect(Collectors.toList()))
+ .containsAtLeast(
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ }
+
+ @Test
+ public void testGetKnownAppsWithConsent_ppapiAndAdExtDataServiceOnly() throws IOException {
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_ADEXT_SERVICE);
+ assertThat(mConsentManager.getKnownAppsWithConsent()).isEqualTo(ImmutableList.of());
+ }
+
+ @Test
+ public void testGetKnownAppsWithConsentAfterConsentForOneOfThemWasRevoked_ppApiOnly()
+ throws IOException, PackageManager.NameNotFoundException {
+ // mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_ONLY);
+ doNothing().when(mCustomAudienceDaoMock).deleteCustomAudienceDataByOwner(any());
+
+ mConsentManager.enable(mContextSpy);
+ mConsentManager.setConsentToSourceOfTruth(true);
+ assertThat(mConsentManager.getConsent().isGiven()).isTrue();
+
+ verify(() -> UiStatsLogger.logOptInSelected());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP30_DATASTORE_KEY, false);
+ List<ApplicationInfo> applicationsInstalled =
+ createApplicationInfos(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ mockInstalledApplications(applicationsInstalled);
+
+ App app = App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME);
+
+ // revoke consent for first app
+ mConsentManager.revokeConsentForApp(app);
+ ImmutableList<App> knownAppsWithConsent = mConsentManager.getKnownAppsWithConsent();
+ ImmutableList<App> appsWithRevokedConsent = mConsentManager.getAppsWithRevokedConsent();
+
+ // all apps have received a consent
+ assertThat(knownAppsWithConsent).hasSize(2);
+ assertThat(appsWithRevokedConsent).hasSize(1);
+ App appWithRevokedConsent = appsWithRevokedConsent.get(0);
+ assertThat(appWithRevokedConsent.getPackageName()).isEqualTo(app.getPackageName());
+
+ SystemClock.sleep(1000);
+ verify(mCustomAudienceDaoMock).deleteCustomAudienceDataByOwner(app.getPackageName());
+ verify(mAppInstallDaoMock).deleteByPackageName(app.getPackageName());
+ verify(mFrequencyCapDaoMock).deleteHistogramDataBySourceApp(app.getPackageName());
+ }
+
+ @Test
+ public void testGetKnownAppsWithConsentAfterConsentForOneOfThemWasRevokedAndRestored_ppApiOnly()
+ throws IOException, PackageManager.NameNotFoundException {
+ doNothing().when(mCustomAudienceDaoMock).deleteCustomAudienceDataByOwner(any());
+
+ mConsentManager.enable(mContextSpy);
+ assertTrue(mConsentManager.getConsent().isGiven());
+
+ verify(() -> UiStatsLogger.logOptInSelected());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP30_DATASTORE_KEY, false);
+ App app = App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME);
+ List<ApplicationInfo> applicationsInstalled =
+ createApplicationInfos(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ mockInstalledApplications(applicationsInstalled);
+
+ // revoke consent for first app
+ mConsentManager.revokeConsentForApp(app);
+ ImmutableList<App> knownAppsWithConsent = mConsentManager.getKnownAppsWithConsent();
+ ImmutableList<App> appsWithRevokedConsent = mConsentManager.getAppsWithRevokedConsent();
+
+ // all apps have received a consent
+ assertThat(knownAppsWithConsent).hasSize(2);
+ assertThat(appsWithRevokedConsent).hasSize(1);
+ App appWithRevokedConsent = appsWithRevokedConsent.get(0);
+ assertThat(appWithRevokedConsent.getPackageName()).isEqualTo(app.getPackageName());
+
+ SystemClock.sleep(1000);
+ verify(mCustomAudienceDaoMock).deleteCustomAudienceDataByOwner(app.getPackageName());
+ verify(mAppInstallDaoMock).deleteByPackageName(app.getPackageName());
+ verify(mFrequencyCapDaoMock).deleteHistogramDataBySourceApp(app.getPackageName());
+
+ // restore consent for first app
+ mConsentManager.restoreConsentForApp(app);
+ knownAppsWithConsent = mConsentManager.getKnownAppsWithConsent();
+ appsWithRevokedConsent = mConsentManager.getAppsWithRevokedConsent();
+
+ // all apps have received a consent
+ assertThat(knownAppsWithConsent).hasSize(3);
+ assertThat(appsWithRevokedConsent).isEmpty();
+ }
+
+ @Test
+ public void testSetConsentForApp_ppApiOnly() throws Exception {
+ mConsentManager.enable(mContextSpy, AdServicesApiType.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ verify(() -> UiStatsLogger.logOptInSelected(AdServicesApiType.FLEDGE));
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+
+ mConsentManager.revokeConsentForApp(App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertTrue(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+
+ mConsentManager.restoreConsentForApp(App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertFalse(
+ mConsentManager.isFledgeConsentRevokedForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ }
+
+ @Test
+ public void testSetConsentForApp_systemServerOnly() throws Exception {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+
+ mConsentManager.revokeConsentForApp(App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ verify(mMockIAdServicesManager)
+ .setConsentForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP10_UID,
+ true);
+
+ mConsentManager.restoreConsentForApp(App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ verify(mMockIAdServicesManager)
+ .setConsentForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP10_UID,
+ false);
+ }
+
+ @Test
+ public void testSetConsentForApp_ppApiAndSystemServer() throws Exception {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.FLEDGE))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.FLEDGE);
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+
+ mConsentManager.revokeConsentForApp(App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ verify(mMockIAdServicesManager)
+ .setConsentForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP10_UID,
+ true);
+ assertEquals(Boolean.TRUE, mDatastore.get(AppConsentDaoFixture.APP10_DATASTORE_KEY));
+
+ mConsentManager.restoreConsentForApp(App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ verify(mMockIAdServicesManager)
+ .setConsentForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP10_UID,
+ false);
+ assertEquals(Boolean.FALSE, mDatastore.get(AppConsentDaoFixture.APP10_DATASTORE_KEY));
+ }
+
+ @Test
+ public void testSetConsentForApp_appSearchOnly() throws Exception {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.APPSEARCH_ONLY);
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+
+ App app = App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME);
+ mConsentManager.revokeConsentForApp(app);
+ verify(mAppSearchConsentManagerMock).setConsentForApp(app.getPackageName(), true);
+
+ mConsentManager.restoreConsentForApp(app);
+ verify(mAppSearchConsentManagerMock).setConsentForApp(app.getPackageName(), false);
+ }
+
+ @Test
+ public void testRevokeConsentForApp_ppapiAndAdExtDataServiceOnly() {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_ADEXT_SERVICE);
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ App app = App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME);
+
+ assertThrows(RuntimeException.class, () -> mConsentManager.revokeConsentForApp(app));
+ }
+
+ @Test
+ public void testRestoreConsentForApp_ppapiAndAdExtDataServiceOnly() {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_ADEXT_SERVICE);
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ App app = App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME);
+
+ assertThrows(RuntimeException.class, () -> mConsentManager.restoreConsentForApp(app));
+ }
+
+ @Test
+ public void clearConsentForUninstalledApp_ppApiOnly()
+ throws PackageManager.NameNotFoundException, IOException {
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+
+ mConsentManager.restoreConsentForApp(App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertEquals(Boolean.FALSE, mDatastore.get(AppConsentDaoFixture.APP10_DATASTORE_KEY));
+ mConsentManager.clearConsentForUninstalledApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ assertNull(mDatastore.get(AppConsentDaoFixture.APP10_DATASTORE_KEY));
+ }
+
+ @Test
+ public void clearConsentForUninstalledApp_systemServerOnly() throws RemoteException {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+ mConsentManager.clearConsentForUninstalledApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ verify(mMockIAdServicesManager)
+ .clearConsentForUninstalledApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ }
+
+ @Test
+ public void clearConsentForUninstalledApp_ppApiAndSystemServer()
+ throws PackageManager.NameNotFoundException, IOException, RemoteException {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+
+ mConsentManager.restoreConsentForApp(App.create(AppConsentDaoFixture.APP10_PACKAGE_NAME));
+ assertEquals(Boolean.FALSE, mDatastore.get(AppConsentDaoFixture.APP10_DATASTORE_KEY));
+ verify(mMockIAdServicesManager)
+ .setConsentForApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP10_UID,
+ false);
+ mConsentManager.clearConsentForUninstalledApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ assertNull(mDatastore.get(AppConsentDaoFixture.APP10_DATASTORE_KEY));
+ verify(mMockIAdServicesManager)
+ .clearConsentForUninstalledApp(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ }
+
+ @Test
+ public void clearConsentForUninstalledApp_appSearchOnly() throws Exception {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.APPSEARCH_ONLY);
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ String packageName = AppConsentDaoFixture.APP10_PACKAGE_NAME;
+ mockGetPackageUid(packageName, AppConsentDaoFixture.APP10_UID);
+
+ mConsentManager.clearConsentForUninstalledApp(packageName, AppConsentDaoFixture.APP10_UID);
+ verify(mAppSearchConsentManagerMock)
+ .clearConsentForUninstalledApp(packageName, AppConsentDaoFixture.APP10_UID);
+ }
+
+ @Test
+ public void clearConsentForUninstalledApp_ppapiAndAdExtDataServiceOnly() {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_ADEXT_SERVICE);
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ String packageName = AppConsentDaoFixture.APP10_PACKAGE_NAME;
+
+ assertThrows(
+ RuntimeException.class,
+ () ->
+ mConsentManager.clearConsentForUninstalledApp(
+ packageName, AppConsentDaoFixture.APP10_UID));
+ }
+
+ @Test
+ public void clearConsentForUninstalledAppWithoutUid_ppApiOnly() throws IOException {
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, true);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, true);
+ mDatastore.put(AppConsentDaoFixture.APP30_DATASTORE_KEY, false);
+
+ mConsentManager.clearConsentForUninstalledApp(AppConsentDaoFixture.APP20_PACKAGE_NAME);
+
+ assertEquals(true, mDatastore.get(AppConsentDaoFixture.APP10_DATASTORE_KEY));
+ assertNull(mDatastore.get(AppConsentDaoFixture.APP20_DATASTORE_KEY));
+ assertEquals(false, mDatastore.get(AppConsentDaoFixture.APP30_DATASTORE_KEY));
+
+ verify(mAppConsentDaoSpy).clearConsentForUninstalledApp(anyString());
+ }
+
+ @Test
+ public void clearConsentForUninstalledAppWithoutUid_ppApiOnly_validatesInput() {
+ assertThrows(
+ NullPointerException.class,
+ () -> {
+ mConsentManager.clearConsentForUninstalledApp(null);
+ });
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> {
+ mConsentManager.clearConsentForUninstalledApp("");
+ });
+ }
+
+ @Test
+ public void testGetKnownTopicsWithConsent() {
+ long taxonomyVersion = 1L;
+ long modelVersion = 1L;
+ Topic topic1 = Topic.create(1, taxonomyVersion, modelVersion);
+ Topic topic2 = Topic.create(2, taxonomyVersion, modelVersion);
+ ImmutableList<Topic> expectedKnownTopicsWithConsent = ImmutableList.of(topic1, topic2);
+ doReturn(expectedKnownTopicsWithConsent)
+ .when(mTopicsWorkerMock)
+ .getKnownTopicsWithConsent();
+
+ ImmutableList<Topic> knownTopicsWithConsent = mConsentManager.getKnownTopicsWithConsent();
+
+ assertThat(knownTopicsWithConsent)
+ .containsExactlyElementsIn(expectedKnownTopicsWithConsent);
+ }
+
+ @Test
+ public void testGetTopicsWithRevokedConsent() {
+ long taxonomyVersion = 1L;
+ long modelVersion = 1L;
+ Topic topic1 = Topic.create(1, taxonomyVersion, modelVersion);
+ Topic topic2 = Topic.create(2, taxonomyVersion, modelVersion);
+ ImmutableList<Topic> expectedTopicsWithRevokedConsent = ImmutableList.of(topic1, topic2);
+ doReturn(expectedTopicsWithRevokedConsent)
+ .when(mTopicsWorkerMock)
+ .getTopicsWithRevokedConsent();
+
+ ImmutableList<Topic> topicsWithRevokedConsent =
+ mConsentManager.getTopicsWithRevokedConsent();
+
+ assertThat(topicsWithRevokedConsent)
+ .containsExactlyElementsIn(expectedTopicsWithRevokedConsent);
+ }
+
+ @Test
+ public void testResetAllAppConsentAndAppData_ppApiOnly()
+ throws IOException, PackageManager.NameNotFoundException {
+ doNothing().when(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+
+ // Prepopulate with consent data for some apps
+ mConsentManager.enable(mContextSpy);
+ assertTrue(mConsentManager.getConsent().isGiven());
+
+ verify(() -> UiStatsLogger.logOptInSelected());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, true);
+ mDatastore.put(AppConsentDaoFixture.APP30_DATASTORE_KEY, false);
+ List<ApplicationInfo> applicationsInstalled =
+ createApplicationInfos(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ mockInstalledApplications(applicationsInstalled);
+
+ // Verify population was successful
+ ImmutableList<App> knownAppsWithConsent = mConsentManager.getKnownAppsWithConsent();
+ ImmutableList<App> appsWithRevokedConsent = mConsentManager.getAppsWithRevokedConsent();
+ assertThat(knownAppsWithConsent).hasSize(2);
+ assertThat(appsWithRevokedConsent).hasSize(1);
+
+ mConsentManager.clearAllAppConsentData();
+
+ // All app consent data was deleted
+ knownAppsWithConsent = mConsentManager.getKnownAppsWithConsent();
+ appsWithRevokedConsent = mConsentManager.getAppsWithRevokedConsent();
+ assertThat(knownAppsWithConsent).isEmpty();
+ assertThat(appsWithRevokedConsent).isEmpty();
+
+ SystemClock.sleep(1000);
+ verify(mCustomAudienceDaoMock, times(2)).deleteAllCustomAudienceData();
+ verify(mAppInstallDaoMock, times(2)).deleteAllAppInstallData();
+ verify(mFrequencyCapDaoMock, times(2)).deleteAllHistogramData();
+ }
+
+ @Test
+ public void testResetAllAppConsentAndAppData_systemServerOnly()
+ throws IOException, RemoteException {
+ doNothing().when(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+
+ mConsentManager.clearAllAppConsentData();
+
+ verify(mMockIAdServicesManager).clearAllAppConsentData();
+
+ SystemClock.sleep(1000);
+ verify(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+ verify(mAppInstallDaoMock).deleteAllAppInstallData();
+ verify(mFrequencyCapDaoMock).deleteAllHistogramData();
+ }
+
+ @Test
+ public void testResetAllAppConsentAndAppData_ppApiAndSystemServer()
+ throws IOException, PackageManager.NameNotFoundException, RemoteException {
+ doNothing().when(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+
+ // Prepopulate with consent data for some apps
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ mConsentManager.enable(mContextSpy);
+
+ verify(() -> UiStatsLogger.logOptInSelected());
+
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.ALL_API))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.ALL_API);
+ assertTrue(mConsentManager.getConsent().isGiven());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, true);
+ mDatastore.put(AppConsentDaoFixture.APP30_DATASTORE_KEY, false);
+ List<ApplicationInfo> applicationsInstalled =
+ createApplicationInfos(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ mockInstalledApplications(applicationsInstalled);
+
+ // Verify population was successful
+ List<App> knownAppsWithConsent =
+ mDatastore.keySetFalse().stream().map(App::create).collect(Collectors.toList());
+ List<App> appsWithRevokedConsent =
+ mDatastore.keySetTrue().stream().map(App::create).collect(Collectors.toList());
+ assertThat(knownAppsWithConsent).hasSize(2);
+ assertThat(appsWithRevokedConsent).hasSize(1);
+
+ mConsentManager.clearAllAppConsentData();
+
+ // All app consent data was deleted
+ knownAppsWithConsent =
+ mDatastore.keySetFalse().stream().map(App::create).collect(Collectors.toList());
+ appsWithRevokedConsent =
+ mDatastore.keySetTrue().stream().map(App::create).collect(Collectors.toList());
+ assertThat(knownAppsWithConsent).isEmpty();
+ assertThat(appsWithRevokedConsent).isEmpty();
+
+ verify(mMockIAdServicesManager, times(2)).clearAllAppConsentData();
+
+ SystemClock.sleep(1000);
+ verify(mCustomAudienceDaoMock, times(2)).deleteAllCustomAudienceData();
+ verify(mAppInstallDaoMock, times(2)).deleteAllAppInstallData();
+ verify(mFrequencyCapDaoMock, times(2)).deleteAllHistogramData();
+ }
+
+ @Test
+ public void testResetAllAppConsentAndAppData_appSearchOnly() throws Exception {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.APPSEARCH_ONLY);
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+
+ mConsentManager.clearKnownAppsWithConsent();
+ verify(mAppSearchConsentManagerMock).clearKnownAppsWithConsent();
+ }
+
+ @Test
+ public void testResetAllAppConsentAndAppData_ppapiAndAdExtDataServiceOnly() {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_ADEXT_SERVICE);
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+
+ assertThrows(IllegalStateException.class, () -> mConsentManager.clearAllAppConsentData());
+ }
+
+ @Test
+ public void testResetAllowedAppConsentAndAppData_ppApiOnly()
+ throws IOException, PackageManager.NameNotFoundException {
+ doNothing().when(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+
+ // Prepopulate with consent data for some apps
+ mConsentManager.enable(mContextSpy);
+ assertTrue(mConsentManager.getConsent().isGiven());
+
+ verify(() -> UiStatsLogger.logOptInSelected());
+
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, true);
+ mDatastore.put(AppConsentDaoFixture.APP30_DATASTORE_KEY, false);
+ List<ApplicationInfo> applicationsInstalled =
+ createApplicationInfos(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ mockInstalledApplications(applicationsInstalled);
+
+ // Verify population was successful
+ ImmutableList<App> knownAppsWithConsentBeforeReset =
+ mConsentManager.getKnownAppsWithConsent();
+ ImmutableList<App> appsWithRevokedConsentBeforeReset =
+ mConsentManager.getAppsWithRevokedConsent();
+ assertThat(knownAppsWithConsentBeforeReset).hasSize(2);
+ assertThat(appsWithRevokedConsentBeforeReset).hasSize(1);
+ mConsentManager.clearKnownAppsWithConsent();
+
+ // Known apps with consent were cleared; revoked apps were not deleted
+ ImmutableList<App> knownAppsWithConsentAfterReset =
+ mConsentManager.getKnownAppsWithConsent();
+ ImmutableList<App> appsWithRevokedConsentAfterReset =
+ mConsentManager.getAppsWithRevokedConsent();
+ assertThat(knownAppsWithConsentAfterReset).isEmpty();
+ assertThat(appsWithRevokedConsentAfterReset).hasSize(1);
+ assertThat(
+ appsWithRevokedConsentAfterReset.stream()
+ .map(App::getPackageName)
+ .collect(Collectors.toList()))
+ .containsExactlyElementsIn(
+ appsWithRevokedConsentBeforeReset.stream()
+ .map(App::getPackageName)
+ .collect(Collectors.toList()));
+
+ SystemClock.sleep(1000);
+ verify(mCustomAudienceDaoMock, times(2)).deleteAllCustomAudienceData();
+ verify(mAppInstallDaoMock, times(2)).deleteAllAppInstallData();
+ verify(mFrequencyCapDaoMock, times(2)).deleteAllHistogramData();
+ }
+
+ @Test
+ public void testResetAllowedAppConsentAndAppData_systemServerOnly()
+ throws IOException, RemoteException {
+ doNothing().when(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+
+ // Prepopulate with consent data for some apps
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.SYSTEM_SERVER_ONLY);
+ mConsentManager.clearKnownAppsWithConsent();
+
+ verify(mMockIAdServicesManager).clearKnownAppsWithConsent();
+
+ SystemClock.sleep(1000);
+ verify(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+ verify(mAppInstallDaoMock).deleteAllAppInstallData();
+ verify(mFrequencyCapDaoMock).deleteAllHistogramData();
+ }
+
+ @Test
+ public void testResetAllowedAppConsentAndAppData_ppApiAndSystemServer()
+ throws IOException, PackageManager.NameNotFoundException, RemoteException {
+ doNothing().when(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+
+ // Prepopulate with consent data for some apps
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_SYSTEM_SERVER);
+ doReturn(ConsentParcel.createGivenConsent(ConsentParcel.ALL_API))
+ .when(mMockIAdServicesManager)
+ .getConsent(ConsentParcel.ALL_API);
+ assertTrue(mConsentManager.getConsent().isGiven());
+ mockGetPackageUid(AppConsentDaoFixture.APP10_PACKAGE_NAME, AppConsentDaoFixture.APP10_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP20_PACKAGE_NAME, AppConsentDaoFixture.APP20_UID);
+ mockGetPackageUid(AppConsentDaoFixture.APP30_PACKAGE_NAME, AppConsentDaoFixture.APP30_UID);
+
+ mDatastore.put(AppConsentDaoFixture.APP10_DATASTORE_KEY, false);
+ mDatastore.put(AppConsentDaoFixture.APP20_DATASTORE_KEY, true);
+ mDatastore.put(AppConsentDaoFixture.APP30_DATASTORE_KEY, false);
+ List<ApplicationInfo> applicationsInstalled =
+ createApplicationInfos(
+ AppConsentDaoFixture.APP10_PACKAGE_NAME,
+ AppConsentDaoFixture.APP20_PACKAGE_NAME,
+ AppConsentDaoFixture.APP30_PACKAGE_NAME);
+ mockInstalledApplications(applicationsInstalled);
+
+ // Verify population was successful
+ List<App> knownAppsWithConsentBeforeReset =
+ mDatastore.keySetFalse().stream().map(App::create).collect(Collectors.toList());
+ List<App> appsWithRevokedConsentBeforeReset =
+ mDatastore.keySetTrue().stream().map(App::create).collect(Collectors.toList());
+ assertThat(knownAppsWithConsentBeforeReset).hasSize(2);
+ assertThat(appsWithRevokedConsentBeforeReset).hasSize(1);
+ mConsentManager.clearKnownAppsWithConsent();
+
+ // Known apps with consent were cleared; revoked apps were not deleted
+ List<App> knownAppsWithConsentAfterReset =
+ mDatastore.keySetFalse().stream().map(App::create).collect(Collectors.toList());
+ List<App> appsWithRevokedConsentAfterReset =
+ mDatastore.keySetTrue().stream().map(App::create).collect(Collectors.toList());
+ assertThat(knownAppsWithConsentAfterReset).isEmpty();
+ assertThat(appsWithRevokedConsentAfterReset).hasSize(1);
+ assertThat(
+ appsWithRevokedConsentAfterReset.stream()
+ .map(App::getPackageName)
+ .collect(Collectors.toList()))
+ .containsExactlyElementsIn(
+ appsWithRevokedConsentBeforeReset.stream()
+ .map(App::getPackageName)
+ .collect(Collectors.toList()));
+
+ verify(mMockIAdServicesManager).clearKnownAppsWithConsent();
+
+ SystemClock.sleep(1000);
+ verify(mCustomAudienceDaoMock).deleteAllCustomAudienceData();
+ verify(mAppInstallDaoMock).deleteAllAppInstallData();
+ verify(mFrequencyCapDaoMock).deleteAllHistogramData();
+ }
+
+ @Test
+ public void testResetAllowedAppConsentAndAppData_appSearchOnly() throws Exception {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.APPSEARCH_ONLY);
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+
+ mConsentManager.clearKnownAppsWithConsent();
+ verify(mAppSearchConsentManagerMock).clearKnownAppsWithConsent();
+ }
+
+ @Test
+ public void testResetAllowedAppConsentAndAppData_ppapiAndAdExtDataServiceOnly() {
+ mConsentManager = getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_AND_ADEXT_SERVICE);
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+
+ assertThrows(
+ IllegalStateException.class, () -> mConsentManager.clearKnownAppsWithConsent());
+ }
+
+ @Test
+ public void testNotificationDisplayedRecorded_PpApiOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.wasNotificationDisplayed()).isFalse();
+
+ verify(mMockIAdServicesManager, never()).wasNotificationDisplayed();
+
+ spyConsentManager.recordNotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasNotificationDisplayed()).isTrue();
+
+ verify(mMockIAdServicesManager, never()).wasNotificationDisplayed();
+ verify(mMockIAdServicesManager, never()).recordNotificationDisplayed(true);
+ }
+
+ @Test
+ public void testNotificationDisplayedRecorded_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.wasNotificationDisplayed()).isFalse();
+
+ verify(mMockIAdServicesManager).wasNotificationDisplayed();
+
+ doReturn(true).when(mMockIAdServicesManager).wasNotificationDisplayed();
+ spyConsentManager.recordNotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasNotificationDisplayed()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).wasNotificationDisplayed();
+ verify(mMockIAdServicesManager).recordNotificationDisplayed(true);
+
+ // Verify notificationDisplayed is not set in PPAPI
+ assertThat(mConsentDatastore.get(NOTIFICATION_DISPLAYED_ONCE)).isFalse();
+ }
+
+ @Test
+ public void testNotificationDisplayedRecorded_PpApiAndSystemServer() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ Boolean wasNotificationDisplayed = spyConsentManager.wasNotificationDisplayed();
+
+ assertThat(wasNotificationDisplayed).isFalse();
+
+ verify(mMockIAdServicesManager).wasNotificationDisplayed();
+
+ doReturn(true).when(mMockIAdServicesManager).wasNotificationDisplayed();
+ spyConsentManager.recordNotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasNotificationDisplayed()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).wasNotificationDisplayed();
+ verify(mMockIAdServicesManager).recordNotificationDisplayed(true);
+
+ // Verify notificationDisplayed is also set in PPAPI
+ assertThat(mConsentDatastore.get(NOTIFICATION_DISPLAYED_ONCE)).isTrue();
+ }
+
+ @Test
+ public void testNotificationDisplayedRecorded_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(false).when(mAppSearchConsentManagerMock).wasNotificationDisplayed();
+ assertThat(spyConsentManager.wasNotificationDisplayed()).isFalse();
+ verify(mAppSearchConsentManagerMock).wasNotificationDisplayed();
+
+ doReturn(true).when(mAppSearchConsentManagerMock).wasNotificationDisplayed();
+ spyConsentManager.recordNotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasNotificationDisplayed()).isTrue();
+
+ verify(mAppSearchConsentManagerMock, times(2)).wasNotificationDisplayed();
+ verify(mAppSearchConsentManagerMock).recordNotificationDisplayed(true);
+ }
+
+ @Test
+ public void testNotificationDisplayedRecorded_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.wasNotificationDisplayed()).isFalse();
+ }
+
+ @Test
+ public void testGaUxNotificationDisplayedRecorded_PpApiOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.wasGaUxNotificationDisplayed()).isFalse();
+
+ verify(mMockIAdServicesManager, never()).wasGaUxNotificationDisplayed();
+
+ spyConsentManager.recordGaUxNotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasGaUxNotificationDisplayed()).isTrue();
+
+ verify(mMockIAdServicesManager, never()).wasGaUxNotificationDisplayed();
+ verify(mMockIAdServicesManager, never()).recordGaUxNotificationDisplayed(true);
+ }
+
+ @Test
+ public void testGaUxNotificationDisplayedRecorded_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.wasGaUxNotificationDisplayed()).isFalse();
+
+ verify(mMockIAdServicesManager).wasGaUxNotificationDisplayed();
+
+ doReturn(true).when(mMockIAdServicesManager).wasGaUxNotificationDisplayed();
+ spyConsentManager.recordGaUxNotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasGaUxNotificationDisplayed()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).wasGaUxNotificationDisplayed();
+ verify(mMockIAdServicesManager).recordGaUxNotificationDisplayed(true);
+
+ // Verify notificationDisplayed is not set in PPAPI
+ assertThat(mConsentDatastore.get(GA_UX_NOTIFICATION_DISPLAYED_ONCE)).isFalse();
+ }
+
+ @Test
+ public void testGaUxNotificationDisplayedRecorded_PpApiAndSystemServer()
+ throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ Boolean wasGaUxNotificationDisplayed = spyConsentManager.wasGaUxNotificationDisplayed();
+
+ assertThat(wasGaUxNotificationDisplayed).isFalse();
+
+ verify(mMockIAdServicesManager).wasGaUxNotificationDisplayed();
+
+ doReturn(true).when(mMockIAdServicesManager).wasGaUxNotificationDisplayed();
+ spyConsentManager.recordGaUxNotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasGaUxNotificationDisplayed()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).wasGaUxNotificationDisplayed();
+ verify(mMockIAdServicesManager).recordGaUxNotificationDisplayed(true);
+
+ // Verify notificationDisplayed is also set in PPAPI
+ assertThat(mConsentDatastore.get(GA_UX_NOTIFICATION_DISPLAYED_ONCE)).isTrue();
+ }
+
+ @Test
+ public void testGaUxNotificationDisplayedRecorded_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ when(mAppSearchConsentManagerMock.wasGaUxNotificationDisplayed()).thenReturn(false);
+ assertThat(spyConsentManager.wasGaUxNotificationDisplayed()).isFalse();
+ verify(mAppSearchConsentManagerMock).wasGaUxNotificationDisplayed();
+
+ when(mAppSearchConsentManagerMock.wasGaUxNotificationDisplayed()).thenReturn(true);
+ spyConsentManager.recordGaUxNotificationDisplayed(true);
+ assertThat(spyConsentManager.wasGaUxNotificationDisplayed()).isTrue();
+
+ verify(mAppSearchConsentManagerMock, times(2)).wasGaUxNotificationDisplayed();
+ verify(mAppSearchConsentManagerMock).recordGaUxNotificationDisplayed(true);
+ }
+
+ @Test
+ public void testGaUxNotificationDisplayedRecorded_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.wasGaUxNotificationDisplayed()).isFalse();
+ }
+
+ @Test
+ public void testNotificationDisplayedRecorded_notSupportedFlag() throws RemoteException {
+ int invalidConsentSourceOfTruth = 5;
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, invalidConsentSourceOfTruth));
+ }
+
+ @Test
+ public void testClearPpApiConsent() throws IOException {
+ mConsentDatastore.put(CONSENT_KEY, true);
+ mConsentDatastore.put(NOTIFICATION_DISPLAYED_ONCE, true);
+ assertThat(mConsentDatastore.get(CONSENT_KEY)).isTrue();
+ assertThat(mConsentDatastore.get(NOTIFICATION_DISPLAYED_ONCE)).isTrue();
+
+ ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore);
+ assertThat(mConsentDatastore.get(CONSENT_KEY)).isNull();
+ assertThat(mConsentDatastore.get(NOTIFICATION_DISPLAYED_ONCE)).isNull();
+
+ // Verify this should only happen once
+ mConsentDatastore.put(CONSENT_KEY, true);
+ mConsentDatastore.put(NOTIFICATION_DISPLAYED_ONCE, true);
+ assertThat(mConsentDatastore.get(CONSENT_KEY)).isTrue();
+ assertThat(mConsentDatastore.get(NOTIFICATION_DISPLAYED_ONCE)).isTrue();
+ // Consent is not cleared again
+ ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore);
+ assertThat(mConsentDatastore.get(CONSENT_KEY)).isTrue();
+ assertThat(mConsentDatastore.get(NOTIFICATION_DISPLAYED_ONCE)).isTrue();
+
+ // Clear shared preference
+ ConsentManagerV2.resetSharedPreference(mContextSpy, SHARED_PREFS_KEY_PPAPI_HAS_CLEARED);
+ }
+
+ @Test
+ public void testMigratePpApiConsentToSystemService() throws RemoteException, IOException {
+ // Disable IPC calls
+ doNothing().when(mMockIAdServicesManager).setConsent(any());
+ doNothing().when(mMockIAdServicesManager).recordNotificationDisplayed(true);
+
+ mConsentDatastore.put(CONSENT_KEY, true);
+ mConsentDatastore.put(NOTIFICATION_DISPLAYED_ONCE, true);
+ assertThat(mConsentDatastore.get(CONSENT_KEY)).isTrue();
+ assertThat(mConsentDatastore.get(NOTIFICATION_DISPLAYED_ONCE)).isTrue();
+
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+
+ verify(mMockIAdServicesManager).setConsent(any());
+ verify(mMockIAdServicesManager).recordNotificationDisplayed(true);
+
+ // Verify this should only happen once
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+ verify(mMockIAdServicesManager).setConsent(any());
+ verify(mMockIAdServicesManager).recordNotificationDisplayed(true);
+
+ // Clear shared preference
+ ConsentManagerV2.resetSharedPreference(mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED);
+ }
+
+ @Test
+ public void testMigratePpApiConsentToSystemServiceWithSuccessfulConsentMigrationLogging()
+ throws RemoteException, IOException {
+ // Disable IPC calls
+ doNothing().when(mMockIAdServicesManager).setConsent(any());
+ doNothing().when(mMockIAdServicesManager).recordNotificationDisplayed(true);
+ mConsentDatastore.put(CONSENT_KEY, true);
+ mConsentDatastore.put(NOTIFICATION_DISPLAYED_ONCE, true);
+ assertThat(mConsentDatastore.get(CONSENT_KEY)).isTrue();
+ assertThat(mConsentDatastore.get(NOTIFICATION_DISPLAYED_ONCE)).isTrue();
+
+ SharedPreferences sharedPreferences =
+ mContextSpy.getSharedPreferences(SHARED_PREFS_CONSENT, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+
+ editor.putBoolean(SHARED_PREFS_KEY_HAS_MIGRATED, false);
+ editor.putBoolean(SHARED_PREFS_KEY_APPSEARCH_HAS_MIGRATED, false);
+ editor.commit();
+ ExtendedMockito.doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any()));
+
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+
+ ConsentMigrationStats consentMigrationStats =
+ ConsentMigrationStats.builder()
+ .setTopicsConsent(true)
+ .setFledgeConsent(true)
+ .setMsmtConsent(true)
+ .setDefaultConsent(true)
+ .setMigrationStatus(
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_UPDATED)
+ .setMigrationType(
+ ConsentMigrationStats.MigrationType.PPAPI_TO_SYSTEM_SERVICE)
+ .setRegion(2)
+ .build();
+
+ verify(mStatsdAdServicesLoggerMock).logConsentMigrationStats(consentMigrationStats);
+
+ // Clear shared preference
+ ConsentManagerV2.resetSharedPreference(mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED);
+ ConsentManagerV2.resetSharedPreference(
+ mContextSpy, SHARED_PREFS_KEY_APPSEARCH_HAS_MIGRATED);
+ }
+
+ @Test
+ public void testMigratePpApiConsentToSystemServiceWithUnSuccessfulConsentMigrationLogging()
+ throws RemoteException, IOException {
+ // Disable IPC calls
+ doNothing().when(mMockIAdServicesManager).setConsent(any());
+ doNothing().when(mMockIAdServicesManager).recordNotificationDisplayed(true);
+ mConsentDatastore.put(CONSENT_KEY, true);
+ mConsentDatastore.put(NOTIFICATION_DISPLAYED_ONCE, true);
+
+ SharedPreferences sharedPreferences = mock(SharedPreferences.class);
+ SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class);
+ doReturn(editor).when(sharedPreferences).edit();
+ doReturn(false).when(editor).commit();
+ doReturn(sharedPreferences).when(mContextSpy).getSharedPreferences(anyString(), anyInt());
+
+ doNothing().when(() -> ErrorLogUtil.e(anyInt(), anyInt()));
+ doNothing().when(mStatsdAdServicesLoggerMock).logConsentMigrationStats(any());
+ ExtendedMockito.doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any()));
+
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+
+ ConsentMigrationStats consentMigrationStats =
+ ConsentMigrationStats.builder()
+ .setTopicsConsent(true)
+ .setFledgeConsent(true)
+ .setMsmtConsent(true)
+ .setDefaultConsent(true)
+ .setMigrationStatus(
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_NOT_UPDATED)
+ .setMigrationType(
+ ConsentMigrationStats.MigrationType.PPAPI_TO_SYSTEM_SERVICE)
+ .setRegion(2)
+ .build();
+
+ verify(mStatsdAdServicesLoggerMock).logConsentMigrationStats(consentMigrationStats);
+
+ doReturn(true).when(editor).commit();
+ // Clear shared preference
+ ConsentManagerV2.resetSharedPreference(mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED);
+ }
+
+ @Test
+ public void testMigratePpApiConsentToSystemServiceThrowsException()
+ throws RemoteException, IOException {
+ mConsentDatastore.put(NOTIFICATION_DISPLAYED_ONCE, true);
+ doThrow(RemoteException.class)
+ .when(mMockIAdServicesManager)
+ .recordNotificationDisplayed(true);
+
+ doNothing().when(() -> ErrorLogUtil.e(anyInt(), anyInt()));
+ doNothing().when(mStatsdAdServicesLoggerMock).logConsentMigrationStats(any());
+ ExtendedMockito.doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any()));
+
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+
+ ConsentMigrationStats consentMigrationStats =
+ ConsentMigrationStats.builder()
+ .setTopicsConsent(true)
+ .setFledgeConsent(true)
+ .setMsmtConsent(true)
+ .setDefaultConsent(true)
+ .setMigrationStatus(ConsentMigrationStats.MigrationStatus.FAILURE)
+ .setMigrationType(
+ ConsentMigrationStats.MigrationType.PPAPI_TO_SYSTEM_SERVICE)
+ .setRegion(2)
+ .build();
+
+ verify(mStatsdAdServicesLoggerMock).logConsentMigrationStats(consentMigrationStats);
+
+ // Clear shared preference
+ ConsentManagerV2.resetSharedPreference(mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED);
+ }
+
+ @Test
+ public void testHandleConsentMigrationIfNeeded_ExtServices() throws RemoteException {
+ doReturn("com." + AdServicesCommon.ADEXTSERVICES_PACKAGE_NAME_SUFFIX)
+ .when(mContextSpy)
+ .getPackageName();
+
+ ConsentManagerV2.handleConsentMigrationIfNeeded(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock,
+ Flags.PPAPI_AND_SYSTEM_SERVER);
+
+ verify(mContextSpy, never()).getSharedPreferences(anyString(), anyInt());
+ verify(mMockIAdServicesManager, never()).setConsent(any());
+ }
+
+ @Test
+ public void testHandleConsentMigrationFromAppSearchIfNeeded_ExtServices() throws Exception {
+ doReturn("com." + AdServicesCommon.ADEXTSERVICES_PACKAGE_NAME_SUFFIX)
+ .when(mContextSpy)
+ .getPackageName();
+ SharedPreferences mockSharedPrefs = mock(SharedPreferences.class);
+ SharedPreferences.Editor mockEditor = mock(SharedPreferences.Editor.class);
+ when(mockSharedPrefs.edit()).thenReturn(mockEditor);
+ when(mContextSpy.getSharedPreferences(any(String.class), anyInt()))
+ .thenReturn(mockSharedPrefs);
+ ConsentManagerV2.handleConsentMigrationFromAppSearchIfNeeded(
+ mContextSpy,
+ mDatastore,
+ mAppConsentDaoSpy,
+ mAppSearchConsentManagerMock,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+
+ verify(mContextSpy, never()).getSharedPreferences(anyString(), anyInt());
+ verify(mAppSearchConsentManagerMock, never())
+ .migrateConsentDataIfNeeded(any(), any(), any(), any());
+ verify(mMockIAdServicesManager, never()).setConsent(any());
+ verify(mMockIAdServicesManager, never()).recordNotificationDisplayed(true);
+ verify(mMockIAdServicesManager, never()).recordGaUxNotificationDisplayed(true);
+ verify(mMockIAdServicesManager, never()).recordDefaultConsent(anyBoolean());
+ verify(mMockIAdServicesManager, never()).recordAdServicesDeletionOccurred(anyInt());
+ verify(mMockIAdServicesManager, never()).recordDefaultAdIdState(anyBoolean());
+ verify(mMockIAdServicesManager, never()).recordFledgeDefaultConsent(anyBoolean());
+ verify(mMockIAdServicesManager, never()).recordMeasurementDefaultConsent(anyBoolean());
+ verify(mMockIAdServicesManager, never()).recordTopicsDefaultConsent(anyBoolean());
+ verify(mMockIAdServicesManager, never()).recordUserManualInteractionWithConsent(anyInt());
+ verify(mockEditor, never()).putBoolean(any(), anyBoolean());
+ }
+
+ @Test
+ public void testResetSharedPreference() {
+ SharedPreferences sharedPreferences =
+ FileCompatUtils.getSharedPreferencesHelper(
+ mContextSpy, SHARED_PREFS_CONSENT, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+
+ editor.putBoolean(SHARED_PREFS_KEY_PPAPI_HAS_CLEARED, true);
+ editor.putBoolean(SHARED_PREFS_KEY_HAS_MIGRATED, true);
+ editor.commit();
+
+ assertThat(
+ sharedPreferences.getBoolean(
+ SHARED_PREFS_KEY_PPAPI_HAS_CLEARED, /* defValue */ false))
+ .isTrue();
+ assertThat(
+ sharedPreferences.getBoolean(
+ SHARED_PREFS_KEY_HAS_MIGRATED, /* defValue */ false))
+ .isTrue();
+
+ resetSharedPreference(mContextSpy, SHARED_PREFS_KEY_PPAPI_HAS_CLEARED);
+ resetSharedPreference(mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED);
+
+ assertThat(
+ sharedPreferences.getBoolean(
+ SHARED_PREFS_KEY_PPAPI_HAS_CLEARED, /* defValue */ true))
+ .isFalse();
+ assertThat(sharedPreferences.getBoolean(SHARED_PREFS_KEY_HAS_MIGRATED, /* defValue */ true))
+ .isFalse();
+ }
+
+ @Test
+ public void testHandleConsentMigrationIfNeeded_PpApiOnly() {
+ // Disable actual execution of internal methods
+ doNothing()
+ .when(
+ () ->
+ ConsentManagerV2.resetSharedPreference(
+ mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED));
+ doNothing()
+ .when(
+ () ->
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock));
+ doNothing().when(() -> ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore));
+
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2.handleConsentMigrationIfNeeded(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock,
+ consentSourceOfTruth);
+
+ verify(
+ () ->
+ ConsentManagerV2.resetSharedPreference(
+ mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED));
+ verify(
+ () ->
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock),
+ never());
+ verify(() -> ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore), never());
+ }
+
+ @Test
+ public void testHandleConsentMigrationIfNeeded_SystemServerOnly() {
+ // Disable actual execution of internal methods
+ doNothing()
+ .when(
+ () ->
+ ConsentManagerV2.resetSharedPreference(
+ mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED));
+ doNothing()
+ .when(
+ () ->
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock));
+ doNothing().when(() -> ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore));
+
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2.handleConsentMigrationIfNeeded(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock,
+ consentSourceOfTruth);
+
+ verify(
+ () ->
+ ConsentManagerV2.resetSharedPreference(
+ mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED),
+ never());
+ verify(
+ () ->
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock));
+ verify(() -> ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore));
+ }
+
+ @Test
+ public void testHandleConsentMigrationIfNeeded_PpApiAndSystemServer() {
+ // Disable actual execution of internal methods
+ doNothing()
+ .when(
+ () ->
+ ConsentManagerV2.resetSharedPreference(
+ mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED));
+ doNothing()
+ .when(
+ () ->
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock));
+ doNothing().when(() -> ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore));
+
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2.handleConsentMigrationIfNeeded(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock,
+ consentSourceOfTruth);
+
+ verify(
+ () ->
+ ConsentManagerV2.resetSharedPreference(
+ mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED),
+ never());
+ verify(
+ () ->
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock));
+ verify(() -> ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore), never());
+ }
+
+ @Test
+ public void testHandleConsentMigrationIfNeeded_AppSearchOnly() {
+ // Disable actual execution of internal methods
+ doNothing()
+ .when(
+ () ->
+ ConsentManagerV2.resetSharedPreference(
+ mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED));
+ doNothing()
+ .when(
+ () ->
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock));
+ doNothing().when(() -> ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore));
+
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2.handleConsentMigrationIfNeeded(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock,
+ consentSourceOfTruth);
+
+ verify(
+ () ->
+ ConsentManagerV2.resetSharedPreference(
+ mContextSpy, SHARED_PREFS_KEY_HAS_MIGRATED),
+ never());
+ verify(
+ () ->
+ ConsentManagerV2.migratePpApiConsentToSystemService(
+ mContextSpy,
+ mConsentDatastore,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock),
+ never());
+ verify(() -> ConsentManagerV2.clearPpApiConsent(mContextSpy, mConsentDatastore), never());
+ }
+
+ @Test
+ public void testHandleConsentMigrationFromAppSearchIfNeeded_notMigrated() throws Exception {
+ when(mAppSearchConsentManagerMock.migrateConsentDataIfNeeded(any(), any(), any(), any()))
+ .thenReturn(false);
+ BooleanFileDatastore mockDatastore = mock(BooleanFileDatastore.class);
+
+ SharedPreferences mockSharedPrefs = mock(SharedPreferences.class);
+ SharedPreferences.Editor mockEditor = mock(SharedPreferences.Editor.class);
+ when(mockSharedPrefs.edit()).thenReturn(mockEditor);
+ when(mContextSpy.getSharedPreferences(any(String.class), anyInt()))
+ .thenReturn(mockSharedPrefs);
+
+ ConsentManagerV2.handleConsentMigrationFromAppSearchIfNeeded(
+ mContextSpy,
+ mockDatastore,
+ mAppConsentDaoSpy,
+ mAppSearchConsentManagerMock,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+ verify(mockEditor, never()).putBoolean(any(), anyBoolean());
+ verify(mAppSearchConsentManagerMock).migrateConsentDataIfNeeded(any(), any(), any(), any());
+ verify(mAppSearchConsentManagerMock, never()).recordNotificationDisplayed(true);
+ verify(mAppSearchConsentManagerMock, never()).recordGaUxNotificationDisplayed(true);
+ verify(mAppSearchConsentManagerMock, never()).recordDefaultConsent(any(), anyBoolean());
+
+ verify(mAppSearchConsentManagerMock, never()).recordDefaultAdIdState(anyBoolean());
+ verify(mAppSearchConsentManagerMock, never()).recordDefaultConsent(any(), anyBoolean());
+
+ verify(mAppSearchConsentManagerMock, never())
+ .recordUserManualInteractionWithConsent(anyInt());
+ }
+
+ @Test
+ public void testHandleConsentMigrationFromAppSearchIfNeeded() throws Exception {
+ when(mAppSearchConsentManagerMock.migrateConsentDataIfNeeded(any(), any(), any(), any()))
+ .thenReturn(true);
+ when(mAppSearchConsentManagerMock.getConsent(any())).thenReturn(AdServicesApiConsent.GIVEN);
+ when(mAppSearchConsentManagerMock.getDefaultConsent(any()))
+ .thenReturn(AdServicesApiConsent.GIVEN);
+ mConsentDatastore.put(CONSENT_KEY, true);
+ mConsentDatastore.put(NOTIFICATION_DISPLAYED_ONCE, true);
+
+ SharedPreferences mockSharedPrefs = mock(SharedPreferences.class);
+ SharedPreferences.Editor mockEditor = mock(SharedPreferences.Editor.class);
+ when(mockSharedPrefs.edit()).thenReturn(mockEditor);
+ when(mContextSpy.getSharedPreferences(any(String.class), anyInt()))
+ .thenReturn(mockSharedPrefs);
+ when(mAppSearchConsentManagerMock.getUserManualInteractionWithConsent())
+ .thenReturn(MANUAL_INTERACTIONS_RECORDED);
+ when(mockEditor.commit()).thenReturn(true);
+ ExtendedMockito.doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any()));
+
+ ConsentManagerV2.handleConsentMigrationFromAppSearchIfNeeded(
+ mContextSpy,
+ mConsentDatastore,
+ mAppConsentDaoSpy,
+ mAppSearchConsentManagerMock,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+ verify(mAppSearchConsentManagerMock).migrateConsentDataIfNeeded(any(), any(), any(), any());
+
+ // Verify interactions data is migrated.
+ assertThat(mConsentDatastore.get(ConsentConstants.MANUAL_INTERACTION_WITH_CONSENT_RECORDED))
+ .isTrue();
+ verify(mAdServicesStorageManager).recordUserManualInteractionWithConsent(anyInt());
+
+ // Verify migration is recorded.
+ verify(mockEditor)
+ .putBoolean(eq(ConsentConstants.SHARED_PREFS_KEY_APPSEARCH_HAS_MIGRATED), eq(true));
+
+ // Verify default consents data is migrated.
+ assertThat(mConsentDatastore.get(ConsentConstants.TOPICS_DEFAULT_CONSENT)).isTrue();
+ assertThat(mConsentDatastore.get(ConsentConstants.FLEDGE_DEFAULT_CONSENT)).isTrue();
+ assertThat(mConsentDatastore.get(ConsentConstants.MEASUREMENT_DEFAULT_CONSENT)).isTrue();
+ assertThat(mConsentDatastore.get(ConsentConstants.CONSENT_KEY)).isTrue();
+ assertThat(mConsentDatastore.get(ConsentConstants.DEFAULT_CONSENT)).isTrue();
+ verify(mAdServicesStorageManager)
+ .recordDefaultConsent(eq(AdServicesApiType.ALL_API), eq(true));
+ verify(mAdServicesStorageManager)
+ .recordDefaultConsent(eq(AdServicesApiType.TOPICS), eq(true));
+ verify(mAdServicesStorageManager)
+ .recordDefaultConsent(eq(AdServicesApiType.MEASUREMENTS), eq(true));
+ verify(mAdServicesStorageManager)
+ .recordDefaultConsent(eq(AdServicesApiType.FLEDGE), eq(true));
+
+ // Verify per API consents data is migrated.
+ assertThat(mConsentDatastore.get(AdServicesApiType.TOPICS.toPpApiDatastoreKey())).isTrue();
+ assertThat(mConsentDatastore.get(AdServicesApiType.FLEDGE.toPpApiDatastoreKey())).isTrue();
+ assertThat(mConsentDatastore.get(AdServicesApiType.MEASUREMENTS.toPpApiDatastoreKey()))
+ .isTrue();
+ verify(mAdServicesStorageManager, atLeast(4)).recordDefaultConsent(any(), anyBoolean());
+ ExtendedMockito.doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any()));
+
+ ConsentMigrationStats consentMigrationStats =
+ ConsentMigrationStats.builder()
+ .setTopicsConsent(true)
+ .setFledgeConsent(true)
+ .setMsmtConsent(true)
+ .setDefaultConsent(true)
+ .setMigrationStatus(
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_UPDATED)
+ .setMigrationType(
+ ConsentMigrationStats.MigrationType.APPSEARCH_TO_SYSTEM_SERVICE)
+ .setRegion(2)
+ .build();
+
+ verify(mStatsdAdServicesLoggerMock).logConsentMigrationStats(consentMigrationStats);
+ }
+
+ @Test
+ public void testHandleConsentMigrationFromAppSearchIfNeededSharedPrefsEditorUnsuccessful()
+ throws Exception {
+ when(mAppSearchConsentManagerMock.migrateConsentDataIfNeeded(any(), any(), any(), any()))
+ .thenReturn(true);
+ when(mAppSearchConsentManagerMock.getConsent(any())).thenReturn(AdServicesApiConsent.GIVEN);
+ when(mAppSearchConsentManagerMock.getDefaultConsent(any()))
+ .thenReturn(AdServicesApiConsent.GIVEN);
+ mConsentDatastore.put(CONSENT_KEY, true);
+ mConsentDatastore.put(NOTIFICATION_DISPLAYED_ONCE, true);
+
+ SharedPreferences mockSharedPrefs = mock(SharedPreferences.class);
+ SharedPreferences.Editor mockEditor = mock(SharedPreferences.Editor.class);
+ when(mockSharedPrefs.edit()).thenReturn(mockEditor);
+ when(mContextSpy.getSharedPreferences(any(String.class), anyInt()))
+ .thenReturn(mockSharedPrefs);
+ when(mAppSearchConsentManagerMock.getUserManualInteractionWithConsent())
+ .thenReturn(MANUAL_INTERACTIONS_RECORDED);
+ when(mockEditor.commit()).thenReturn(false);
+ doNothing().when(() -> ErrorLogUtil.e(any(), anyInt(), anyInt()));
+ ExtendedMockito.doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any()));
+
+ ConsentManagerV2.handleConsentMigrationFromAppSearchIfNeeded(
+ mContextSpy,
+ mConsentDatastore,
+ mAppConsentDaoSpy,
+ mAppSearchConsentManagerMock,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+
+ ConsentMigrationStats consentMigrationStats =
+ ConsentMigrationStats.builder()
+ .setTopicsConsent(true)
+ .setFledgeConsent(true)
+ .setMsmtConsent(true)
+ .setDefaultConsent(true)
+ .setMigrationStatus(
+ ConsentMigrationStats.MigrationStatus
+ .SUCCESS_WITH_SHARED_PREF_NOT_UPDATED)
+ .setMigrationType(
+ ConsentMigrationStats.MigrationType.APPSEARCH_TO_SYSTEM_SERVICE)
+ .setRegion(2)
+ .build();
+
+ verify(mStatsdAdServicesLoggerMock).logConsentMigrationStats(consentMigrationStats);
+ }
+
+ @Test
+ public void testHandleConsentMigrationFromAppSearchIfNeededThrowsException() throws Exception {
+ when(mAppSearchConsentManagerMock.migrateConsentDataIfNeeded(any(), any(), any(), any()))
+ .thenThrow(IOException.class);
+
+ doNothing().when(() -> ErrorLogUtil.e(any(), anyInt(), anyInt()));
+ doNothing().when(mStatsdAdServicesLoggerMock).logConsentMigrationStats(any());
+
+ doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any()));
+
+ ConsentManagerV2.handleConsentMigrationFromAppSearchIfNeeded(
+ mContextSpy,
+ mConsentDatastore,
+ mAppConsentDaoSpy,
+ mAppSearchConsentManagerMock,
+ mAdServicesStorageManager,
+ mStatsdAdServicesLoggerMock);
+
+ ConsentMigrationStats consentMigrationStats =
+ ConsentMigrationStats.builder()
+ .setTopicsConsent(true)
+ .setFledgeConsent(true)
+ .setMsmtConsent(true)
+ .setDefaultConsent(true)
+ .setMigrationStatus(ConsentMigrationStats.MigrationStatus.FAILURE)
+ .setMigrationType(
+ ConsentMigrationStats.MigrationType.APPSEARCH_TO_SYSTEM_SERVICE)
+ .setRegion(2)
+ .build();
+ Mockito.verify(mStatsdAdServicesLoggerMock).logConsentMigrationStats(consentMigrationStats);
+ }
+
+ @Test
+ public void testTopicsProxyCalls() {
+ Topic topic = Topic.create(1, 1, 1);
+ ArrayList<String> tablesToBlock = new ArrayList<>();
+ tablesToBlock.add(TopicsTables.BlockedTopicsContract.TABLE);
+
+ TopicsWorker topicsWorker =
+ spy(
+ new TopicsWorker(
+ mMockEpochManager,
+ mCacheManagerMock,
+ mBlockedTopicsManagerMock,
+ mAppUpdateManagerMock,
+ mMockFlags));
+
+ ConsentManagerV2 consentManager =
+ new ConsentManagerV2(
+ topicsWorker,
+ mAppConsentDaoSpy,
+ mEnrollmentDaoSpy,
+ mMeasurementImplMock,
+ mCustomAudienceDaoMock,
+ mAppConsentStorageManager,
+ mAppInstallDaoMock,
+ mFrequencyCapDaoMock,
+ mAdServicesStorageManager,
+ mConsentDatastore,
+ mAppSearchConsentManagerMock,
+ mUserProfileIdManagerMock,
+ mAppConsentForRStorageManager,
+ mMockFlags,
+ Flags.PPAPI_ONLY,
+ true,
+ true);
+
+ doNothing().when(mBlockedTopicsManagerMock).blockTopic(any());
+ doNothing().when(mBlockedTopicsManagerMock).unblockTopic(any());
+ // The actual usage is to invoke clearAllTopicsData() from TopicsWorker
+ doNothing().when(topicsWorker).clearAllTopicsData(any());
+
+ consentManager.revokeConsentForTopic(topic);
+ consentManager.restoreConsentForTopic(topic);
+ consentManager.resetTopics();
+
+ verify(mBlockedTopicsManagerMock).blockTopic(topic);
+ verify(mBlockedTopicsManagerMock).unblockTopic(topic);
+ verify(topicsWorker).clearAllTopicsData(tablesToBlock);
+ }
+
+ @Test
+ public void testLoggingSettingsUsageReportedOptInSelectedRow() {
+ doReturn(false).when(() -> DeviceRegionProvider.isEuDevice(any(Context.class)));
+ ConsentManagerV2 temporalConsentManagerV2 =
+ getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_ONLY);
+
+ temporalConsentManagerV2.enable(mContextSpy);
+
+ verify(mUiStatsLoggerMock).logOptInSelected();
+ }
+
+ @Test
+ public void testLoggingSettingsUsageReportedOptInSelectedEu() {
+ doReturn(true).when(() -> DeviceRegionProvider.isEuDevice(any(Context.class)));
+ ConsentManagerV2 temporalConsentManagerV2 =
+ getConsentManagerByConsentSourceOfTruth(Flags.PPAPI_ONLY);
+
+ temporalConsentManagerV2.enable(mContextSpy);
+
+ verify(mUiStatsLoggerMock).logOptInSelected();
+ }
+
+ @Test
+ public void testConsentPerApiIsGivenAfterEnabling_PpApiOnly()
+ throws RemoteException, IOException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.TOPICS);
+
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven()).isTrue();
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(
+ eq(/* isGiven */ true), eq(AdServicesApiType.TOPICS));
+
+ verify(spyConsentManager).resetTopicsAndBlockedTopics();
+ }
+
+ @Test
+ public void testConsentPerApiIsGivenAfterEnabling_SystemServerOnly() throws RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ doReturn(PrivacySandboxUxCollection.UNSUPPORTED_UX).when(mAdServicesStorageManager).getUx();
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForConsentPerApiTesting(
+ isGiven, consentSourceOfTruth, AdServicesApiType.TOPICS.toConsentApiType());
+
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.TOPICS);
+
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven()).isTrue();
+ verify(mAdServicesStorageManager).setConsent(eq(AdServicesApiType.TOPICS), eq(isGiven));
+ verify(mMockIAdServicesManager, times(2)).getConsent(ConsentParcel.TOPICS);
+ verify(spyConsentManager).resetTopicsAndBlockedTopics();
+ }
+
+ @Test
+ public void testConsentPerApiIsGivenAfterEnabling_PpApiAndSystemServer()
+ throws RemoteException, IOException {
+ doNothing().when(() -> ErrorLogUtil.e(any(), anyInt(), anyInt()));
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ doReturn(PrivacySandboxUxCollection.UNSUPPORTED_UX).when(mAdServicesStorageManager).getUx();
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForConsentPerApiTesting(
+ isGiven, consentSourceOfTruth, AdServicesApiType.TOPICS.toConsentApiType());
+ doThrow(RuntimeException.class)
+ .when(mAdServicesStorageManager)
+ .getConsent(eq(AdServicesApiType.TOPICS));
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.TOPICS);
+ doReturn(AdServicesApiConsent.GIVEN)
+ .when(mAdServicesStorageManager)
+ .getConsent(eq(AdServicesApiType.TOPICS));
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven()).isTrue();
+ verify(mAdServicesStorageManager).setConsent(eq(AdServicesApiType.TOPICS), eq(isGiven));
+
+ verify(mAdServicesStorageManager, times(2)).getConsent(eq(AdServicesApiType.TOPICS));
+
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(
+ eq(/* isGiven */ true), eq(AdServicesApiType.TOPICS));
+ verify(spyConsentManager).resetTopicsAndBlockedTopics();
+ verify(
+ () ->
+ ErrorLogUtil.e(
+ any(Throwable.class),
+ eq(AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ERROR_WHILE_GET_CONSENT),
+ eq(AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX)));
+ }
+
+ @Test
+ public void testConsentPerApiIsGivenAfterEnabling_AppSearchOnly() throws RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ when(mAppSearchConsentManagerMock.getConsent(any()))
+ .thenReturn(AdServicesApiConsent.REVOKED);
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ AdServicesApiType apiType = AdServicesApiType.TOPICS;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.TOPICS);
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(eq(/* isGiven */ true), eq(apiType));
+ verify(mAppSearchConsentManagerMock).setConsent(eq(apiType), eq(isGiven));
+ when(mAppSearchConsentManagerMock.getConsent(AdServicesApiType.TOPICS))
+ .thenReturn(AdServicesApiConsent.GIVEN);
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven()).isTrue();
+ }
+
+ @Test
+ public void testMeasurementConsentIsGivenAfterEnabling_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ AdServicesApiType apiType = AdServicesApiType.MEASUREMENTS;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.MEASUREMENTS);
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(eq(/* isGiven */ true), eq(apiType));
+ verify(mAdServicesExtDataManager).setMsmtConsent(eq(true));
+ when(mAdServicesExtDataManager.getMsmtConsent()).thenReturn(true);
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven()).isTrue();
+ }
+
+ @Test
+ public void testMeasurementConsentIsRevokedAfterDisabling_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ boolean isGiven = false;
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ AdServicesApiType apiType = AdServicesApiType.MEASUREMENTS;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+ when(mAppConsentForRStorageManager.getConsent(any()))
+ .thenReturn(AdServicesApiConsent.REVOKED);
+ spyConsentManager.disable(mContextSpy, AdServicesApiType.MEASUREMENTS);
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(eq(/* isGiven */ false), eq(apiType));
+ verify(mAppConsentForRStorageManager)
+ .setConsent(eq(AdServicesApiType.MEASUREMENTS), eq(false));
+ when(mAppConsentForRStorageManager.getConsent(eq(AdServicesApiType.MEASUREMENTS)))
+ .thenReturn(AdServicesApiConsent.REVOKED);
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven())
+ .isFalse();
+ }
+
+ @Test
+ public void testFledgeConsentIsEnabled_userProfileIdIsClearedThanRecreated()
+ throws RemoteException {
+ doNothing().when(() -> ErrorLogUtil.e(any(), anyInt(), anyInt()));
+ doReturn(PrivacySandboxUxCollection.UNSUPPORTED_UX).when(mAdServicesStorageManager).getUx();
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForConsentPerApiTesting(
+ isGiven, consentSourceOfTruth, AdServicesApiType.FLEDGE.toConsentApiType());
+
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.FLEDGE);
+
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven()).isTrue();
+ verify(mUserProfileIdManagerMock).deleteId();
+ verify(mUserProfileIdManagerMock).getOrCreateId();
+ }
+
+ @Test
+ public void testFledgeConsentIsDisabled_userProfileIdIsCleared() throws RemoteException {
+ doNothing().when(() -> ErrorLogUtil.e(any(), anyInt(), anyInt()));
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ doReturn(PrivacySandboxUxCollection.UNSUPPORTED_UX).when(mAdServicesStorageManager).getUx();
+ boolean isGiven = false;
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForConsentPerApiTesting(
+ isGiven, consentSourceOfTruth, AdServicesApiType.FLEDGE.toConsentApiType());
+
+ spyConsentManager.disable(mContextSpy, AdServicesApiType.FLEDGE);
+
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven()).isFalse();
+ verify(mUserProfileIdManagerMock).deleteId();
+ }
+
+ @Test
+ public void testGetDefaultConsent_AppSearchOnly() throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ when(mAppSearchConsentManagerMock.getDefaultConsent(eq(AdServicesApiType.ALL_API)))
+ .thenReturn(AdServicesApiConsent.REVOKED);
+ assertThat(spyConsentManager.getDefaultConsent()).isFalse();
+
+ verify(mAppSearchConsentManagerMock).getDefaultConsent(eq(AdServicesApiType.ALL_API));
+ }
+
+ @Test
+ public void testGetDefaultConsent_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+ assertThat(spyConsentManager.getDefaultConsent()).isFalse();
+ }
+
+ @Test
+ public void testGetTopicsDefaultConsent_AppSearchOnly() throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ when(mAppSearchConsentManagerMock.getDefaultConsent(eq(AdServicesApiType.TOPICS)))
+ .thenReturn(AdServicesApiConsent.REVOKED);
+ assertThat(spyConsentManager.getTopicsDefaultConsent()).isFalse();
+ verify(mAppSearchConsentManagerMock).getDefaultConsent(eq(AdServicesApiType.TOPICS));
+ }
+
+ @Test
+ public void testGetTopicsDefaultConsent_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.getTopicsDefaultConsent()).isFalse();
+ }
+
+ @Test
+ public void testGetFledgeDefaultConsent_AppSearchOnly() throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ when(mAppSearchConsentManagerMock.getDefaultConsent(eq(AdServicesApiType.FLEDGE)))
+ .thenReturn(AdServicesApiConsent.REVOKED);
+ assertThat(spyConsentManager.getFledgeDefaultConsent()).isFalse();
+ verify(mAppSearchConsentManagerMock).getDefaultConsent(eq(AdServicesApiType.FLEDGE));
+ }
+
+ @Test
+ public void testGetFledgeDefaultConsent_ppapiAndAdExtDataServiceOnly() throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.getFledgeDefaultConsent()).isFalse();
+ }
+
+ @Test
+ public void testGetMeasurementDefaultConsent_AppSearchOnly() throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ when(mAppSearchConsentManagerMock.getDefaultConsent(eq(AdServicesApiType.MEASUREMENTS)))
+ .thenReturn(AdServicesApiConsent.REVOKED);
+ assertThat(spyConsentManager.getMeasurementDefaultConsent()).isFalse();
+ verify(mAppSearchConsentManagerMock).getDefaultConsent(eq(AdServicesApiType.MEASUREMENTS));
+ }
+
+ @Test
+ public void testGetMeasurementDefaultConsent_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+ spyConsentManager.recordMeasurementDefaultConsent(true);
+ // assertThat(spyConsentManager.getMeasurementDefaultConsent()).isTrue();
+ // spyConsentManager.recordMeasurementDefaultConsent(false);
+ // assertThat(spyConsentManager.getMeasurementDefaultConsent()).isFalse();
+ }
+
+ @Test
+ public void testGetDefaultAdIdState_AppSearchOnly() throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ when(mAppSearchConsentManagerMock.getDefaultAdIdState()).thenReturn(false);
+ assertThat(spyConsentManager.getDefaultAdIdState()).isFalse();
+ verify(mAppSearchConsentManagerMock).getDefaultAdIdState();
+ }
+
+ @Test
+ public void testGetDefaultAdIdState_ppapiAndAdExtDataServiceOnly() throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ spyConsentManager.recordDefaultAdIdState(true);
+ assertThat(spyConsentManager.getDefaultAdIdState()).isTrue();
+ spyConsentManager.recordDefaultAdIdState(false);
+ assertThat(spyConsentManager.getDefaultAdIdState()).isFalse();
+ }
+
+ @Test
+ public void testRecordDefaultConsent_AppSearchOnly() throws RemoteException, IOException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ spyConsentManager.recordDefaultConsent(true);
+ verify(mAppSearchConsentManagerMock)
+ .recordDefaultConsent(eq(AdServicesApiType.ALL_API), eq(true));
+ }
+
+ @Test
+ public void testRecordDefaultConsent_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+ assertThrows(RuntimeException.class, () -> spyConsentManager.recordDefaultConsent(false));
+ }
+
+ @Test
+ public void testRecordTopicsDefaultConsent_AppSearchOnly() throws RemoteException, IOException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ spyConsentManager.recordTopicsDefaultConsent(true);
+ verify(mAppSearchConsentManagerMock)
+ .recordDefaultConsent(eq(AdServicesApiType.TOPICS), eq(true));
+ }
+
+ @Test
+ public void testRecordTopicsDefaultConsent_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+ assertThrows(
+ IllegalStateException.class,
+ () -> spyConsentManager.recordTopicsDefaultConsent(true));
+ }
+
+ @Test
+ public void testRecordFledgeDefaultConsent_AppSearchOnly() throws RemoteException, IOException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ spyConsentManager.recordFledgeDefaultConsent(true);
+ verify(mAppSearchConsentManagerMock)
+ .recordDefaultConsent(eq(AdServicesApiType.FLEDGE), eq(true));
+ }
+
+ @Test
+ public void testRecordFledgeDefaultConsent_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ doReturn(true).when(mMockFlags).getEnableAdExtServiceConsentData();
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+ assertThrows(
+ IllegalStateException.class,
+ () -> spyConsentManager.recordFledgeDefaultConsent(true));
+ }
+
+ @Test
+ public void testRecordMeasurementDefaultConsent_AppSearchOnly() throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ spyConsentManager.recordMeasurementDefaultConsent(true);
+ verify(mAppSearchConsentManagerMock)
+ .recordDefaultConsent(eq(AdServicesApiType.MEASUREMENTS), eq(true));
+ }
+
+ @Test
+ public void testRecordDefaultAdIdState_AppSearchOnly() throws RemoteException {
+ doReturn(true).when(mMockFlags).getEnableAppsearchConsentData();
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(false, consentSourceOfTruth);
+
+ spyConsentManager.recordDefaultAdIdState(true);
+ verify(mAppSearchConsentManagerMock).recordDefaultAdIdState(eq(true));
+ }
+
+ @Test
+ public void testAllThreeConsentsPerApiAreGivenAggregatedConsentIsSet_PpApiOnly()
+ throws RemoteException, IOException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.TOPICS);
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.FLEDGE);
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.MEASUREMENTS);
+
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven()).isTrue();
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven()).isTrue();
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven()).isTrue();
+ assertThat(spyConsentManager.getConsent().isGiven()).isTrue();
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(
+ eq(/* isGiven */ true), eq(AdServicesApiType.TOPICS));
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(
+ eq(/* isGiven */ true), eq(AdServicesApiType.FLEDGE));
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(
+ eq(/* isGiven */ true), eq(AdServicesApiType.MEASUREMENTS));
+ verify(mConsentDatastore, times(1))
+ .put(eq(AdServicesApiType.ALL_API.toPpApiDatastoreKey()), eq(true));
+
+ verifyDataCleanup(spyConsentManager);
+ }
+
+ @Test
+ public void testAllConsentAreRevokedClenaupIsExecuted() throws IOException, RemoteException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ boolean isGiven = true;
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(isGiven, consentSourceOfTruth);
+
+ // set up the initial state
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.TOPICS);
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.FLEDGE);
+ spyConsentManager.enable(mContextSpy, AdServicesApiType.MEASUREMENTS);
+
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven()).isTrue();
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven()).isTrue();
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven()).isTrue();
+ assertThat(spyConsentManager.getConsent().isGiven()).isTrue();
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(
+ eq(/* isGiven */ true), eq(AdServicesApiType.TOPICS));
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(
+ eq(/* isGiven */ true), eq(AdServicesApiType.FLEDGE));
+ verify(spyConsentManager)
+ .setPerApiConsentToSourceOfTruth(
+ eq(/* isGiven */ true), eq(AdServicesApiType.MEASUREMENTS));
+
+ // disable all the consent one by one
+ spyConsentManager.disable(mContextSpy, AdServicesApiType.TOPICS);
+ spyConsentManager.disable(mContextSpy, AdServicesApiType.FLEDGE);
+ spyConsentManager.disable(mContextSpy, AdServicesApiType.MEASUREMENTS);
+
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven()).isFalse();
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven()).isFalse();
+ assertThat(spyConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven())
+ .isFalse();
+ assertThat(spyConsentManager.getConsent().isGiven()).isFalse();
+
+ verify(
+ () ->
+ BackgroundJobsManager.unscheduleJobsPerApi(
+ any(JobScheduler.class), eq(AdServicesApiType.TOPICS)));
+ verify(
+ () ->
+ BackgroundJobsManager.unscheduleJobsPerApi(
+ any(JobScheduler.class), eq(AdServicesApiType.FLEDGE)));
+ verify(
+ () ->
+ BackgroundJobsManager.unscheduleJobsPerApi(
+ any(JobScheduler.class), eq(AdServicesApiType.MEASUREMENTS)));
+ verify(() -> BackgroundJobsManager.unscheduleAllBackgroundJobs(any(JobScheduler.class)));
+
+ verify(spyConsentManager, times(2)).resetTopicsAndBlockedTopics();
+ verify(spyConsentManager, times(2)).clearAllAppConsentData();
+ verify(spyConsentManager, times(2)).resetMeasurement();
+ }
+
+ @Test
+ public void testManualInteractionWithConsentRecorded_PpApiOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.getUserManualInteractionWithConsent()).isEqualTo(UNKNOWN);
+
+ verify(mMockIAdServicesManager, never()).getUserManualInteractionWithConsent();
+
+ spyConsentManager.recordUserManualInteractionWithConsent(MANUAL_INTERACTIONS_RECORDED);
+
+ assertThat(spyConsentManager.getUserManualInteractionWithConsent())
+ .isEqualTo(MANUAL_INTERACTIONS_RECORDED);
+
+ verify(mMockIAdServicesManager, never()).getUserManualInteractionWithConsent();
+ verify(mMockIAdServicesManager, never()).recordUserManualInteractionWithConsent(anyInt());
+ }
+
+ @Test
+ public void testManualInteractionWithConsentRecorded_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.getUserManualInteractionWithConsent()).isEqualTo(UNKNOWN);
+
+ verify(mMockIAdServicesManager).getUserManualInteractionWithConsent();
+
+ doReturn(MANUAL_INTERACTIONS_RECORDED)
+ .when(mMockIAdServicesManager)
+ .getUserManualInteractionWithConsent();
+ spyConsentManager.recordUserManualInteractionWithConsent(MANUAL_INTERACTIONS_RECORDED);
+
+ assertThat(spyConsentManager.getUserManualInteractionWithConsent())
+ .isEqualTo(MANUAL_INTERACTIONS_RECORDED);
+
+ verify(mMockIAdServicesManager, times(2)).getUserManualInteractionWithConsent();
+ verify(mMockIAdServicesManager).recordUserManualInteractionWithConsent(anyInt());
+
+ // Verify the bit is not set in PPAPI
+ assertThat(mConsentDatastore.get(MANUAL_INTERACTION_WITH_CONSENT_RECORDED)).isNull();
+ }
+
+ @Test
+ public void testManualInteractionWithConsentRecorded_PpApiAndSystemServer()
+ throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ @ConsentManagerV2.UserManualInteraction
+ int userManualInteractionWithConsent =
+ spyConsentManager.getUserManualInteractionWithConsent();
+
+ assertThat(userManualInteractionWithConsent).isEqualTo(UNKNOWN);
+
+ verify(mMockIAdServicesManager).getUserManualInteractionWithConsent();
+
+ doReturn(MANUAL_INTERACTIONS_RECORDED)
+ .when(mMockIAdServicesManager)
+ .getUserManualInteractionWithConsent();
+ spyConsentManager.recordUserManualInteractionWithConsent(MANUAL_INTERACTIONS_RECORDED);
+
+ assertThat(spyConsentManager.getUserManualInteractionWithConsent())
+ .isEqualTo(MANUAL_INTERACTIONS_RECORDED);
+
+ verify(mMockIAdServicesManager, times(2)).getUserManualInteractionWithConsent();
+ verify(mMockIAdServicesManager).recordUserManualInteractionWithConsent(anyInt());
+
+ // Verify the bit is also set in PPAPI
+ assertThat(mConsentDatastore.get(MANUAL_INTERACTION_WITH_CONSENT_RECORDED)).isTrue();
+ }
+
+ @Test
+ public void testManualInteractionWithConsentRecorded_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ when(mAppSearchConsentManagerMock.getUserManualInteractionWithConsent())
+ .thenReturn(UNKNOWN);
+ assertThat(spyConsentManager.getUserManualInteractionWithConsent()).isEqualTo(UNKNOWN);
+ verify(mAppSearchConsentManagerMock).getUserManualInteractionWithConsent();
+ verify(mMockIAdServicesManager, never()).getUserManualInteractionWithConsent();
+
+ spyConsentManager.recordUserManualInteractionWithConsent(MANUAL_INTERACTIONS_RECORDED);
+ verify(mAppSearchConsentManagerMock)
+ .recordUserManualInteractionWithConsent(MANUAL_INTERACTIONS_RECORDED);
+ when(mAppSearchConsentManagerMock.getUserManualInteractionWithConsent())
+ .thenReturn(MANUAL_INTERACTIONS_RECORDED);
+ assertThat(spyConsentManager.getUserManualInteractionWithConsent())
+ .isEqualTo(MANUAL_INTERACTIONS_RECORDED);
+
+ verify(mMockIAdServicesManager, never()).getUserManualInteractionWithConsent();
+ verify(mMockIAdServicesManager, never()).recordUserManualInteractionWithConsent(anyInt());
+ }
+
+ @Test
+ public void testManualInteractionWithConsentRecorded_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ when(mAdServicesExtDataManager.getManualInteractionWithConsentStatus()).thenReturn(UNKNOWN);
+ assertThat(spyConsentManager.getUserManualInteractionWithConsent()).isEqualTo(UNKNOWN);
+ verify(mAdServicesExtDataManager).getManualInteractionWithConsentStatus();
+
+ spyConsentManager.recordUserManualInteractionWithConsent(MANUAL_INTERACTIONS_RECORDED);
+ verify(mAppConsentForRStorageManager)
+ .recordUserManualInteractionWithConsent(MANUAL_INTERACTIONS_RECORDED);
+ when(mAdServicesExtDataManager.getManualInteractionWithConsentStatus())
+ .thenReturn(MANUAL_INTERACTIONS_RECORDED);
+ assertThat(spyConsentManager.getUserManualInteractionWithConsent())
+ .isEqualTo(MANUAL_INTERACTIONS_RECORDED);
+ }
+
+ // Note this method needs to be invoked after other private variables are initialized.
+ private ConsentManagerV2 getConsentManagerByConsentSourceOfTruth(int consentSourceOfTruth) {
+ return new ConsentManagerV2(
+ mTopicsWorkerMock,
+ mAppConsentDaoSpy,
+ mEnrollmentDaoSpy,
+ mMeasurementImplMock,
+ mCustomAudienceDaoMock,
+ mAppConsentStorageManager,
+ mAppInstallDaoMock,
+ mFrequencyCapDaoMock,
+ mAdServicesStorageManager,
+ mConsentDatastore,
+ mAppSearchConsentManagerMock,
+ mUserProfileIdManagerMock,
+ mAppConsentForRStorageManager,
+ mMockFlags,
+ consentSourceOfTruth,
+ true,
+ true);
+ }
+
+ private ConsentManagerV2 getSpiedConsentManagerForMigrationTesting(
+ boolean isGiven, int consentSourceOfTruth) throws RemoteException {
+ ConsentManagerV2 consentManager =
+ spy(getConsentManagerByConsentSourceOfTruth(consentSourceOfTruth));
+
+ // Disable IPC calls
+ ConsentParcel consentParcel =
+ isGiven
+ ? ConsentParcel.createGivenConsent(ConsentParcel.ALL_API)
+ : ConsentParcel.createRevokedConsent(ConsentParcel.ALL_API);
+ doReturn(consentParcel).when(mMockIAdServicesManager).getConsent(ConsentParcel.ALL_API);
+ doReturn(isGiven).when(mMockIAdServicesManager).wasNotificationDisplayed();
+ doNothing().when(mMockIAdServicesManager).recordNotificationDisplayed(true);
+ doReturn(isGiven).when(mMockIAdServicesManager).wasGaUxNotificationDisplayed();
+ doNothing().when(mMockIAdServicesManager).recordGaUxNotificationDisplayed(true);
+ doReturn(UNKNOWN).when(mMockIAdServicesManager).getUserManualInteractionWithConsent();
+ doNothing().when(mMockIAdServicesManager).recordUserManualInteractionWithConsent(anyInt());
+ doReturn(AdServicesApiConsent.getConsent(isGiven))
+ .when(mAppSearchConsentManagerMock)
+ .getConsent(AdServicesApiType.ALL_API);
+ return consentManager;
+ }
+
+ private ConsentManagerV2 getSpiedConsentManagerForConsentPerApiTesting(
+ boolean isGiven,
+ int consentSourceOfTruth,
+ @ConsentParcel.ConsentApiType int consentApiType)
+ throws RemoteException {
+ ConsentManagerV2 consentManager =
+ spy(getConsentManagerByConsentSourceOfTruth(consentSourceOfTruth));
+
+ // Disable IPC calls
+ doNothing().when(mAdServicesStorageManager).setConsent(any(), anyBoolean());
+ ConsentParcel consentParcel =
+ isGiven
+ ? ConsentParcel.createGivenConsent(consentApiType)
+ : ConsentParcel.createRevokedConsent(consentApiType);
+ doReturn(consentParcel).when(mMockIAdServicesManager).getConsent(consentApiType);
+ doReturn(isGiven).when(mMockIAdServicesManager).wasNotificationDisplayed();
+ doNothing().when(mMockIAdServicesManager).recordNotificationDisplayed(true);
+ doReturn(isGiven).when(mMockIAdServicesManager).wasGaUxNotificationDisplayed();
+ doNothing().when(mMockIAdServicesManager).recordGaUxNotificationDisplayed(true);
+ doReturn(UNKNOWN).when(mMockIAdServicesManager).getUserManualInteractionWithConsent();
+ doNothing().when(mMockIAdServicesManager).recordUserManualInteractionWithConsent(anyInt());
+ doReturn(AdServicesApiConsent.getConsent(isGiven))
+ .when(mAppSearchConsentManagerMock)
+ .getConsent(any());
+ return consentManager;
+ }
+
+ private void verifyConsentMigration(
+ boolean isGiven,
+ boolean hasWrittenToPpApi,
+ boolean hasWrittenToSystemServer,
+ boolean hasReadFromSystemServer)
+ throws RemoteException, IOException {
+ verify(mAppConsentStorageManager, verificationMode(hasWrittenToPpApi))
+ .setConsent(any(), eq(isGiven));
+ verify(mAdServicesStorageManager, verificationMode(hasWrittenToSystemServer))
+ .setConsent(any(), eq(isGiven));
+
+ verify(mMockIAdServicesManager, verificationMode(hasReadFromSystemServer))
+ .getConsent(ConsentParcel.ALL_API);
+ }
+
+ private void verifyDataCleanup(ConsentManagerV2 consentManager) throws IOException {
+ verify(consentManager).resetTopicsAndBlockedTopics();
+ verify(consentManager).clearAllAppConsentData();
+ verify(consentManager).resetMeasurement();
+ }
+
+ private VerificationMode verificationMode(boolean hasHappened) {
+ return hasHappened ? atLeastOnce() : never();
+ }
+
+ private void mockGetPackageUid(@NonNull String packageName, int uid)
+ throws PackageManager.NameNotFoundException {
+ doReturn(uid)
+ .when(
+ () ->
+ PackageManagerCompatUtils.getPackageUid(
+ any(), eq(packageName), anyInt()));
+ }
+
+ private void mockInstalledApplications(List<ApplicationInfo> applicationsInstalled) {
+ doReturn(applicationsInstalled)
+ .when(() -> PackageManagerCompatUtils.getInstalledApplications(any(), anyInt()));
+ }
+
+ private void mockThrowExceptionOnGetPackageUid(@NonNull String packageName) {
+ doThrow(PackageManager.NameNotFoundException.class)
+ .when(
+ () ->
+ PackageManagerCompatUtils.getPackageUid(
+ any(), eq(packageName), anyInt()));
+ }
+
+ private List<ApplicationInfo> createApplicationInfos(String... packageNames) {
+ return Arrays.stream(packageNames)
+ .map(s -> ApplicationInfoBuilder.newBuilder().setPackageName(s).build())
+ .collect(Collectors.toList());
+ }
+
+ private class ListMatcherIgnoreOrder implements ArgumentMatcher<List<String>> {
+ @NonNull private final List<String> mStrings;
+
+ private ListMatcherIgnoreOrder(@NonNull List<String> strings) {
+ Objects.requireNonNull(strings);
+ mStrings = strings;
+ }
+
+ @Override
+ public boolean matches(@Nullable List<String> argument) {
+ if (argument == null) {
+ return false;
+ }
+ if (argument.size() != mStrings.size()) {
+ return false;
+ }
+ if (!argument.containsAll(mStrings)) {
+ return false;
+ }
+ if (!mStrings.containsAll(argument)) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ @Test
+ public void testCurrentPrivacySandboxFeature_ppapiOnly() throws RemoteException {
+ getCurrentPrivacySandboxFeatureWithPpApiOnly(Flags.PPAPI_ONLY);
+ }
+
+ @Test
+ public void testCurrentPrivacySandboxFeature_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException {
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ getCurrentPrivacySandboxFeatureWithPpApiOnly(Flags.PPAPI_AND_ADEXT_SERVICE);
+ }
+
+ private void getCurrentPrivacySandboxFeatureWithPpApiOnly(int consentSourceOfTruth)
+ throws RemoteException {
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED);
+ verify(mMockIAdServicesManager, never()).getCurrentPrivacySandboxFeature();
+
+ spyConsentManager.setCurrentPrivacySandboxFeature(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT);
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT);
+
+ verify(mMockIAdServicesManager, never()).getCurrentPrivacySandboxFeature();
+ verify(mMockIAdServicesManager, never()).setCurrentPrivacySandboxFeature(anyString());
+ }
+
+ @Test
+ public void testCurrentPrivacySandboxFeature_SystemServerOnly()
+ throws RemoteException, IOException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ doThrow(RuntimeException.class)
+ .when(mAdServicesStorageManager)
+ .getCurrentPrivacySandboxFeature();
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+ doNothing().when(() -> ErrorLogUtil.e(any(), anyInt(), anyInt()));
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED);
+ verify(mAdServicesStorageManager).getCurrentPrivacySandboxFeature();
+
+ int errorCode = AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PRIVACY_SANDBOX_SAVE_FAILURE;
+ MockedVoidMethod mockedVoidMethod =
+ () ->
+ ErrorLogUtil.e(
+ any(),
+ eq(errorCode),
+ eq(AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX));
+ verify(mockedVoidMethod);
+ doReturn(PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT)
+ .when(mAdServicesStorageManager)
+ .getCurrentPrivacySandboxFeature();
+ spyConsentManager.setCurrentPrivacySandboxFeature(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT);
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT);
+
+ doReturn(PrivacySandboxFeatureType.PRIVACY_SANDBOX_RECONSENT)
+ .when(mAdServicesStorageManager)
+ .getCurrentPrivacySandboxFeature();
+ spyConsentManager.setCurrentPrivacySandboxFeature(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_RECONSENT);
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_RECONSENT);
+
+ doReturn(PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED)
+ .when(mAdServicesStorageManager)
+ .getCurrentPrivacySandboxFeature();
+ spyConsentManager.setCurrentPrivacySandboxFeature(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED);
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED);
+
+ assertThat(
+ mConsentDatastore.get(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED.name()))
+ .isNull();
+ assertThat(
+ mConsentDatastore.get(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT.name()))
+ .isNull();
+ assertThat(
+ mConsentDatastore.get(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_RECONSENT.name()))
+ .isNull();
+ }
+
+ @Test
+ public void testCurrentPrivacySandboxFeature_PpApiAndSystemServer()
+ throws RemoteException, IOException {
+ doNothing().when(() -> ErrorLogUtil.e(any(), anyInt(), anyInt()));
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+ doThrow(RuntimeException.class)
+ .when(mAdServicesStorageManager)
+ .getCurrentPrivacySandboxFeature();
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED);
+ verify(mAdServicesStorageManager).getCurrentPrivacySandboxFeature();
+ doThrow(RuntimeException.class)
+ .when(mAdServicesStorageManager)
+ .getCurrentPrivacySandboxFeature();
+ int saveErrorCode = AD_SERVICES_ERROR_REPORTED__ERROR_CODE__PRIVACY_SANDBOX_SAVE_FAILURE;
+ MockedVoidMethod mockedVoidMethod =
+ () ->
+ ErrorLogUtil.e(
+ any(),
+ eq(saveErrorCode),
+ eq(AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__UX));
+ verify(mockedVoidMethod);
+ doReturn(PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT)
+ .when(mAdServicesStorageManager)
+ .getCurrentPrivacySandboxFeature();
+ spyConsentManager.setCurrentPrivacySandboxFeature(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT);
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT);
+
+ doReturn(PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED)
+ .when(mAdServicesStorageManager)
+ .getCurrentPrivacySandboxFeature();
+ spyConsentManager.setCurrentPrivacySandboxFeature(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED);
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED);
+
+ doReturn(PrivacySandboxFeatureType.PRIVACY_SANDBOX_RECONSENT)
+ .when(mAdServicesStorageManager)
+ .getCurrentPrivacySandboxFeature();
+ spyConsentManager.setCurrentPrivacySandboxFeature(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_RECONSENT);
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_RECONSENT);
+
+ // Only the last set bit is true.
+ assertThat(
+ mConsentDatastore.get(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED.name()))
+ .isFalse();
+ assertThat(
+ mConsentDatastore.get(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT.name()))
+ .isFalse();
+ assertThat(
+ mConsentDatastore.get(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_RECONSENT.name()))
+ .isTrue();
+ }
+
+ @Test
+ public void testCurrentPrivacySandboxFeature_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ when(mAppSearchConsentManagerMock.getCurrentPrivacySandboxFeature())
+ .thenReturn(PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED);
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_UNSUPPORTED);
+
+ spyConsentManager.setCurrentPrivacySandboxFeature(
+ PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT);
+ verify(mAppSearchConsentManagerMock)
+ .setCurrentPrivacySandboxFeature(
+ eq(PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT));
+ when(mAppSearchConsentManagerMock.getCurrentPrivacySandboxFeature())
+ .thenReturn(PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT);
+ assertThat(spyConsentManager.getCurrentPrivacySandboxFeature())
+ .isEqualTo(PrivacySandboxFeatureType.PRIVACY_SANDBOX_FIRST_CONSENT);
+
+ verify(mMockIAdServicesManager, never()).getCurrentPrivacySandboxFeature();
+ verify(mMockIAdServicesManager, never()).setCurrentPrivacySandboxFeature(anyString());
+ }
+
+ @Test
+ public void isAdIdEnabledTest_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.isAdIdEnabled()).isFalse();
+
+ verify(mMockIAdServicesManager).isAdIdEnabled();
+
+ doReturn(true).when(mMockIAdServicesManager).isAdIdEnabled();
+ spyConsentManager.setAdIdEnabled(true);
+
+ assertThat(spyConsentManager.isAdIdEnabled()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).isAdIdEnabled();
+ verify(mMockIAdServicesManager).setAdIdEnabled(anyBoolean());
+ }
+
+ @Test
+ public void isAdIdEnabledTest_PpApiAndSystemServer() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ Boolean isAdIdEnabled = spyConsentManager.isAdIdEnabled();
+
+ assertThat(isAdIdEnabled).isFalse();
+
+ verify(mMockIAdServicesManager).isAdIdEnabled();
+
+ doReturn(true).when(mMockIAdServicesManager).isAdIdEnabled();
+ spyConsentManager.setAdIdEnabled(true);
+
+ assertThat(spyConsentManager.isAdIdEnabled()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).isAdIdEnabled();
+ verify(mMockIAdServicesManager).setAdIdEnabled(anyBoolean());
+ }
+
+ @Test
+ public void isAdIdEnabledTest_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(false).when(mAppSearchConsentManagerMock).isAdIdEnabled();
+ assertThat(spyConsentManager.isAdIdEnabled()).isFalse();
+ verify(mAppSearchConsentManagerMock).isAdIdEnabled();
+
+ doReturn(true).when(mAppSearchConsentManagerMock).isAdIdEnabled();
+ spyConsentManager.setAdIdEnabled(true);
+
+ assertThat(spyConsentManager.isAdIdEnabled()).isTrue();
+
+ verify(mAppSearchConsentManagerMock, times(2)).isAdIdEnabled();
+ verify(mAppSearchConsentManagerMock).setAdIdEnabled(anyBoolean());
+ }
+
+ @Test
+ public void isU18AccountTest_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.isU18Account()).isFalse();
+
+ verify(mMockIAdServicesManager).isU18Account();
+
+ doReturn(true).when(mMockIAdServicesManager).isU18Account();
+ spyConsentManager.setU18Account(true);
+
+ assertThat(spyConsentManager.isU18Account()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).isU18Account();
+ verify(mMockIAdServicesManager).setU18Account(anyBoolean());
+ }
+
+ @Test
+ public void isU18AccountTest_PpApiAndSystemServer() throws RemoteException, IOException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ Boolean isU18Account = spyConsentManager.isU18Account();
+
+ assertThat(isU18Account).isFalse();
+
+ verify(mMockIAdServicesManager).isU18Account();
+
+ doReturn(true).when(mMockIAdServicesManager).isU18Account();
+ spyConsentManager.setU18Account(true);
+
+ assertThat(spyConsentManager.isU18Account()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).isU18Account();
+ verify(mMockIAdServicesManager).setU18Account(anyBoolean());
+ }
+
+ @Test
+ public void isU18AccountTest_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(false).when(mAppSearchConsentManagerMock).isU18Account();
+ assertThat(spyConsentManager.isU18Account()).isFalse();
+ verify(mAppSearchConsentManagerMock).isU18Account();
+
+ doReturn(true).when(mAppSearchConsentManagerMock).isU18Account();
+ spyConsentManager.setU18Account(true);
+
+ assertThat(spyConsentManager.isU18Account()).isTrue();
+
+ verify(mAppSearchConsentManagerMock, times(2)).isU18Account();
+ verify(mAppSearchConsentManagerMock).setU18Account(anyBoolean());
+ }
+
+ @Test
+ public void isU18AccountTest_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(false).when(mAppConsentForRStorageManager).isU18Account();
+ assertThat(spyConsentManager.isU18Account()).isFalse();
+ verify(mAppConsentForRStorageManager).isU18Account();
+
+ doReturn(true).when(mAppConsentForRStorageManager).isU18Account();
+ spyConsentManager.setU18Account(true);
+
+ assertThat(spyConsentManager.isU18Account()).isTrue();
+
+ verify(mAppConsentForRStorageManager, times(2)).isU18Account();
+ verify(mAppConsentForRStorageManager).setU18Account(anyBoolean());
+ }
+
+ @Test
+ public void isEntryPointEnabledTest_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ spyConsentManager.setEntryPointEnabled(true);
+ assertThat(spyConsentManager.isEntryPointEnabled()).isTrue();
+ spyConsentManager.setEntryPointEnabled(false);
+ assertThat(spyConsentManager.isEntryPointEnabled()).isFalse();
+ }
+
+ @Test
+ public void isEntryPointEnabledTest_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.isEntryPointEnabled()).isFalse();
+
+ verify(mMockIAdServicesManager).isEntryPointEnabled();
+
+ doReturn(true).when(mMockIAdServicesManager).isEntryPointEnabled();
+ spyConsentManager.setEntryPointEnabled(true);
+
+ assertThat(spyConsentManager.isEntryPointEnabled()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).isEntryPointEnabled();
+ verify(mMockIAdServicesManager).setEntryPointEnabled(anyBoolean());
+ }
+
+ @Test
+ public void isEntryPointEnabledTest_PpApiAndSystemServer() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ Boolean isEntryPointEnabled = spyConsentManager.isEntryPointEnabled();
+
+ assertThat(isEntryPointEnabled).isFalse();
+
+ verify(mMockIAdServicesManager).isEntryPointEnabled();
+
+ doReturn(true).when(mMockIAdServicesManager).isEntryPointEnabled();
+ spyConsentManager.setEntryPointEnabled(true);
+
+ assertThat(spyConsentManager.isEntryPointEnabled()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).isEntryPointEnabled();
+ verify(mMockIAdServicesManager).setEntryPointEnabled(anyBoolean());
+ }
+
+ @Test
+ public void isEntryPointEnabledTest_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(false).when(mAppSearchConsentManagerMock).isEntryPointEnabled();
+ assertThat(spyConsentManager.isEntryPointEnabled()).isFalse();
+ verify(mAppSearchConsentManagerMock).isEntryPointEnabled();
+
+ doReturn(true).when(mAppSearchConsentManagerMock).isEntryPointEnabled();
+ spyConsentManager.setEntryPointEnabled(true);
+
+ assertThat(spyConsentManager.isEntryPointEnabled()).isTrue();
+
+ verify(mAppSearchConsentManagerMock, times(2)).isEntryPointEnabled();
+ verify(mAppSearchConsentManagerMock).setEntryPointEnabled(anyBoolean());
+ }
+
+ @Test
+ public void isAdultAccountTest_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.isAdultAccount()).isFalse();
+
+ verify(mMockIAdServicesManager).isAdultAccount();
+
+ doReturn(true).when(mMockIAdServicesManager).isAdultAccount();
+ spyConsentManager.setAdultAccount(true);
+
+ assertThat(spyConsentManager.isAdultAccount()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).isAdultAccount();
+ verify(mMockIAdServicesManager).setAdultAccount(anyBoolean());
+ }
+
+ @Test
+ public void isAdultAccountTest_PpApiAndSystemServer() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ Boolean isAdultAccount = spyConsentManager.isAdultAccount();
+
+ assertThat(isAdultAccount).isFalse();
+
+ verify(mMockIAdServicesManager).isAdultAccount();
+
+ doReturn(true).when(mMockIAdServicesManager).isAdultAccount();
+ spyConsentManager.setAdultAccount(true);
+
+ assertThat(spyConsentManager.isAdultAccount()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).isAdultAccount();
+ verify(mMockIAdServicesManager).setAdultAccount(anyBoolean());
+ }
+
+ @Test
+ public void isAdultAccountTest_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(false).when(mAppConsentForRStorageManager).isAdultAccount();
+ assertThat(spyConsentManager.isAdultAccount()).isFalse();
+ verify(mAppConsentForRStorageManager).isAdultAccount();
+
+ doReturn(true).when(mAppConsentForRStorageManager).isAdultAccount();
+ spyConsentManager.setAdultAccount(true);
+
+ assertThat(spyConsentManager.isAdultAccount()).isTrue();
+
+ verify(mAppConsentForRStorageManager, times(2)).isAdultAccount();
+ verify(mAppConsentForRStorageManager).setAdultAccount(anyBoolean());
+ }
+
+ @Test
+ public void isAdultAccountTest_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(false).when(mAppSearchConsentManagerMock).isAdultAccount();
+ assertThat(spyConsentManager.isAdultAccount()).isFalse();
+ verify(mAppSearchConsentManagerMock).isAdultAccount();
+
+ doReturn(true).when(mAppSearchConsentManagerMock).isAdultAccount();
+ spyConsentManager.setAdultAccount(true);
+
+ assertThat(spyConsentManager.isAdultAccount()).isTrue();
+
+ verify(mAppSearchConsentManagerMock, times(2)).isAdultAccount();
+ verify(mAppSearchConsentManagerMock).setAdultAccount(anyBoolean());
+ }
+
+ @Test
+ public void testDefaultConsentRecorded_PpApiOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.getDefaultConsent()).isFalse();
+
+ verify(mMockIAdServicesManager, never()).getDefaultConsent();
+
+ spyConsentManager.recordDefaultConsent(true);
+
+ assertThat(spyConsentManager.getDefaultConsent()).isTrue();
+
+ verify(mMockIAdServicesManager, never()).getDefaultConsent();
+ verify(mMockIAdServicesManager, never()).recordDefaultConsent(anyBoolean());
+ }
+
+ @Test
+ public void testDefaultConsentRecorded_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.getDefaultConsent()).isFalse();
+
+ verify(mMockIAdServicesManager).getDefaultConsent();
+
+ doReturn(true).when(mMockIAdServicesManager).getDefaultConsent();
+ spyConsentManager.recordDefaultConsent(true);
+
+ assertThat(spyConsentManager.getDefaultConsent()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).getDefaultConsent();
+ verify(mMockIAdServicesManager).recordDefaultConsent(eq(true));
+
+ // Verify default consent is not set in PPAPI
+ assertThat(mConsentDatastore.get(DEFAULT_CONSENT)).isNull();
+ }
+
+ @Test
+ public void testDefaultConsentRecorded_PpApiAndSystemServer() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ Boolean getDefaultConsent = spyConsentManager.getDefaultConsent();
+
+ assertThat(getDefaultConsent).isFalse();
+
+ verify(mMockIAdServicesManager).getDefaultConsent();
+
+ doReturn(true).when(mMockIAdServicesManager).getDefaultConsent();
+ spyConsentManager.recordDefaultConsent(true);
+
+ assertThat(spyConsentManager.getDefaultConsent()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).getDefaultConsent();
+ verify(mMockIAdServicesManager).recordDefaultConsent(eq(true));
+
+ // Verify default consent is also set in PPAPI
+ assertThat(mConsentDatastore.get(DEFAULT_CONSENT)).isTrue();
+ }
+
+ @Test
+ public void testDefaultConsentRecorded_ppapiAndAdExtDataServiceOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+ assertThat(spyConsentManager.getDefaultConsent()).isFalse();
+ }
+
+ @Test
+ public void wasU18NotificationDisplayedTest_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ assertThat(spyConsentManager.wasU18NotificationDisplayed()).isFalse();
+
+ verify(mMockIAdServicesManager).wasU18NotificationDisplayed();
+
+ doReturn(true).when(mMockIAdServicesManager).wasU18NotificationDisplayed();
+ spyConsentManager.setU18NotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasU18NotificationDisplayed()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).wasU18NotificationDisplayed();
+ verify(mMockIAdServicesManager).setU18NotificationDisplayed(anyBoolean());
+ }
+
+ @Test
+ public void wasU18NotificationDisplayedTest_PpApiAndSystemServer() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ Boolean wasU18NotificationDisplayed = spyConsentManager.wasU18NotificationDisplayed();
+
+ assertThat(wasU18NotificationDisplayed).isFalse();
+
+ verify(mMockIAdServicesManager).wasU18NotificationDisplayed();
+
+ doReturn(true).when(mMockIAdServicesManager).wasU18NotificationDisplayed();
+ spyConsentManager.setU18NotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasU18NotificationDisplayed()).isTrue();
+
+ verify(mMockIAdServicesManager, times(2)).wasU18NotificationDisplayed();
+ verify(mMockIAdServicesManager).setU18NotificationDisplayed(anyBoolean());
+ }
+
+ @Test
+ public void wasU18NotificationDisplayedTest_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(false).when(mAppSearchConsentManagerMock).wasU18NotificationDisplayed();
+ assertThat(spyConsentManager.wasU18NotificationDisplayed()).isFalse();
+ verify(mAppSearchConsentManagerMock).wasU18NotificationDisplayed();
+
+ doReturn(true).when(mAppSearchConsentManagerMock).wasU18NotificationDisplayed();
+ spyConsentManager.setU18NotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasU18NotificationDisplayed()).isTrue();
+
+ verify(mAppSearchConsentManagerMock, times(2)).wasU18NotificationDisplayed();
+ verify(mAppSearchConsentManagerMock).setU18NotificationDisplayed(anyBoolean());
+ }
+
+ @Test
+ public void testWasU18NotificationDisplayed_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_ADEXT_SERVICE;
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(false).when(mAppConsentForRStorageManager).wasU18NotificationDisplayed();
+ assertThat(spyConsentManager.wasU18NotificationDisplayed()).isFalse();
+ verify(mAppConsentForRStorageManager).wasU18NotificationDisplayed();
+
+ doReturn(true).when(mAppConsentForRStorageManager).wasU18NotificationDisplayed();
+ spyConsentManager.setU18NotificationDisplayed(true);
+
+ assertThat(spyConsentManager.wasU18NotificationDisplayed()).isTrue();
+
+ verify(mAppConsentForRStorageManager, times(2)).wasU18NotificationDisplayed();
+ verify(mAppConsentForRStorageManager).setU18NotificationDisplayed(anyBoolean());
+ }
+
+ @Test
+ public void testIsRvcAdultUser_ageCheckFlagOn() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ when(mMockFlags.getRvcPostOtaNotifAgeCheck()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(true).when(mAppConsentForRStorageManager).wasU18NotificationDisplayed();
+ doReturn(false).when(mAppConsentForRStorageManager).isU18Account();
+ doReturn(true).when(mAppConsentForRStorageManager).isAdultAccount();
+ assertThat(spyConsentManager.isOtaAdultUserFromRvc()).isTrue();
+ verify(mAppConsentForRStorageManager).wasU18NotificationDisplayed();
+ verify(mAppConsentForRStorageManager).isAdultAccount();
+ verify(mAppConsentForRStorageManager).isU18Account();
+ }
+
+ @Test
+ public void testIsRvcAdultUser_ageCheckFlagOff() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ doReturn(true).when(mAppConsentForRStorageManager).wasU18NotificationDisplayed();
+ assertThat(spyConsentManager.isOtaAdultUserFromRvc()).isTrue();
+ verify(mAppConsentForRStorageManager).wasU18NotificationDisplayed();
+ }
+
+ @Test
+ public void testGetUx_PpApiOnly() throws RemoteException {
+ getUxWithPpApiOnly(Flags.PPAPI_ONLY);
+ }
+
+ @Test
+ public void testGetUx_ppapiAndAdExtDataServiceOnly() throws RemoteException {
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ getUxWithPpApiOnly(Flags.PPAPI_AND_ADEXT_SERVICE);
+ }
+
+ private void getUxWithPpApiOnly(int consentSourceOfTruth) throws RemoteException {
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ doReturn(ux).when(mUxStatesDaoMock).getUx();
+ assertThat(spyConsentManager.getUx()).isEqualTo(ux);
+
+ spyConsentManager.setUx(ux);
+ }
+
+ verify(mUxStatesDaoMock, times(5)).getUx();
+ verify(mUxStatesDaoMock, times(5)).setUx(any());
+ }
+
+ @Test
+ public void getUxTest_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ doReturn(ux.toString()).when(mMockIAdServicesManager).getUx();
+ assertThat(spyConsentManager.getUx()).isEqualTo(ux);
+
+ spyConsentManager.setUx(ux);
+ }
+
+ verify(mMockIAdServicesManager, times(5)).getUx();
+ verify(mMockIAdServicesManager, times(5)).setUx(any());
+ }
+
+ @Test
+ public void getUxTest_PpApiAndSystemServer() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ doReturn(ux.toString()).when(mMockIAdServicesManager).getUx();
+ assertThat(spyConsentManager.getUx()).isEqualTo(ux);
+
+ spyConsentManager.setUx(ux);
+ }
+
+ verify(mMockIAdServicesManager, times(5)).getUx();
+ verify(mMockIAdServicesManager, times(5)).setUx(any());
+ }
+
+ @Test
+ public void getUxTest_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ doReturn(ux).when(mAppSearchConsentManagerMock).getUx();
+ assertThat(spyConsentManager.getUx()).isEqualTo(ux);
+
+ spyConsentManager.setUx(ux);
+ }
+
+ verify(mAppSearchConsentManagerMock, times(5)).getUx();
+ verify(mAppSearchConsentManagerMock, times(5)).setUx(any());
+ }
+
+ @Test
+ public void testGetEnrollmentChannel_ppapiOnly() throws RemoteException, IOException {
+ getEnrollmentChannelWithPpApiOnly(Flags.PPAPI_ONLY);
+ }
+
+ @Test
+ public void testGetEnrollmentChannel_ppapiAndAdExtDataServiceOnly()
+ throws RemoteException, IOException {
+ when(mMockFlags.getEnableAdExtServiceConsentData()).thenReturn(true);
+ getEnrollmentChannelWithPpApiOnly(Flags.PPAPI_AND_ADEXT_SERVICE);
+ }
+
+ private void getEnrollmentChannelWithPpApiOnly(int consentSourceOfTruth)
+ throws RemoteException {
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ for (PrivacySandboxEnrollmentChannelCollection channel :
+ ux.getEnrollmentChannelCollection()) {
+ doReturn(channel).when(mUxStatesDaoMock).getEnrollmentChannel(ux);
+ assertThat(spyConsentManager.getEnrollmentChannel(ux)).isEqualTo(channel);
+
+ spyConsentManager.setEnrollmentChannel(ux, channel);
+ }
+ }
+
+ verify(mUxStatesDaoMock, times(20)).getEnrollmentChannel(any());
+ verify(mUxStatesDaoMock, times(20)).setEnrollmentChannel(any(), any());
+ }
+
+ @Test
+ public void getEnrollmentChannel_SystemServerOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.SYSTEM_SERVER_ONLY;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ for (PrivacySandboxEnrollmentChannelCollection channel :
+ ux.getEnrollmentChannelCollection()) {
+ doReturn(channel.toString()).when(mMockIAdServicesManager).getEnrollmentChannel();
+ assertThat(spyConsentManager.getEnrollmentChannel(ux)).isEqualTo(channel);
+
+ spyConsentManager.setEnrollmentChannel(ux, channel);
+ }
+ }
+
+ verify(mMockIAdServicesManager, times(20)).getEnrollmentChannel();
+ verify(mMockIAdServicesManager, times(20)).setEnrollmentChannel(anyString());
+ }
+
+ @Test
+ public void getEnrollmentChannel_PpApiAndSystemServer() throws RemoteException {
+ int consentSourceOfTruth = Flags.PPAPI_AND_SYSTEM_SERVER;
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ for (PrivacySandboxEnrollmentChannelCollection channel :
+ ux.getEnrollmentChannelCollection()) {
+ doReturn(channel.toString()).when(mMockIAdServicesManager).getEnrollmentChannel();
+ assertThat(spyConsentManager.getEnrollmentChannel(ux)).isEqualTo(channel);
+
+ spyConsentManager.setEnrollmentChannel(ux, channel);
+ }
+ }
+
+ verify(mMockIAdServicesManager, times(20)).getEnrollmentChannel();
+ verify(mMockIAdServicesManager, times(20)).setEnrollmentChannel(anyString());
+ }
+
+ @Test
+ public void getEnrollmentChannel_appSearchOnly() throws RemoteException {
+ int consentSourceOfTruth = Flags.APPSEARCH_ONLY;
+ when(mMockFlags.getEnableAppsearchConsentData()).thenReturn(true);
+ ConsentManagerV2 spyConsentManager =
+ getSpiedConsentManagerForMigrationTesting(
+ /* isGiven */ false, consentSourceOfTruth);
+
+ for (PrivacySandboxUxCollection ux : PrivacySandboxUxCollection.values()) {
+ for (PrivacySandboxEnrollmentChannelCollection channel :
+ ux.getEnrollmentChannelCollection()) {
+ doReturn(channel).when(mAppSearchConsentManagerMock).getEnrollmentChannel(ux);
+ assertThat(spyConsentManager.getEnrollmentChannel(ux)).isEqualTo(channel);
+
+ spyConsentManager.setEnrollmentChannel(ux, channel);
+ }
+ }
+
+ verify(mAppSearchConsentManagerMock, times(20)).getEnrollmentChannel(any());
+ verify(mAppSearchConsentManagerMock, times(20)).setEnrollmentChannel(any(), any());
+ }
+}
diff --git a/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/UxEngineTest.java b/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/UxEngineTest.java
index f52fe2d82..0cdbf6701 100644
--- a/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/UxEngineTest.java
+++ b/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/UxEngineTest.java
@@ -19,7 +19,7 @@ package com.android.adservices.service.ui;
import static com.android.adservices.service.FlagsConstants.KEY_ADSERVICES_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_GA_UX_FEATURE_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_IS_U18_UX_DETENTION_CHANNEL_ENABLED;
-import static com.android.adservices.service.FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED;
+import static com.android.adservices.service.FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_RVC_UX_ENABLED;
import static com.android.adservices.service.FlagsConstants.KEY_U18_UX_ENABLED;
import static com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection.BETA_UX;
@@ -748,7 +748,7 @@ public class UxEngineTest {
verify(mUxStatesManager).getFlag(KEY_RVC_UX_ENABLED);
// RVC UX logic where flag is checked once in RvcPostOTAChannel.
- verify(mUxStatesManager).getFlag(KEY_RVC_NOTIFICATION_ENABLED);
+ verify(mUxStatesManager).getFlag(KEY_RVC_POST_OTA_NOTIFICATION_ENABLED);
// The UX can not be updated due to the fact that graduation channel is currently disabled.
verify(mConsentManager, never()).setUx(any());
diff --git a/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/AlreadyEnrolledChannelTest.java b/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/AlreadyEnrolledChannelTest.java
index ff676ef37..aafd575ad 100644
--- a/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/AlreadyEnrolledChannelTest.java
+++ b/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/AlreadyEnrolledChannelTest.java
@@ -151,15 +151,4 @@ public final class AlreadyEnrolledChannelTest extends AdServicesExtendedMockitoT
mUxStatesManager))
.isFalse();
}
-
- // @Test
- // public void enrollTest_enrollDoesNotTriggerNotification() {
- // mAlreadyEnrolledChannel.enroll(appContext.get(), mConsentManager);
- // verify(
- // () ->
- // ConsentNotificationJobService.schedule(
- // any(Context.class), anyBoolean(), anyBoolean()),
- // never());
- // }
-
}
diff --git a/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/RvcPostOTAChannelTest.java b/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/RvcPostOTAChannelTest.java
index d8a222b08..1d0b4f932 100644
--- a/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/RvcPostOTAChannelTest.java
+++ b/adservices/tests/unittest/ui/src/com/android/adservices/service/ui/enrollment/RvcPostOTAChannelTest.java
@@ -16,7 +16,7 @@
package com.android.adservices.service.ui.enrollment;
-import static com.android.adservices.service.FlagsConstants.KEY_RVC_NOTIFICATION_ENABLED;
+import static com.android.adservices.service.FlagsConstants.KEY_RVC_POST_OTA_NOTIFICATION_ENABLED;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -87,7 +87,7 @@ public class RvcPostOTAChannelTest {
@Test
public void isEligibleTest_isRvcAdultUser() {
- doReturn(true).when(mUxStatesManager).getFlag(KEY_RVC_NOTIFICATION_ENABLED);
+ doReturn(true).when(mUxStatesManager).getFlag(KEY_RVC_POST_OTA_NOTIFICATION_ENABLED);
doReturn(true).when(mConsentManager).isOtaAdultUserFromRvc();
assertThat(
@@ -100,7 +100,7 @@ public class RvcPostOTAChannelTest {
@Test
public void isEligibleTest_notRvcAdultUser() {
- doReturn(true).when(mUxStatesManager).getFlag(KEY_RVC_NOTIFICATION_ENABLED);
+ doReturn(true).when(mUxStatesManager).getFlag(KEY_RVC_POST_OTA_NOTIFICATION_ENABLED);
doReturn(false).when(mConsentManager).isOtaAdultUserFromRvc();
assertThat(
diff --git a/apex/Android.bp b/apex/Android.bp
index 8305223e3..3036699db 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -115,6 +115,7 @@ bootclasspath_fragment {
"android.adservices.exceptions",
"android.adservices.extdata",
"android.adservices.measurement",
+ "android.adservices.shell",
"android.adservices.signals",
"android.adservices.topics",
"android.app.adservices",
diff --git a/sdksandbox/service/java/com/android/server/sdksandbox/SdkSandboxManagerService.java b/sdksandbox/service/java/com/android/server/sdksandbox/SdkSandboxManagerService.java
index 43e141987..6714cd178 100644
--- a/sdksandbox/service/java/com/android/server/sdksandbox/SdkSandboxManagerService.java
+++ b/sdksandbox/service/java/com/android/server/sdksandbox/SdkSandboxManagerService.java
@@ -217,20 +217,11 @@ public class SdkSandboxManagerService extends ISdkSandboxManager.Stub {
private static final String WEBVIEW_SAFE_MODE_CONTENT_PROVIDER = "SafeModeContentProvider";
- // On UDC, AdServicesManagerService.Lifecycle implements dumpable so it's dumped as part of
- // SystemServer.
// If AdServices register itself as binder service, dump() will ignore the --AdServices option
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
static final String DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_AD_SERVICES_ITSELF =
"Don't need to dump AdServices as it's available as " + AD_SERVICES_SYSTEM_SERVICE;
- // On UDC, if AdServices register itself as binder service, dump() will ignore the --AdServices
- // option because AdServices could be dumped as part of SystemService
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- static final String DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_SYSTEM_SERVICE =
- "Don't need to dump AdServices on UDC+ - use "
- + "'dumpsys system_server_dumper --name AdServices instead'";
-
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
static final ArraySet<String> DEFAULT_ACTIVITY_ALLOWED_ACTIONS =
new ArraySet<>(
@@ -1164,17 +1155,6 @@ public class SdkSandboxManagerService extends ISdkSandboxManager.Stub {
}
}
- if (SdkLevel.isAtLeastU()) {
- // AdServices didn't register itself as binder service, but
- // AdServicesManagerService.Lifecycle implements Dumpable so it's dumped as
- // part of SystemServer
- if (quiet) {
- Log.d(TAG, DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_SYSTEM_SERVICE);
- } else {
- writer.println(DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_SYSTEM_SERVICE);
- }
- return;
- }
writer.print("AdServices:");
IBinder adServicesManager = getAdServicesManager();
if (adServicesManager == null) {
diff --git a/sdksandbox/tests/cts/endtoendtests/Android.bp b/sdksandbox/tests/cts/endtoendtests/Android.bp
index 3684cbee7..c477725f9 100644
--- a/sdksandbox/tests/cts/endtoendtests/Android.bp
+++ b/sdksandbox/tests/cts/endtoendtests/Android.bp
@@ -48,6 +48,7 @@ android_test {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
}
@@ -78,5 +79,6 @@ android_test {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
}
diff --git a/sdksandbox/tests/cts/endtoendtests/AndroidTest.xml b/sdksandbox/tests/cts/endtoendtests/AndroidTest.xml
index 04237b6c1..8d58b9c56 100644
--- a/sdksandbox/tests/cts/endtoendtests/AndroidTest.xml
+++ b/sdksandbox/tests/cts/endtoendtests/AndroidTest.xml
@@ -20,6 +20,24 @@
<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-user-token" value="%TEST_USER%"/>
+
+ <!-- IMPORTANT: This needs to come before SuiteApkInstaller
+
+ SuiteApkInstaller is not able to uninstall the Sdk-Provider.apk because the test
+ app that requires it is still installed at that point. This means the apk would
+ stay on the test device after the test ends.
+
+ This preparer, during tear down, runs after SuiteApkInstaller and will finally
+ uninstall the provider, leaving the device in a clean state.
+
+ See b/314294893 for more details.
+ -->
+ <target_preparer
+ class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="teardown-command"
+ value="pm --user %TEST_USER% uninstall com.android.ctssdkprovider"/>
+ </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true"/>
@@ -41,7 +59,6 @@
<option name="teardown-command" value="cmd sdk_sandbox set-state --reset" />
</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" />
diff --git a/sdksandbox/tests/cts/endtoendtests/DisabledAndroidTest.xml b/sdksandbox/tests/cts/endtoendtests/DisabledAndroidTest.xml
index 98f3e93e3..9c266f849 100644
--- a/sdksandbox/tests/cts/endtoendtests/DisabledAndroidTest.xml
+++ b/sdksandbox/tests/cts/endtoendtests/DisabledAndroidTest.xml
@@ -20,6 +20,26 @@
<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-user-token" value="%TEST_USER%"/>
+
+ <!-- IMPORTANT: This needs to come before SuiteApkInstaller
+
+ SuiteApkInstaller is not able to uninstall the Sdk-Provider.apk because the test
+ app that requires it is still installed at that point. This means the apk would
+ stay on the test device after the test ends.
+
+ This preparer, during tear down, runs after SuiteApkInstaller and will finally
+ uninstall the provider, leaving the device in a clean state.
+
+ See b/314294893 for more details.
+ -->
+ <target_preparer
+ class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="teardown-command"
+ value="pm --user %TEST_USER% uninstall com.android.ctssdkprovider"/>
+ </target_preparer>
+
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true"/>
<option name="test-file-name" value="SdkSandboxManagerCtsProvider.apk"/>
@@ -37,7 +57,6 @@
<option name="teardown-command" value="cmd sdk_sandbox set-state --reset" />
</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" />
diff --git a/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/Android.bp b/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/Android.bp
index 25723690b..869d57534 100644
--- a/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/Android.bp
+++ b/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/Android.bp
@@ -25,6 +25,7 @@ android_test_helper_app {
],
static_libs: [
"CtsMediationTestSdkApi",
+ "CtsSdkProviderApi",
"compatibility-device-util-axt",
"SdkSandboxTestUtils",
],
diff --git a/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/IMediationTestSdkApi.aidl b/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/IMediationTestSdkApi.aidl
index 702f115f5..dd00bc0f2 100644
--- a/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/IMediationTestSdkApi.aidl
+++ b/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/IMediationTestSdkApi.aidl
@@ -21,4 +21,5 @@ interface IMediationTestSdkApi {
List<AppOwnedSdkSandboxInterface> getAppOwnedSdkSandboxInterfaces();
List<SandboxedSdk> getSandboxedSdks();
void loadSdkBySdk(String sdkName);
+ void checkCanCallMediateeInterface(boolean inSandbox, String expectedValue);
}
diff --git a/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/MediationTestSdkApiImpl.java b/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/MediationTestSdkApiImpl.java
index 68e1c1d34..e521e0282 100644
--- a/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/MediationTestSdkApiImpl.java
+++ b/sdksandbox/tests/cts/endtoendtests/providers/MediationProvider/src/com/android/sdksandbox/cts/provider/mediationtest/MediationTestSdkApiImpl.java
@@ -23,6 +23,10 @@ import android.app.sdksandbox.sdkprovider.SdkSandboxController;
import android.app.sdksandbox.testutils.FakeLoadSdkCallback;
import android.content.Context;
import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.ctssdkprovider.ICtsSdkProviderApi;
import java.util.List;
@@ -60,4 +64,48 @@ public class MediationTestSdkApiImpl extends IMediationTestSdkApi.Stub {
throw new IllegalStateException(e);
}
}
+
+ /**
+ * Checks that the mediator can invoke an interface defined by a mediatee, either inside or
+ * outside the sandbox.
+ */
+ @Override
+ public void checkCanCallMediateeInterface(boolean inSandbox, String expectedValue) {
+ ICtsSdkProviderApi sdk = getMediateeInterface(inSandbox);
+ String clientPackageName;
+ try {
+ clientPackageName = sdk.getClientPackageName();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Cannot invoke interface: " + e.getMessage());
+ }
+ if (!clientPackageName.equals(expectedValue)) {
+ throw new IllegalStateException(
+ "String "
+ + clientPackageName
+ + " did not match expected value "
+ + expectedValue);
+ }
+ }
+
+ private ICtsSdkProviderApi getMediateeInterface(boolean inSandbox) {
+ if (inSandbox) {
+ List<SandboxedSdk> sandboxedSdks = getSandboxedSdks();
+ for (SandboxedSdk sandboxedSdk : sandboxedSdks) {
+ IBinder iBinder = sandboxedSdk.getInterface();
+ if (iBinder.queryLocalInterface(ICtsSdkProviderApi.DESCRIPTOR) != null) {
+ return ICtsSdkProviderApi.Stub.asInterface(iBinder);
+ }
+ }
+ } else {
+ List<AppOwnedSdkSandboxInterface> appOwnedInterfaces =
+ getAppOwnedSdkSandboxInterfaces();
+ for (AppOwnedSdkSandboxInterface appOwnedInterface : appOwnedInterfaces) {
+ IBinder iBinder = appOwnedInterface.getInterface();
+ if (iBinder.queryLocalInterface(ICtsSdkProviderApi.DESCRIPTOR) != null) {
+ return ICtsSdkProviderApi.Stub.asInterface(iBinder);
+ }
+ }
+ }
+ throw new IllegalStateException("No mediatee interface found.");
+ }
}
diff --git a/sdksandbox/tests/cts/endtoendtests/src/com/android/tests/sdksandbox/endtoend/SdkSandboxMediationTest.java b/sdksandbox/tests/cts/endtoendtests/src/com/android/tests/sdksandbox/endtoend/SdkSandboxMediationTest.java
index e1678fd80..b3a6f18bf 100644
--- a/sdksandbox/tests/cts/endtoendtests/src/com/android/tests/sdksandbox/endtoend/SdkSandboxMediationTest.java
+++ b/sdksandbox/tests/cts/endtoendtests/src/com/android/tests/sdksandbox/endtoend/SdkSandboxMediationTest.java
@@ -34,6 +34,7 @@ import android.os.RemoteException;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import com.android.ctssdkprovider.ICtsSdkProviderApi;
import com.android.sdksandbox.cts.provider.mediationtest.IMediationTestSdkApi;
import org.junit.After;
@@ -69,7 +70,6 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
private Context mContext;
private SdkSandboxManager mSdkSandboxManager;
- private IMediationTestSdkApi mSdk;
@Before
public void setup() {
@@ -102,7 +102,7 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
@Test
public void testGetAppOwnedSdkSandboxInterfaces() throws Exception {
- loadMediatorSdkAndPopulateInterface();
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
IBinder iBinder = new Binder();
mSdkSandboxManager.registerAppOwnedSdkSandboxInterface(
new AppOwnedSdkSandboxInterface(
@@ -111,7 +111,7 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
/*interfaceIBinder=*/ iBinder));
final List<AppOwnedSdkSandboxInterface> appOwnedSdkSandboxInterfaceList =
- mSdk.getAppOwnedSdkSandboxInterfaces();
+ mediatorSdk.getAppOwnedSdkSandboxInterfaces();
assertThat(appOwnedSdkSandboxInterfaceList).hasSize(1);
@@ -123,13 +123,13 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
@Test
public void testGetAppOwnedSdkSandboxInterfaces_NoInterface() throws Exception {
- loadMediatorSdkAndPopulateInterface();
- assertThat(mSdk.getAppOwnedSdkSandboxInterfaces()).hasSize(0);
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
+ assertThat(mediatorSdk.getAppOwnedSdkSandboxInterfaces()).hasSize(0);
}
@Test
public void testGetAppOwnedSdkSandboxInterfaces_MultipleInterfaces() throws Exception {
- loadMediatorSdkAndPopulateInterface();
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
IBinder iBinder = new Binder();
mSdkSandboxManager.registerAppOwnedSdkSandboxInterface(
new AppOwnedSdkSandboxInterface(
@@ -144,7 +144,7 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
/*version=*/ 1,
/*interfaceIBinder=*/ iBinder2));
final List<AppOwnedSdkSandboxInterface> appOwnedSdkSandboxInterfaceList =
- mSdk.getAppOwnedSdkSandboxInterfaces();
+ mediatorSdk.getAppOwnedSdkSandboxInterfaces();
assertThat(appOwnedSdkSandboxInterfaceList).hasSize(2);
@@ -169,9 +169,9 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
@Test
public void testGetSandboxedSdk_GetsAllSdksLoadedInTheSandbox() throws Exception {
- loadMediatorSdkAndPopulateInterface();
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
- final List<SandboxedSdk> sandboxedSdks = mSdk.getSandboxedSdks();
+ final List<SandboxedSdk> sandboxedSdks = mediatorSdk.getSandboxedSdks();
assertThat(sandboxedSdks).hasSize(1);
assertThat(sandboxedSdks.get(0).getInterface().getInterfaceDescriptor())
.isEqualTo(
@@ -181,10 +181,10 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
@Test
public void testGetSandboxedSdk_MultipleSdks() throws Exception {
- loadMediatorSdkAndPopulateInterface();
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
loadMediateeSdk();
- final List<SandboxedSdk> sandboxedSdks = mSdk.getSandboxedSdks();
+ final List<SandboxedSdk> sandboxedSdks = mediatorSdk.getSandboxedSdks();
assertThat(sandboxedSdks).hasSize(2);
Set<String> interfaceDescriptors =
sandboxedSdks.stream()
@@ -207,10 +207,10 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
@Test
public void testLoadSdkByOtherSdk() throws Exception {
- loadMediatorSdkAndPopulateInterface();
- mSdk.loadSdkBySdk(MEDIATEE_SDK_NAME);
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
+ mediatorSdk.loadSdkBySdk(MEDIATEE_SDK_NAME);
- final List<SandboxedSdk> sandboxedSdks = mSdk.getSandboxedSdks();
+ final List<SandboxedSdk> sandboxedSdks = mediatorSdk.getSandboxedSdks();
assertThat(sandboxedSdks).hasSize(2);
Set<String> loadedSdks =
sandboxedSdks.stream()
@@ -225,10 +225,11 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
@Test
public void testLoadSdkBySameSdk() throws Exception {
- loadMediatorSdkAndPopulateInterface();
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
IllegalStateException exception =
assertThrows(
- IllegalStateException.class, () -> mSdk.loadSdkBySdk(MEDIATOR_SDK_NAME));
+ IllegalStateException.class,
+ () -> mediatorSdk.loadSdkBySdk(MEDIATOR_SDK_NAME));
assertThat(exception.getMessage())
.isEqualTo(
"java.lang.AssertionError: Load SDK was not successful. errorCode: 101,"
@@ -239,10 +240,12 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
@Test
public void testLoadSdkThatDoesNotExist() throws Exception {
- loadMediatorSdkAndPopulateInterface();
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
final String nonExistingSdk = "non-existing-sdk";
IllegalStateException exception =
- assertThrows(IllegalStateException.class, () -> mSdk.loadSdkBySdk(nonExistingSdk));
+ assertThrows(
+ IllegalStateException.class,
+ () -> mediatorSdk.loadSdkBySdk(nonExistingSdk));
assertThat(exception.getMessage())
.isEqualTo(
"java.lang.AssertionError: "
@@ -253,18 +256,36 @@ public class SdkSandboxMediationTest extends SandboxKillerBeforeTest {
+ " not found for loading");
}
- private void loadMediatorSdkAndPopulateInterface() {
+ @Test
+ public void testSandboxedSdkCanCallAppSdk() throws Exception {
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
+ // we load the mediatee SDK to get a handle to its IBinder, which will be registered as an
+ // app owned interface. This is done to avoid re-implementing an ICtsSdkProviderApi.
+ ICtsSdkProviderApi mediateeSdk = loadMediateeSdk();
+ mSdkSandboxManager.registerAppOwnedSdkSandboxInterface(
+ new AppOwnedSdkSandboxInterface("mediatee", 1, mediateeSdk.asBinder()));
+ mediatorSdk.checkCanCallMediateeInterface(/*inSandbox=*/ false, mContext.getPackageName());
+ }
+
+ @Test
+ public void testSandboxedSdkCanCallSandboxedSdk() throws Exception {
+ IMediationTestSdkApi mediatorSdk = loadMediatorSdk();
+ loadMediateeSdk();
+ mediatorSdk.checkCanCallMediateeInterface(/*inSandbox=*/ true, mContext.getPackageName());
+ }
+
+ private IMediationTestSdkApi loadMediatorSdk() {
FakeLoadSdkCallback callback = new FakeLoadSdkCallback();
mSdkSandboxManager.loadSdk(MEDIATOR_SDK_NAME, new Bundle(), Runnable::run, callback);
callback.assertLoadSdkIsSuccessful();
- // Store the returned SDK interface so that we can interact with it later.
- mSdk = IMediationTestSdkApi.Stub.asInterface(callback.getSandboxedSdk().getInterface());
+ return IMediationTestSdkApi.Stub.asInterface(callback.getSandboxedSdk().getInterface());
}
- private void loadMediateeSdk() {
+ private ICtsSdkProviderApi loadMediateeSdk() {
FakeLoadSdkCallback callback = new FakeLoadSdkCallback();
mSdkSandboxManager.loadSdk(MEDIATEE_SDK_NAME, new Bundle(), Runnable::run, callback);
callback.assertLoadSdkIsSuccessful();
+ return ICtsSdkProviderApi.Stub.asInterface(callback.getSandboxedSdk().getInterface());
}
}
diff --git a/sdksandbox/tests/cts/hostside/Android.bp b/sdksandbox/tests/cts/hostside/Android.bp
index 39ad735a1..d48ec7bec 100644
--- a/sdksandbox/tests/cts/hostside/Android.bp
+++ b/sdksandbox/tests/cts/hostside/Android.bp
@@ -31,6 +31,7 @@ java_test_host {
"cts",
"mts-adservices",
"general-tests",
+ "mcts-adservices",
],
data: [
":CtsSdkSandboxHostTestApp",
diff --git a/sdksandbox/tests/cts/inprocess/Android.bp b/sdksandbox/tests/cts/inprocess/Android.bp
index 9a367342e..94090c2c3 100644
--- a/sdksandbox/tests/cts/inprocess/Android.bp
+++ b/sdksandbox/tests/cts/inprocess/Android.bp
@@ -43,9 +43,10 @@ android_test {
test_suites: [
"cts",
"mts-adservices",
- "general-tests"
+ "general-tests",
+ "mcts-adservices",
],
test_options: {
extra_test_configs: ["AndroidTest_MultiUser.xml"]
},
-}
+} \ No newline at end of file
diff --git a/sdksandbox/tests/cts/inprocess/src/com/android/sdksandbox/tests/cts/inprocess/SdkSandboxConfigurationTest.java b/sdksandbox/tests/cts/inprocess/src/com/android/sdksandbox/tests/cts/inprocess/SdkSandboxConfigurationTest.java
index 4a356ca0d..618a1eeb8 100644
--- a/sdksandbox/tests/cts/inprocess/src/com/android/sdksandbox/tests/cts/inprocess/SdkSandboxConfigurationTest.java
+++ b/sdksandbox/tests/cts/inprocess/src/com/android/sdksandbox/tests/cts/inprocess/SdkSandboxConfigurationTest.java
@@ -36,6 +36,9 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.PackageInfoFlags;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.media.AudioManager;
import android.os.IBinder;
import android.os.Process;
import android.os.SELinux;
@@ -68,6 +71,9 @@ public class SdkSandboxConfigurationTest {
private static final String TEST_PKG = "com.android.sdksandbox.tests.cts.inprocesstests";
private static final String CURRENT_USER_ID =
String.valueOf(Process.myUserHandle().getUserId(Process.myUid()));
+ private final Context mContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+ private final PackageManager mPackageManager = mContext.getPackageManager();
@Before
public void setUp() {
@@ -76,11 +82,9 @@ public class SdkSandboxConfigurationTest {
InstrumentationRegistry.getInstrumentation().getContext()));
}
- /**
- * Tests that uid belongs to the sdk sandbox processes uid range.
- */
+ /** Tests that uid belongs to the sdk sandbox processes uid range. */
@Test
- public void testUidBelongsToSdkSandboxRange() throws Exception {
+ public void testUidBelongsToSdkSandboxRange() {
int myUid = Process.myUid();
assertWithMessage(myUid + " is not a SdkSandbox uid").that(Process.isSdkSandbox()).isTrue();
}
@@ -89,17 +93,17 @@ public class SdkSandboxConfigurationTest {
* Tests that sdk sandbox processes are running under the {@code sdk_sandbox} selinux domain.
*/
@Test
- public void testCorrectSelinuxDomain() throws Exception {
- final String ctx = SELinux.getContext();
- assertThat(ctx).contains("u:r:sdk_sandbox");
+ public void testCorrectSelinuxDomain() {
+ final String selinuxContext = SELinux.getContext();
+ assertThat(selinuxContext).contains("u:r:sdk_sandbox");
}
/** Tests that sdk sandbox SDK minimum and target versions are correct. */
@Test
public void testCorrectSdkVersion() throws Exception {
- final Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
- final PackageManager pm = ctx.getPackageManager();
- final PackageInfo info = pm.getPackageInfo(ctx.getPackageName(), PackageInfoFlags.of(0));
+ final PackageManager pm = mContext.getPackageManager();
+ final PackageInfo info =
+ pm.getPackageInfo(mContext.getPackageName(), PackageInfoFlags.of(0));
int minSdkVersion = info.applicationInfo.minSdkVersion;
assertThat(minSdkVersion).isEqualTo(33);
@@ -113,21 +117,18 @@ public class SdkSandboxConfigurationTest {
*/
@Test
public void testClientAppIsVisibleToSdkSandbox() throws Exception {
- final Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
- final PackageManager pm = ctx.getPackageManager();
- final PackageInfo info = pm.getPackageInfo(TEST_PKG, PackageInfoFlags.of(0));
+ final PackageInfo info = mPackageManager.getPackageInfo(TEST_PKG, PackageInfoFlags.of(0));
assertThat(info.applicationInfo.uid).isEqualTo(
Process.getAppUidForSdkSandboxUid(Process.myUid()));
}
/**
- * Tests that {@link Context#getDataDir()} returns correct value for the CE storage of the
- * sak sandbox.
+ * Tests that {@link Context#getDataDir()} returns correct value for the CE storage of the sak
+ * sandbox.
*/
@Test
- public void testGetDataDir_CE() throws Exception {
- final Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
- final File dir = ctx.getDataDir();
+ public void testGetDataDir_CE() {
+ final File dir = mContext.getDataDir();
assertThat(dir.getAbsolutePath())
.isEqualTo(
"/data/misc_ce/" + CURRENT_USER_ID + "/sdksandbox/" + TEST_PKG + "/shared");
@@ -139,10 +140,7 @@ public class SdkSandboxConfigurationTest {
*/
@Test
public void testGetDataDir_DE() throws Exception {
- final Context ctx =
- InstrumentationRegistry.getInstrumentation()
- .getTargetContext()
- .createDeviceProtectedStorageContext();
+ final Context ctx = mContext.createDeviceProtectedStorageContext();
final File dir = ctx.getDataDir();
assertThat(dir.getAbsolutePath())
.isEqualTo(
@@ -152,13 +150,13 @@ public class SdkSandboxConfigurationTest {
/** Tests that sdk sandbox process can write to it's CE storage. */
@Test
public void testCanWriteToDataDir_CE() throws Exception {
- final Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
- try (OutputStreamWriter writer = new OutputStreamWriter(
- ctx.openFileOutput("random_ce_file", MODE_PRIVATE))) {
+ try (OutputStreamWriter writer =
+ new OutputStreamWriter(mContext.openFileOutput("random_ce_file", MODE_PRIVATE))) {
writer.write("I am an sdk sandbox");
}
- try (BufferedReader reader = new BufferedReader(
- new InputStreamReader(ctx.openFileInput("random_ce_file")))) {
+ try (BufferedReader reader =
+ new BufferedReader(
+ new InputStreamReader(mContext.openFileInput("random_ce_file")))) {
String line = reader.readLine();
assertThat(line).isEqualTo("I am an sdk sandbox");
}
@@ -167,10 +165,7 @@ public class SdkSandboxConfigurationTest {
/** Tests that sdk sandbox process can write to it's DE storage. */
@Test
public void testCanWriteToDataDir_DE() throws Exception {
- final Context ctx =
- InstrumentationRegistry.getInstrumentation()
- .getTargetContext()
- .createDeviceProtectedStorageContext();
+ final Context ctx = mContext.createDeviceProtectedStorageContext();
try (OutputStreamWriter writer = new OutputStreamWriter(
ctx.openFileOutput("random_de_file", MODE_PRIVATE))) {
writer.write("I am also an sdk sandbox");
@@ -190,13 +185,11 @@ public class SdkSandboxConfigurationTest {
assumeThat(
SdkSandboxManager.getSdkSandboxState(),
equalTo(SdkSandboxManager.SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION));
- final Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
// First check that we can resolve the adservices apk
- final PackageManager pm = ctx.getPackageManager();
final Intent resolveIntent = new Intent(AdServicesCommon.ACTION_TOPICS_SERVICE);
final List<ResolveInfo> services =
- pm.queryIntentServices(
+ mPackageManager.queryIntentServices(
resolveIntent,
PackageManager.ResolveInfoFlags.of(
PackageManager.GET_SERVICES
@@ -221,13 +214,13 @@ public class SdkSandboxConfigurationTest {
@Override
public void onServiceDisconnected(ComponentName name) {}
};
- final boolean ret = ctx.bindService(serviceIntent, conn, Context.BIND_AUTO_CREATE);
+ final boolean ret = mContext.bindService(serviceIntent, conn, Context.BIND_AUTO_CREATE);
try {
assertThat(ret).isTrue();
assertThat(latch.await(3, TimeUnit.SECONDS)).isTrue();
} finally {
- ctx.unbindService(conn);
+ mContext.unbindService(conn);
}
}
@@ -244,9 +237,30 @@ public class SdkSandboxConfigurationTest {
// Now time to query the current WebView provider through PackageManager, this is used to
// check if this sdk sandbox process can see the WebView.
- final Context ctx = InstrumentationRegistry.getInstrumentation().getTargetContext();
final PackageInfo webViewProviderInfo =
- ctx.getPackageManager().getPackageInfo(info.packageName, PackageInfoFlags.of(0));
+ mPackageManager.getPackageInfo(info.packageName, PackageInfoFlags.of(0));
assertThat(webViewProviderInfo).isNotNull();
}
+
+ @Test
+ public void testCanAccessGyroscope() {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_GYROSCOPE));
+
+ SensorManager sensorManager = mContext.getSystemService(SensorManager.class);
+ assertThat(sensorManager).isNotNull();
+ Sensor gyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
+ assertThat(gyroscope).isNotNull();
+ }
+
+ @Test
+ public void testCanAccessVolume() {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT));
+
+ AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+ int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_SYSTEM);
+ int minVolume = audioManager.getStreamMinVolume(AudioManager.STREAM_SYSTEM);
+ int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_SYSTEM);
+ assertThat(currentVolume).isAtMost(maxVolume);
+ assertThat(currentVolume).isAtLeast(minVolume);
+ }
}
diff --git a/sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java b/sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java
index 61a59810b..9b16bf2e3 100644
--- a/sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java
+++ b/sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java
@@ -27,11 +27,14 @@ import android.app.sdksandbox.testutils.ConfigListener;
import android.app.sdksandbox.testutils.DeviceConfigUtils;
import android.app.sdksandbox.testutils.EmptyActivity;
import android.app.sdksandbox.testutils.FakeLoadSdkCallback;
+import android.app.sdksandbox.testutils.ProtoUtil;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.DeviceConfig;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
@@ -211,9 +214,10 @@ public class BroadcastRestrictionsTestApp {
public void testRegisterBroadcastReceiver_DeviceConfigEmptyAllowlistApplied() throws Exception {
mDeviceConfigUtils.setProperty(PROPERTY_ENFORCE_RESTRICTIONS, "true");
- // Set an empty allowlist for effectiveTargetSdkVersion U. This should block all
- // BroadcastReceivers.
- mDeviceConfigUtils.setProperty(PROPERTY_BROADCASTRECEIVER_ALLOWLIST, "CgQIIhIA");
+ ArrayMap<Integer, List<String>> allowedIntentActions = new ArrayMap<>();
+ allowedIntentActions.put(34, new ArrayList<>());
+ String encodedAllowlist = ProtoUtil.encodeBroadcastReceiverAllowlist(allowedIntentActions);
+ mDeviceConfigUtils.setProperty(PROPERTY_BROADCASTRECEIVER_ALLOWLIST, encodedAllowlist);
loadSdk();
assertThrows(
@@ -232,12 +236,10 @@ public class BroadcastRestrictionsTestApp {
public void testRegisterBroadcastReceiver_DeviceConfigAllowlistApplied() throws Exception {
mDeviceConfigUtils.setProperty(PROPERTY_ENFORCE_RESTRICTIONS, "true");
- // Set an allowlist mapping from U to {android.intent.action.VIEW,
- // android.intent.action.SCREEN_OFF}
- final String encodedAllowlist =
- "CkIIIhI+ChphbmRyb2lkLmludGVudC5hY3Rpb24uVklFVwogYW5kcm9pZC5pbnRlbnQuYWN0aW9uLlNDUk"
- + "VFTl9PRkY=";
-
+ ArrayMap<Integer, List<String>> allowedIntentActions = new ArrayMap<>();
+ allowedIntentActions.put(
+ 34, new ArrayList<>(Arrays.asList(Intent.ACTION_VIEW, Intent.ACTION_SCREEN_OFF)));
+ String encodedAllowlist = ProtoUtil.encodeBroadcastReceiverAllowlist(allowedIntentActions);
mDeviceConfigUtils.setProperty(PROPERTY_BROADCASTRECEIVER_ALLOWLIST, encodedAllowlist);
loadSdk();
@@ -268,13 +270,10 @@ public class BroadcastRestrictionsTestApp {
mDeviceConfigUtils.setProperty(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, "true");
- // Base64 encoded proto AllowedBroadcastReceivers containing the strings Intent.ACTION_VIEW
- // and Intent.ACTION_SEND.
- String encodedNextAllowlist =
- "ChphbmRyb2lkLmludGVudC5hY3Rpb24uVklFVwoaYW5kcm9pZC5pbnRlbnQuYWN0aW9uLlNFTkQ=";
- // Set the canary set.
- mDeviceConfigUtils.setProperty(
- PROPERTY_NEXT_BROADCASTRECEIVER_ALLOWLIST, encodedNextAllowlist);
+ ArraySet<String> allowedIntentActions =
+ new ArraySet<>(Arrays.asList(Intent.ACTION_VIEW, Intent.ACTION_SEND));
+ String encodedAllowlist = ProtoUtil.encodeBroadcastReceiverAllowlist(allowedIntentActions);
+ mDeviceConfigUtils.setProperty(PROPERTY_NEXT_BROADCASTRECEIVER_ALLOWLIST, encodedAllowlist);
loadSdk();
// No exception should be thrown when registering a BroadcastReceiver with
diff --git a/sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java b/sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java
index 1f142edce..95528a90e 100644
--- a/sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java
+++ b/sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java
@@ -27,10 +27,12 @@ import android.app.sdksandbox.testutils.ConfigListener;
import android.app.sdksandbox.testutils.DeviceConfigUtils;
import android.app.sdksandbox.testutils.EmptyActivity;
import android.app.sdksandbox.testutils.FakeLoadSdkCallback;
+import android.app.sdksandbox.testutils.ProtoUtil;
import android.content.Context;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.DeviceConfig;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.webkit.WebViewUpdateService;
@@ -47,7 +49,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
@RunWith(JUnit4.class)
public class ContentProviderRestrictionsTestApp {
@@ -169,17 +173,16 @@ public class ContentProviderRestrictionsTestApp {
public void testGetContentProvider_DeviceConfigAllowlistApplied() throws Exception {
mDeviceConfigUtils.setProperty(ENFORCE_RESTRICTIONS, "true");
- /**
- * Base64 encoded proto ContentProviderAllowlists containing allowlist_per_target_sdk { key:
- * 34 value { authorities: "com.android.textclassifier.icons" authorities: "user_dictionary"
- * } }
- *
- * <p>allowlist_per_target_sdk { key: 35 value { authorities:
- * "com.android.textclassifier.icons" authorities: "user_dictionary" } }
- */
- String encodedAllowlist =
- "CjcIIhIzCiBjb20uYW5kcm9pZC50ZXh0Y2xhc3NpZmllci5pY29ucwoPdXNlcl9kaWN0aW9uYXJ5CjcII"
- + "xIzCiBjb20uYW5kcm9pZC50ZXh0Y2xhc3NpZmllci5pY29ucwoPdXNlcl9kaWN0aW9uYXJ5";
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(
+ 34,
+ new ArrayList<>(
+ Arrays.asList("com.android.textclassifier.icons", "user_dictionary")));
+ allowedAuthorities.put(
+ 35,
+ new ArrayList<>(
+ Arrays.asList("com.android.textclassifier.icons", "user_dictionary")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
@@ -198,19 +201,19 @@ public class ContentProviderRestrictionsTestApp {
mDeviceConfigUtils.setProperty(ENFORCE_RESTRICTIONS, "true");
mDeviceConfigUtils.setProperty(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, "true");
- // Base64 encoded proto AllowedContentProviders containing the string
- // 'com.android.textclassifier.icons'
- String encodedNextAllowlist = "CiBjb20uYW5kcm9pZC50ZXh0Y2xhc3NpZmllci5pY29ucw==";
- // Set the canary set.
+ ArraySet<String> nextAllowedAuthorities =
+ new ArraySet<>(Arrays.asList("com.android.textclassifier.icons"));
+ String nextEncodedAllowlist =
+ ProtoUtil.encodeContentProviderAllowlist(nextAllowedAuthorities);
mDeviceConfigUtils.setProperty(
- PROPERTY_NEXT_CONTENTPROVIDER_ALLOWLIST, encodedNextAllowlist);
-
- // Base64 encoded proto ContentProviderAllowlists containing mappings to the string
- // 'com.android.textclassifier.icons' and 'user_dictionary'.
- String encodedAllowlist =
- "CjcIIhIzCiBjb20uYW5kcm9pZC50ZXh0Y2xhc3NpZmllci5pY29ucwoPdXNlcl9kaWN0aW9uYXJ5";
- // Also set the non-canary allowlist to verify that this allowlist is not applied when the
- // canary flag is set.
+ PROPERTY_NEXT_CONTENTPROVIDER_ALLOWLIST, nextEncodedAllowlist);
+
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(
+ 34,
+ new ArrayList<>(
+ Arrays.asList("com.android.textclassifier.icons", "user_dictionary")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
@@ -227,16 +230,9 @@ public class ContentProviderRestrictionsTestApp {
public void testGetContentProvider_DeviceConfigWildcardAllowlistApplied() throws Exception {
mDeviceConfigUtils.setProperty(ENFORCE_RESTRICTIONS, "true");
- /*
- * Base64 encoded proto ContentProviderAllowlists in the following form:
- * allowlist_per_target_sdk {
- * key: 34
- * value {
- * authorities: "*"
- * }
- * }
- */
- String encodedAllowlist = "CgcIIhIDCgEq";
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(34, new ArrayList<>(Arrays.asList("*")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
@@ -251,16 +247,9 @@ public class ContentProviderRestrictionsTestApp {
public void testGetContentProvider_DeviceConfigAllowlistWithWildcardApplied() throws Exception {
mDeviceConfigUtils.setProperty(ENFORCE_RESTRICTIONS, "true");
- /*
- * Base64 encoded proto ContentProviderAllowlists in the following form:
- * allowlist_per_target_sdk {
- * key: 34
- * value {
- * authorities: "com.android.contacts.*"
- * }
- * }
- */
- String encodedAllowlist = "ChwIIhIYChZjb20uYW5kcm9pZC5jb250YWN0cy4q";
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(34, new ArrayList<>(Arrays.asList("com.android.contacts.*")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
mContentProvidersSdkApi.getContentProviderByAuthority(
@@ -335,16 +324,9 @@ public class ContentProviderRestrictionsTestApp {
throws Exception {
mDeviceConfigUtils.setProperty(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, "true");
- /*
- * Base64 encoded proto ContentProviderAllowlists in the following form:
- * allowlist_per_target_sdk {
- * key: 34
- * value {
- * authorities: "com.android.contacts.*"
- * }
- * }
- */
- String encodedAllowlist = "ChwIIhIYChZjb20uYW5kcm9pZC5jb250YWN0cy4q";
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(34, new ArrayList<>(Arrays.asList("com.android.contacts.*")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
mContentProvidersSdkApi.getContentProviderByAuthority(
diff --git a/sdksandbox/tests/testutils/src/android/app/sdksandbox/testutils/ProtoUtil.java b/sdksandbox/tests/testutils/src/android/app/sdksandbox/testutils/ProtoUtil.java
new file mode 100644
index 000000000..aedf8863c
--- /dev/null
+++ b/sdksandbox/tests/testutils/src/android/app/sdksandbox/testutils/ProtoUtil.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2024 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 android.app.sdksandbox.testutils;
+
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Base64;
+
+import com.android.server.sdksandbox.proto.Activity.ActivityAllowlists;
+import com.android.server.sdksandbox.proto.Activity.AllowedActivities;
+import com.android.server.sdksandbox.proto.BroadcastReceiver.AllowedBroadcastReceivers;
+import com.android.server.sdksandbox.proto.BroadcastReceiver.BroadcastReceiverAllowlists;
+import com.android.server.sdksandbox.proto.ContentProvider.AllowedContentProviders;
+import com.android.server.sdksandbox.proto.ContentProvider.ContentProviderAllowlists;
+import com.android.server.sdksandbox.proto.Services.AllowedService;
+import com.android.server.sdksandbox.proto.Services.AllowedServices;
+import com.android.server.sdksandbox.proto.Services.ServiceAllowlists;
+
+import java.util.List;
+
+/** Utility class to get encoded string for various restrictions */
+public class ProtoUtil {
+ /** Encode authorities for ContentProvider Allowlist */
+ public static String encodeContentProviderAllowlist(
+ ArrayMap<Integer, List<String>> authorities) {
+ ContentProviderAllowlists.Builder contentProviderAllowlistsBuilder =
+ ContentProviderAllowlists.newBuilder();
+
+ authorities.entrySet().stream()
+ .forEach(
+ x -> {
+ AllowedContentProviders allowedContentProvidersBuilder =
+ AllowedContentProviders.newBuilder()
+ .addAllAuthorities(x.getValue())
+ .build();
+ contentProviderAllowlistsBuilder.putAllowlistPerTargetSdk(
+ x.getKey(), allowedContentProvidersBuilder);
+ });
+ ContentProviderAllowlists contentProviderAllowlists =
+ contentProviderAllowlistsBuilder.build();
+
+ return Base64.encodeToString(
+ contentProviderAllowlists.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ /** Encode authorities for ContentProvider Allowlist */
+ public static String encodeContentProviderAllowlist(ArraySet<String> authorities) {
+ AllowedContentProviders allowedContentProvidersBuilder =
+ AllowedContentProviders.newBuilder().addAllAuthorities(authorities).build();
+ return Base64.encodeToString(
+ allowedContentProvidersBuilder.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ /** Encode intent actions for startActivity Allowlist */
+ public static String encodeActivityAllowlist(ArrayMap<Integer, List<String>> actions) {
+ ActivityAllowlists.Builder activityAllowlistsBuilder = ActivityAllowlists.newBuilder();
+
+ actions.entrySet().stream()
+ .forEach(
+ x -> {
+ AllowedActivities allowedActivitiesBuilder =
+ AllowedActivities.newBuilder()
+ .addAllActions(x.getValue())
+ .build();
+ activityAllowlistsBuilder.putAllowlistPerTargetSdk(
+ x.getKey(), allowedActivitiesBuilder);
+ });
+ ActivityAllowlists activityAllowlists = activityAllowlistsBuilder.build();
+ String res =
+ Base64.encodeToString(
+ activityAllowlists.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+
+ return res;
+ }
+
+ /** Encode intent actions for broadcastReceivers Allowlist */
+ public static String encodeBroadcastReceiverAllowlist(
+ ArrayMap<Integer, List<String>> intentActions) {
+ BroadcastReceiverAllowlists.Builder broadcastReceiverAllowlistBuilder =
+ BroadcastReceiverAllowlists.newBuilder();
+
+ intentActions.entrySet().stream()
+ .forEach(
+ x -> {
+ AllowedBroadcastReceivers allowedBroadcastReceivers =
+ AllowedBroadcastReceivers.newBuilder()
+ .addAllIntentActions(x.getValue())
+ .build();
+
+ broadcastReceiverAllowlistBuilder.putAllowlistPerTargetSdk(
+ x.getKey(), allowedBroadcastReceivers);
+ });
+ BroadcastReceiverAllowlists broadcastReceiverAllowlist =
+ broadcastReceiverAllowlistBuilder.build();
+ return Base64.encodeToString(
+ broadcastReceiverAllowlist.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ /** Encode intent actions for broadcastReceivers Allowlist */
+ public static String encodeBroadcastReceiverAllowlist(ArraySet<String> actions) {
+ AllowedBroadcastReceivers allowedBroadcastReceivers =
+ AllowedBroadcastReceivers.newBuilder().addAllIntentActions(actions).build();
+ return Base64.encodeToString(
+ allowedBroadcastReceivers.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ /**
+ * Encode intent action, packageName, component className, component packageName for Service
+ * Allowlist
+ */
+ public static String encodeServiceAllowlist(
+ ArrayMap<Integer, List<ArrayMap<String, String>>> services) {
+ ServiceAllowlists.Builder serviceAllowlistsBuilder = ServiceAllowlists.newBuilder();
+
+ services.entrySet().stream()
+ .forEach(
+ x -> {
+ AllowedServices.Builder allowedServicesBuilder =
+ AllowedServices.newBuilder();
+ if (x.getValue().size() == 0) {
+ allowedServicesBuilder.addAllowedServices(
+ AllowedService.newBuilder().build());
+ } else {
+ x.getValue()
+ .forEach(
+ service -> {
+ allowedServicesBuilder.addAllowedServices(
+ getAllowedService(service));
+ });
+ }
+ serviceAllowlistsBuilder.putAllowlistPerTargetSdk(
+ x.getKey(), allowedServicesBuilder.build());
+ });
+ ServiceAllowlists serviceAllowlists = serviceAllowlistsBuilder.build();
+ return Base64.encodeToString(
+ serviceAllowlists.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ private static AllowedService getAllowedService(ArrayMap<String, String> service) {
+ return AllowedService.newBuilder()
+ .setAction(service.get("action"))
+ .setPackageName(service.get("packageName"))
+ .setComponentClassName(service.get("componentClassName"))
+ .setComponentPackageName(service.get("componentPackageName"))
+ .build();
+ }
+}
diff --git a/sdksandbox/tests/testutils/src/com/android/server/sdksandbox/testutils/FakeSdkSandboxProvider.java b/sdksandbox/tests/testutils/src/com/android/server/sdksandbox/testutils/FakeSdkSandboxProvider.java
index f1cb19197..6510ec2a7 100644
--- a/sdksandbox/tests/testutils/src/com/android/server/sdksandbox/testutils/FakeSdkSandboxProvider.java
+++ b/sdksandbox/tests/testutils/src/com/android/server/sdksandbox/testutils/FakeSdkSandboxProvider.java
@@ -38,6 +38,8 @@ public class FakeSdkSandboxProvider implements SdkSandboxServiceProvider {
private final ArrayMap<CallingInfo, ISdkSandboxService> mService = new ArrayMap<>();
private static final String TEST_PACKAGE = "com.android.server.sdksandbox.tests";
+ public static final String FAKE_DUMP_OUTPUT = "FakeDump";
+
// When set to true, this will fail the bindService call
private boolean mFailBinding = false;
@@ -127,7 +129,7 @@ public class FakeSdkSandboxProvider implements SdkSandboxServiceProvider {
@Override
public void dump(PrintWriter writer) {
- writer.println("FakeDump");
+ writer.println(FAKE_DUMP_OUTPUT);
}
@NonNull
diff --git a/sdksandbox/tests/unittest/Android.bp b/sdksandbox/tests/unittest/Android.bp
index 6344c438d..fe65d38d3 100644
--- a/sdksandbox/tests/unittest/Android.bp
+++ b/sdksandbox/tests/unittest/Android.bp
@@ -29,6 +29,7 @@ java_defaults {
"compatibility-device-util-axt-minus-dexmaker",
"mockito-target-extended-minus-junit4",
"truth",
+ "adservices-test-utility",
"SdkSandboxTestUtils",
"SdkSandbox-java-lib",
],
diff --git a/sdksandbox/tests/unittest/src/com/android/sdksandbox/SdkSandboxTest.java b/sdksandbox/tests/unittest/src/com/android/sdksandbox/SdkSandboxTest.java
index bbd0f6501..18e817bbe 100644
--- a/sdksandbox/tests/unittest/src/com/android/sdksandbox/SdkSandboxTest.java
+++ b/sdksandbox/tests/unittest/src/com/android/sdksandbox/SdkSandboxTest.java
@@ -174,12 +174,20 @@ public class SdkSandboxTest {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
mContext = Mockito.spy(context);
+ mApplicationInfo = mContext.getPackageManager().getApplicationInfo(SDK_PACKAGE, 0);
+ mLoader = getClassLoader(mApplicationInfo);
+ if (sCustomizedSdkContextEnabled) {
+ Mockito.doReturn(mContext)
+ .when(mContext)
+ .createContextForSdkInSandbox(Mockito.any(), Mockito.anyInt());
+ Mockito.doReturn(mLoader).when(mContext).getClassLoader();
+ }
+
mSpyPackageManager = Mockito.spy(mContext.getPackageManager());
- mInjector = Mockito.spy(new InjectorForTest(mContext));
Mockito.doReturn(mSpyPackageManager).when(mContext).getPackageManager();
+
+ mInjector = Mockito.spy(new InjectorForTest(mContext));
mService = new SdkSandboxServiceImpl(mInjector);
- mApplicationInfo = mContext.getPackageManager().getApplicationInfo(SDK_PACKAGE, 0);
- mLoader = getClassLoader(mApplicationInfo);
}
@After
diff --git a/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxManagerServiceUnitTest.java b/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxManagerServiceUnitTest.java
index c89bf03a7..e9f80f3dd 100644
--- a/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxManagerServiceUnitTest.java
+++ b/sdksandbox/tests/unittest/src/com/android/server/sdksandbox/SdkSandboxManagerServiceUnitTest.java
@@ -22,6 +22,7 @@ import static android.app.sdksandbox.ISharedPreferencesSyncCallback.PREFERENCES_
import static android.app.sdksandbox.SdkSandboxManager.ACTION_START_SANDBOXED_ACTIVITY;
import static android.app.sdksandbox.SdkSandboxManager.LOAD_SDK_INTERNAL_ERROR;
+import static com.android.server.sdksandbox.testutils.FakeSdkSandboxProvider.FAKE_DUMP_OUTPUT;
import static com.android.server.wm.ActivityInterceptorCallback.MAINLINE_SDK_SANDBOX_ORDER_ID;
import static com.google.common.truth.Truth.assertThat;
@@ -30,6 +31,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import android.Manifest;
@@ -74,6 +76,7 @@ import android.util.Log;
import androidx.annotation.Nullable;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.adservices.shared.testing.common.DumpHelper;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.modules.utils.build.SdkLevel;
@@ -271,7 +274,9 @@ public class SdkSandboxManagerServiceUnitTest {
if (sSdkSandboxSettingsListener != null) {
sSdkSandboxSettingsListener.unregisterPropertiesListener();
}
- mStaticMockSession.finishMocking();
+ if (mStaticMockSession != null) {
+ mStaticMockSession.finishMocking();
+ }
}
/** Mock the ActivityManager::killUid to avoid SecurityException thrown in test. **/
@@ -2169,26 +2174,9 @@ public class SdkSandboxManagerServiceUnitTest {
mockGrantedPermission(DUMP);
mService.registerAdServicesManagerService(mAdServicesManager, /* published= */ false);
- String dump;
- try (StringWriter stringWriter = new StringWriter()) {
- // Mock call to mAdServicesManager.dump();
- FileDescriptor fd = new FileDescriptor();
- PrintWriter writer = new PrintWriter(stringWriter);
- String[] args = new String[0];
- Mockito.doAnswer(
- (inv) -> {
- writer.println("FakeAdServiceDump");
- return null;
- })
- .when(mAdServicesManager)
- .dump(fd, args);
-
- mService.dump(fd, writer, args);
-
- dump = stringWriter.toString();
- }
+ String dump = mockAdServicesDumpAndDump("FakeAdServiceDump");
- assertThat(dump).contains("FakeDump");
+ assertThat(dump).contains(FAKE_DUMP_OUTPUT);
assertThat(dump).contains("FakeAdServiceDump");
}
@@ -2198,15 +2186,9 @@ public class SdkSandboxManagerServiceUnitTest {
mockGrantedPermission(DUMP);
mService.registerAdServicesManagerService(mAdServicesManager, /* published= */ true);
- String dump;
- try (StringWriter stringWriter = new StringWriter()) {
- mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
-
- dump = stringWriter.toString();
- }
-
- assertThat(dump).contains("FakeDump");
+ String dump = dump();
+ assertThat(dump).contains(FAKE_DUMP_OUTPUT);
Mockito.verify(mAdServicesManager, Mockito.never())
.dump(ArgumentMatchers.any(), ArgumentMatchers.any());
}
@@ -2217,16 +2199,10 @@ public class SdkSandboxManagerServiceUnitTest {
mockGrantedPermission(DUMP);
mService.registerAdServicesManagerService(mAdServicesManager, /* published= */ false);
- String dump;
- try (StringWriter stringWriter = new StringWriter()) {
- mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
- dump = stringWriter.toString();
- }
-
- assertThat(dump).contains("FakeDump");
+ String dump = mockAdServicesDumpAndDump("FakeAdServiceDump");
- Mockito.verify(mAdServicesManager, Mockito.never())
- .dump(ArgumentMatchers.any(), ArgumentMatchers.any());
+ assertThat(dump).contains(FAKE_DUMP_OUTPUT);
+ assertThat(dump).contains("FakeAdServiceDump");
}
@Test
@@ -2235,14 +2211,9 @@ public class SdkSandboxManagerServiceUnitTest {
mockGrantedPermission(DUMP);
mService.registerAdServicesManagerService(mAdServicesManager, /* published= */ true);
- String dump;
- try (StringWriter stringWriter = new StringWriter()) {
- mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
- dump = stringWriter.toString();
- }
-
- assertThat(dump).contains("FakeDump");
+ String dump = dump();
+ assertThat(dump).contains(FAKE_DUMP_OUTPUT);
Mockito.verify(mAdServicesManager, Mockito.never())
.dump(ArgumentMatchers.any(), ArgumentMatchers.any());
}
@@ -2253,24 +2224,7 @@ public class SdkSandboxManagerServiceUnitTest {
mockGrantedPermission(DUMP);
mService.registerAdServicesManagerService(mAdServicesManager, /* published= */ false);
- String dump;
- try (StringWriter stringWriter = new StringWriter()) {
- // Mock call to mAdServicesManager.dump();
- FileDescriptor fd = new FileDescriptor();
- PrintWriter writer = new PrintWriter(stringWriter);
- String[] args = new String[] {"--AdServices"};
- Mockito.doAnswer(
- (inv) -> {
- writer.println("FakeAdServiceDump");
- return null;
- })
- .when(mAdServicesManager)
- .dump(fd, args);
-
- mService.dump(fd, writer, args);
-
- dump = stringWriter.toString();
- }
+ String dump = mockAdServicesDumpAndDump("FakeAdServiceDump", "--AdServices");
assertThat(dump).isEqualTo("AdServices:\n\nFakeAdServiceDump\n\n");
}
@@ -2281,14 +2235,7 @@ public class SdkSandboxManagerServiceUnitTest {
mockGrantedPermission(DUMP);
mService.registerAdServicesManagerService(mAdServicesManager, /* published= */ true);
- String dump;
- try (StringWriter stringWriter = new StringWriter()) {
- mService.dump(
- new FileDescriptor(),
- new PrintWriter(stringWriter),
- new String[] {"--AdServices"});
- dump = stringWriter.toString();
- }
+ String dump = dump("--AdServices");
assertThat(dump)
.isEqualTo(
@@ -2305,22 +2252,9 @@ public class SdkSandboxManagerServiceUnitTest {
mockGrantedPermission(DUMP);
mService.registerAdServicesManagerService(mAdServicesManager, /* published= */ false);
- String dump;
- try (StringWriter stringWriter = new StringWriter()) {
- mService.dump(
- new FileDescriptor(),
- new PrintWriter(stringWriter),
- new String[] {"--AdServices"});
- dump = stringWriter.toString();
- }
-
- assertThat(dump)
- .isEqualTo(
- SdkSandboxManagerService.DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_SYSTEM_SERVICE
- + "\n");
+ String dump = mockAdServicesDumpAndDump("FakeAdServiceDump", "--AdServices");
- Mockito.verify(mAdServicesManager, Mockito.never())
- .dump(ArgumentMatchers.any(), ArgumentMatchers.any());
+ assertThat(dump).isEqualTo("AdServices:\n\nFakeAdServiceDump\n\n");
}
@Test
@@ -2329,23 +2263,13 @@ public class SdkSandboxManagerServiceUnitTest {
mockGrantedPermission(DUMP);
mService.registerAdServicesManagerService(mAdServicesManager, /* published= */ true);
- String dump;
- try (StringWriter stringWriter = new StringWriter()) {
- mService.dump(
- new FileDescriptor(),
- new PrintWriter(stringWriter),
- new String[] {"--AdServices"});
- dump = stringWriter.toString();
- }
+ String dump = mockAdServicesDumpAndDump("FakeAdServiceDump", "--AdServices");
assertThat(dump)
.isEqualTo(
SdkSandboxManagerService
.DUMP_AD_SERVICES_MESSAGE_HANDLED_BY_AD_SERVICES_ITSELF
+ "\n");
-
- Mockito.verify(mAdServicesManager, Mockito.never())
- .dump(ArgumentMatchers.any(), ArgumentMatchers.any());
}
@Test(expected = SecurityException.class)
@@ -2433,7 +2357,6 @@ public class SdkSandboxManagerServiceUnitTest {
disableForegroundCheck();
sSdkSandboxSettingsListener.setKillSwitchState(true);
- setDeviceConfigProperty(PROPERTY_DISABLE_SANDBOX, "true");
FakeLoadSdkCallbackBinder callback = new FakeLoadSdkCallbackBinder();
mService.loadSdk(
TEST_PACKAGE,
@@ -2815,6 +2738,34 @@ public class SdkSandboxManagerServiceUnitTest {
}
}
+ private String dump(String... args) throws Exception {
+ Log.d(TAG, "dump(): args=" + Arrays.toString(args));
+ return DumpHelper.dump(pw -> mService.dump(new FileDescriptor(), pw, args));
+ }
+
+ private String mockAdServicesDumpAndDump(String adServicesDump, String... args)
+ throws Exception {
+ Log.d(
+ TAG,
+ "mockAdServicesDumpAndDump(): adServicesDump="
+ + adServicesDump
+ + ", args="
+ + Arrays.toString(args));
+ return DumpHelper.dump(
+ pw -> {
+ Mockito.doAnswer(
+ inv -> {
+ Log.d(TAG, inv.toString());
+ pw.println(adServicesDump);
+ return null;
+ })
+ .when(mAdServicesManager)
+ .dump(any(), eq(args));
+
+ mService.dump(new FileDescriptor(), pw, args);
+ });
+ }
+
private static Bundle getTestBundle() {
final Bundle data = new Bundle();
data.putString(TEST_KEY, TEST_VALUE);
diff --git a/shared/device-side/libraries/Android.bp b/shared/device-side/libraries/Android.bp
index d243b1531..4880a29ec 100644
--- a/shared/device-side/libraries/Android.bp
+++ b/shared/device-side/libraries/Android.bp
@@ -70,7 +70,7 @@ java_library {
// NOTE: currently there's just one library for everything (which for
// now is just ApplicationContext), but it might be better to split
-// into multiple libraries in the feature (if it gets bigger and/or
+// into multiple libraries in the future (if it gets bigger and/or
// if new classes adds external dependencies)
java_library {
name: "adservices-shared-common",
@@ -79,6 +79,9 @@ java_library {
srcs: [
"java/com/android/adservices/shared/common/*.java",
],
+ static_libs: [
+ "modules-utils-preconditions",
+ ],
libs: [
"framework-annotations-lib",
"jsr305", // for @ThreadSafe",
@@ -106,3 +109,23 @@ java_library {
],
apex_available: ["com.android.adservices", "com.android.extservices", "com.android.ondevicepersonalization"],
}
+
+// NOTE: this util library only have one Preconditions class now. If we add more classes, we should
+// consider splitting this into a specific preconditions library. (if it gets bigger and/or if new
+// classes adds external dependencies)
+java_library {
+ name: "adservices-shared-util",
+ min_sdk_version: "30",
+ sdk_version: "module_current",
+ srcs: [
+ "java/com/android/adservices/shared/util/*.java",
+ ],
+ libs: [
+ "framework-annotations-lib",
+ ],
+ static_libs: [
+ "modules-utils-build",
+ "error_prone_annotations", // For @FormatMethod
+ ],
+ apex_available: ["com.android.adservices", "com.android.extservices", "com.android.ondevicepersonalization"],
+} \ No newline at end of file
diff --git a/shared/device-side/libraries/java/com/android/adservices/shared/common/ApplicationContextSingleton.java b/shared/device-side/libraries/java/com/android/adservices/shared/common/ApplicationContextSingleton.java
index 77e20507b..c8066570b 100644
--- a/shared/device-side/libraries/java/com/android/adservices/shared/common/ApplicationContextSingleton.java
+++ b/shared/device-side/libraries/java/com/android/adservices/shared/common/ApplicationContextSingleton.java
@@ -19,6 +19,7 @@ import android.content.Context;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
@@ -49,11 +50,7 @@ public final class ApplicationContextSingleton {
*/
public static Context get() {
Context context = sContext.get();
- // TODO(b/303886367): use Preconditions.checkState()
- if (context == null) {
- // TODO(b/309169907): log to CEL
- throw new IllegalStateException(ERROR_MESSAGE_SET_NOT_CALLED);
- }
+ Preconditions.checkState(context != null, ERROR_MESSAGE_SET_NOT_CALLED);
return context;
}
@@ -68,11 +65,9 @@ public final class ApplicationContextSingleton {
public static void set(Context context) {
Context appContext =
Objects.requireNonNull(context, "context cannot be null").getApplicationContext();
- // TODO(b/303886367): use Preconditions.checkIllegalArgument()
- if (appContext == null) {
- throw new IllegalArgumentException(
- "Context (" + context + ") does not have an application context");
- }
+
+ Preconditions.checkArgument(
+ appContext != null, "Context (%s) does not have an application context", context);
// Set if it's not set yet
if (sContext.compareAndSet(null, appContext)) {
diff --git a/shared/device-side/libraries/java/com/android/adservices/shared/testing/common/DumpHelper.java b/shared/device-side/libraries/java/com/android/adservices/shared/testing/common/DumpHelper.java
index da3466c6c..cde3e3fd9 100644
--- a/shared/device-side/libraries/java/com/android/adservices/shared/testing/common/DumpHelper.java
+++ b/shared/device-side/libraries/java/com/android/adservices/shared/testing/common/DumpHelper.java
@@ -19,7 +19,6 @@ import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.fail;
-import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -30,7 +29,7 @@ import java.util.Objects;
public final class DumpHelper {
/** Calls {@code dump()} in the given dumper, and return its output. */
- public static String dump(Dumper dumper) throws IOException {
+ public static String dump(Dumper dumper) throws Exception {
Objects.requireNonNull(dumper);
try (StringWriter sw = new StringWriter()) {
PrintWriter pw = new PrintWriter(sw);
@@ -67,7 +66,7 @@ public final class DumpHelper {
/** Helper to dump an object. */
public interface Dumper {
/** Ah, might as well dump (dump!) */
- void dump(PrintWriter printWriter);
+ void dump(PrintWriter printWriter) throws Exception;
}
private DumpHelper() {
diff --git a/shared/device-side/libraries/java/com/android/adservices/shared/util/Preconditions.java b/shared/device-side/libraries/java/com/android/adservices/shared/util/Preconditions.java
new file mode 100644
index 000000000..31e302565
--- /dev/null
+++ b/shared/device-side/libraries/java/com/android/adservices/shared/util/Preconditions.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 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.shared.util;
+
+import com.google.errorprone.annotations.FormatMethod;
+import com.google.errorprone.annotations.FormatString;
+
+/**
+ * Simple static methods to be called at the start of your own methods to verify correct arguments
+ * and state.
+ *
+ * <p>Note: This class contains method(s) added after S+ in modules-utils-preconditions library. Use
+ * this class only when accessing Preconditions methods not available in R. For example, {@link
+ * #checkState(boolean, String, Object...)}.
+ */
+public final class Preconditions {
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance, but not
+ * involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @param messageTemplate a printf-style message template to use if the check fails; will be
+ * converted to a string using {@link String#format(String, Object...)}
+ * @param messageArgs arguments for {@code messageTemplate}
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ @FormatMethod
+ public static void checkState(
+ boolean expression, @FormatString String messageTemplate, Object... messageArgs) {
+ if (!expression) {
+ throw new IllegalStateException(String.format(messageTemplate, messageArgs));
+ }
+ }
+}
diff --git a/shared/device-side/tests/Android.bp b/shared/device-side/tests/Android.bp
index 5fb9a0ae3..0d6b83780 100644
--- a/shared/device-side/tests/Android.bp
+++ b/shared/device-side/tests/Android.bp
@@ -27,6 +27,7 @@ android_test {
"adservices-shared-error-logging",
"adservices-shared-storage",
"adservices-shared-testing",
+ "adservices-shared-util",
"androidx.test.core",
"androidx.test.runner",
"auto_value_annotations",
diff --git a/shared/device-side/tests/java/com/android/adservices/shared/storage/BooleanFileDatastoreTest.java b/shared/device-side/tests/java/com/android/adservices/shared/storage/BooleanFileDatastoreTest.java
index b771355f0..f9c4c993a 100644
--- a/shared/device-side/tests/java/com/android/adservices/shared/storage/BooleanFileDatastoreTest.java
+++ b/shared/device-side/tests/java/com/android/adservices/shared/storage/BooleanFileDatastoreTest.java
@@ -236,7 +236,6 @@ public final class BooleanFileDatastoreTest {
assertWithMessage("get(%s)", TEST_KEY).that(readValue).isNotNull();
assertWithMessage("get(%s)", TEST_KEY).that(readValue).isEqualTo(insertedValue);
- Set<String> keys = mDatastore.keySet();
assertWithMessage("keys").that(mDatastore.keySet()).containsExactly(TEST_KEY);
// Delete
diff --git a/shared/device-side/tests/java/com/android/adservices/shared/util/PreconditionsTest.java b/shared/device-side/tests/java/com/android/adservices/shared/util/PreconditionsTest.java
new file mode 100644
index 000000000..f4ef110af
--- /dev/null
+++ b/shared/device-side/tests/java/com/android/adservices/shared/util/PreconditionsTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 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.shared.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import org.junit.Test;
+
+public final class PreconditionsTest {
+ private static final String MESSAGE = "A test message";
+ private static final String MESSAGE_TEMPLATE = "Expect a message: %s";
+
+ @Test
+ public void testCheckState_success() {
+ Preconditions.checkState(true, MESSAGE_TEMPLATE, MESSAGE);
+ }
+
+ @Test
+ public void testCheckState_failure() {
+ Exception e =
+ assertThrows(
+ IllegalStateException.class,
+ () -> Preconditions.checkState(false, MESSAGE));
+ assertThat(e).hasMessageThat().isEqualTo(MESSAGE);
+ }
+
+ @Test
+ public void testCheckState_formattedMessage_success() {
+ Preconditions.checkState(true, MESSAGE_TEMPLATE, MESSAGE);
+ }
+
+ @Test
+ public void testCheckState_formattedMessage_failure() {
+ Exception e =
+ assertThrows(
+ IllegalStateException.class,
+ () -> Preconditions.checkState(false, MESSAGE_TEMPLATE, MESSAGE));
+ assertThat(e).hasMessageThat().isEqualTo(String.format(MESSAGE_TEMPLATE, MESSAGE));
+ }
+}