1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.adservices.service.common; 18 19 import static android.adservices.adselection.CustomAudienceBiddingInfoFixture.DATA_VERSION_1; 20 import static android.adservices.adselection.CustomAudienceBiddingInfoFixture.DATA_VERSION_2; 21 import static android.adservices.customaudience.CustomAudienceFixture.VALID_OWNER; 22 23 import static com.android.adservices.data.adselection.AdSelectionDatabase.DATABASE_NAME; 24 import static com.android.adservices.service.adselection.AdSelectionScriptEngine.NUM_BITS_STOCHASTIC_ROUNDING; 25 import static com.android.adservices.service.adselection.DataVersionFetcher.DATA_VERSION_HEADER_BIDDING_KEY; 26 import static com.android.adservices.service.adselection.DataVersionFetcher.DATA_VERSION_HEADER_SCORING_KEY; 27 import static com.android.adservices.service.adselection.ImpressionReporterLegacy.CALLER_PACKAGE_NAME_MISMATCH; 28 import static com.android.adservices.service.customaudience.FetchCustomAudienceImplTest.FetchCustomAudienceTestCallback; 29 import static com.android.adservices.service.stats.AdSelectionExecutionLoggerTest.DB_AD_SELECTION_FILE_SIZE; 30 import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION; 31 import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_API_CALLED__API_NAME__REPORT_INTERACTION; 32 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; 33 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean; 34 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; 35 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 36 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow; 37 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; 38 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; 39 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; 40 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 41 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; 42 43 import static com.google.common.truth.Truth.assertThat; 44 import static com.google.common.truth.Truth.assertWithMessage; 45 46 import static org.junit.Assert.assertEquals; 47 import static org.junit.Assert.assertFalse; 48 import static org.junit.Assert.assertNotNull; 49 import static org.junit.Assert.assertNull; 50 import static org.junit.Assert.assertTrue; 51 import static org.mockito.ArgumentMatchers.anyInt; 52 import static org.mockito.ArgumentMatchers.anyString; 53 import static org.mockito.Mockito.never; 54 import static org.mockito.Mockito.spy; 55 56 import android.adservices.adid.AdId; 57 import android.adservices.adselection.AdSelectionCallback; 58 import android.adservices.adselection.AdSelectionConfig; 59 import android.adservices.adselection.AdSelectionConfigFixture; 60 import android.adservices.adselection.AdSelectionInput; 61 import android.adservices.adselection.AdSelectionOverrideCallback; 62 import android.adservices.adselection.AdSelectionResponse; 63 import android.adservices.adselection.DecisionLogic; 64 import android.adservices.adselection.PerBuyerDecisionLogic; 65 import android.adservices.adselection.ReportEventRequest; 66 import android.adservices.adselection.ReportImpressionCallback; 67 import android.adservices.adselection.ReportImpressionInput; 68 import android.adservices.adselection.ReportInteractionCallback; 69 import android.adservices.adselection.ReportInteractionInput; 70 import android.adservices.adselection.SetAppInstallAdvertisersCallback; 71 import android.adservices.adselection.SetAppInstallAdvertisersInput; 72 import android.adservices.adselection.SignedContextualAds; 73 import android.adservices.adselection.SignedContextualAdsFixture; 74 import android.adservices.adselection.UpdateAdCounterHistogramInput; 75 import android.adservices.common.AdData; 76 import android.adservices.common.AdDataFixture; 77 import android.adservices.common.AdFilters; 78 import android.adservices.common.AdSelectionSignals; 79 import android.adservices.common.AdServicesStatusUtils; 80 import android.adservices.common.AdTechIdentifier; 81 import android.adservices.common.AppInstallFilters; 82 import android.adservices.common.CallerMetadata; 83 import android.adservices.common.CallingAppUidSupplierProcessImpl; 84 import android.adservices.common.CommonFixture; 85 import android.adservices.common.FledgeErrorResponse; 86 import android.adservices.common.FrequencyCapFilters; 87 import android.adservices.common.KeyedFrequencyCap; 88 import android.adservices.common.KeyedFrequencyCapFixture; 89 import android.adservices.customaudience.CustomAudience; 90 import android.adservices.customaudience.CustomAudienceFixture; 91 import android.adservices.customaudience.CustomAudienceOverrideCallback; 92 import android.adservices.customaudience.FetchAndJoinCustomAudienceInput; 93 import android.adservices.customaudience.ICustomAudienceCallback; 94 import android.adservices.customaudience.TrustedBiddingData; 95 import android.adservices.customaudience.TrustedBiddingDataFixture; 96 import android.adservices.http.MockWebServerRule; 97 import android.content.Context; 98 import android.content.pm.PackageManager; 99 import android.net.Uri; 100 import android.os.IBinder; 101 import android.os.Process; 102 import android.os.RemoteException; 103 104 import androidx.room.Room; 105 import androidx.test.core.app.ApplicationProvider; 106 import androidx.test.filters.FlakyTest; 107 108 import com.android.adservices.MockWebServerRuleFactory; 109 import com.android.adservices.common.AdServicesExtendedMockitoTestCase; 110 import com.android.adservices.common.WebViewSupportUtil; 111 import com.android.adservices.concurrency.AdServicesExecutors; 112 import com.android.adservices.data.adselection.AdSelectionDatabase; 113 import com.android.adservices.data.adselection.AdSelectionDebugReportDao; 114 import com.android.adservices.data.adselection.AdSelectionDebugReportingDatabase; 115 import com.android.adservices.data.adselection.AdSelectionEntryDao; 116 import com.android.adservices.data.adselection.AdSelectionServerDatabase; 117 import com.android.adservices.data.adselection.AppInstallDao; 118 import com.android.adservices.data.adselection.ConsentedDebugConfigurationDao; 119 import com.android.adservices.data.adselection.DBAdSelectionDebugReport; 120 import com.android.adservices.data.adselection.FrequencyCapDao; 121 import com.android.adservices.data.adselection.SharedStorageDatabase; 122 import com.android.adservices.data.common.DBAdData; 123 import com.android.adservices.data.customaudience.AdDataConversionStrategy; 124 import com.android.adservices.data.customaudience.AdDataConversionStrategyFactory; 125 import com.android.adservices.data.customaudience.CustomAudienceDao; 126 import com.android.adservices.data.customaudience.CustomAudienceDatabase; 127 import com.android.adservices.data.customaudience.DBCustomAudience; 128 import com.android.adservices.data.customaudience.DBTrustedBiddingData; 129 import com.android.adservices.data.encryptionkey.EncryptionKeyDao; 130 import com.android.adservices.data.enrollment.EnrollmentDao; 131 import com.android.adservices.data.signals.EncodedPayloadDao; 132 import com.android.adservices.data.signals.ProtectedSignalsDatabase; 133 import com.android.adservices.service.Flags; 134 import com.android.adservices.service.FlagsFactory; 135 import com.android.adservices.service.adid.AdIdCacheManager; 136 import com.android.adservices.service.adselection.AdCost; 137 import com.android.adservices.service.adselection.AdFilteringFeatureFactory; 138 import com.android.adservices.service.adselection.AdIdFetcher; 139 import com.android.adservices.service.adselection.AdSelectionServiceImpl; 140 import com.android.adservices.service.adselection.DebugReportSenderJobService; 141 import com.android.adservices.service.adselection.EventReporter; 142 import com.android.adservices.service.adselection.JsVersionHelper; 143 import com.android.adservices.service.adselection.JsVersionRegister; 144 import com.android.adservices.service.adselection.MockAdIdWorker; 145 import com.android.adservices.service.adselection.MultiCloudSupportStrategy; 146 import com.android.adservices.service.adselection.MultiCloudTestStrategyFactory; 147 import com.android.adservices.service.adselection.UpdateAdCounterHistogramWorkerTest; 148 import com.android.adservices.service.adselection.debug.ConsentedDebugConfigurationGeneratorFactory; 149 import com.android.adservices.service.adselection.encryption.ObliviousHttpEncryptor; 150 import com.android.adservices.service.common.cache.CacheProviderFactory; 151 import com.android.adservices.service.common.httpclient.AdServicesHttpsClient; 152 import com.android.adservices.service.consent.AdServicesApiConsent; 153 import com.android.adservices.service.consent.AdServicesApiType; 154 import com.android.adservices.service.consent.ConsentManager; 155 import com.android.adservices.service.customaudience.BackgroundFetchJob; 156 import com.android.adservices.service.customaudience.CustomAudienceBlobFixture; 157 import com.android.adservices.service.customaudience.CustomAudienceImpl; 158 import com.android.adservices.service.customaudience.CustomAudienceQuantityChecker; 159 import com.android.adservices.service.customaudience.CustomAudienceServiceImpl; 160 import com.android.adservices.service.customaudience.CustomAudienceValidator; 161 import com.android.adservices.service.devapi.DevContext; 162 import com.android.adservices.service.devapi.DevContextFilter; 163 import com.android.adservices.service.exception.FilterException; 164 import com.android.adservices.service.kanon.KAnonSignJoinFactory; 165 import com.android.adservices.service.signals.EgressConfigurationGenerator; 166 import com.android.adservices.service.stats.AdServicesLogger; 167 import com.android.adservices.shared.testing.SupportedByConditionRule; 168 import com.android.modules.utils.testing.ExtendedMockitoRule.MockStatic; 169 import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic; 170 171 import com.google.common.collect.ImmutableList; 172 import com.google.common.collect.ImmutableMap; 173 import com.google.common.collect.ImmutableSet; 174 import com.google.common.util.concurrent.MoreExecutors; 175 import com.google.mockwebserver.MockResponse; 176 import com.google.mockwebserver.MockWebServer; 177 178 import org.junit.Before; 179 import org.junit.Rule; 180 import org.junit.Test; 181 import org.mockito.Mock; 182 183 import java.io.File; 184 import java.time.Duration; 185 import java.util.ArrayList; 186 import java.util.Arrays; 187 import java.util.Collections; 188 import java.util.HashMap; 189 import java.util.HashSet; 190 import java.util.List; 191 import java.util.Map; 192 import java.util.Objects; 193 import java.util.Optional; 194 import java.util.Set; 195 import java.util.concurrent.CountDownLatch; 196 import java.util.concurrent.ExecutorService; 197 import java.util.concurrent.ScheduledThreadPoolExecutor; 198 import java.util.concurrent.Semaphore; 199 import java.util.concurrent.TimeUnit; 200 import java.util.stream.Collectors; 201 202 @SpyStatic(FlagsFactory.class) 203 @MockStatic(BackgroundJobsManager.class) 204 @MockStatic(ConsentManager.class) 205 @MockStatic(AppImportanceFilter.class) 206 @MockStatic(DebugReportSenderJobService.class) 207 @MockStatic(BackgroundFetchJob.class) 208 public final class FledgeE2ETest extends AdServicesExtendedMockitoTestCase { 209 public static final String CUSTOM_AUDIENCE_SEQ_1 = "/ca1"; 210 public static final String CUSTOM_AUDIENCE_SEQ_2 = "/ca2"; 211 private static final String FETCH_CA_PATH = "/fetch"; 212 public static final AppInstallFilters CURRENT_APP_FILTER = 213 new AppInstallFilters.Builder() 214 .setPackageNames(new HashSet<>(Arrays.asList(CommonFixture.TEST_PACKAGE_NAME))) 215 .build(); 216 public static final FrequencyCapFilters CLICK_ONCE_PER_DAY_KEY1 = 217 new FrequencyCapFilters.Builder() 218 .setKeyedFrequencyCapsForClickEvents( 219 ImmutableList.of( 220 new KeyedFrequencyCap.Builder( 221 KeyedFrequencyCapFixture.KEY1, 222 1, 223 Duration.ofDays(1)) 224 .build())) 225 .build(); 226 public static final FrequencyCapFilters WIN_ONCE_PER_DAY_KEY1 = 227 new FrequencyCapFilters.Builder() 228 .setKeyedFrequencyCapsForWinEvents( 229 ImmutableList.of( 230 new KeyedFrequencyCap.Builder( 231 KeyedFrequencyCapFixture.KEY1, 232 1, 233 Duration.ofDays(1)) 234 .build())) 235 .build(); 236 private static final AdTechIdentifier LOCALHOST_BUYER = 237 AdTechIdentifier.fromString("localhost"); 238 private static final Uri BUYER_DOMAIN_1 = 239 CommonFixture.getUri(AdSelectionConfigFixture.BUYER_1, ""); 240 private static final Uri BUYER_DOMAIN_2 = 241 CommonFixture.getUri(AdSelectionConfigFixture.BUYER_2, ""); 242 private static final String AD_URI_PREFIX = "/adverts/123"; 243 private static final String BUYER_BIDDING_LOGIC_URI_PATH = "/buyer/bidding/logic"; 244 private static final String BUYER_TRUSTED_SIGNAL_URI_PATH = "/kv/buyer/signals"; 245 private static final String BUYER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION = 246 "/kv/buyer/data/version/signals/"; 247 private static final String SELLER_DECISION_LOGIC_URI_PATH = "/ssp/decision/logic/"; 248 private static final String SELLER_TRUSTED_SIGNAL_URI_PATH = "/kv/seller/signals/"; 249 private static final String SELLER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION = 250 "/kv/seller/data/version/signals/"; 251 private static final String SELLER_TRUSTED_SIGNAL_PARAMS = "?renderuris="; 252 private static final String SELLER_REPORTING_PATH = "/reporting/seller"; 253 private static final String SELLER_DEBUG_REPORT_WIN_PATH = "/seller/reportWin"; 254 private static final String SELLER_DEBUG_REPORT_LOSS_PATH = "/seller/reportLoss"; 255 private static final String DEBUG_REPORT_WINNING_BID_PARAM = "?wb=${winningBid}"; 256 private static final String DEBUG_REPORT_WINNING_BID_RESPONSE = "?wb=10.0"; 257 private static final String BUYER_REPORTING_PATH = "/reporting/buyer"; 258 private static final String BUYER_DEBUG_REPORT_WIN_PATH = "/buyer/reportWin"; 259 private static final String BUYER_DEBUG_REPORT_LOSS_PATH = "/buyer/reportLoss"; 260 private static final AdSelectionSignals TRUSTED_BIDDING_SIGNALS = 261 AdSelectionSignals.fromString( 262 "{\n" 263 + "\t\"example\": \"example\",\n" 264 + "\t\"valid\": \"Also valid\",\n" 265 + "\t\"list\": \"list\",\n" 266 + "\t\"of\": \"of\",\n" 267 + "\t\"keys\": \"trusted bidding signal Values\"\n" 268 + "}"); 269 private static final AdSelectionSignals TRUSTED_SCORING_SIGNALS = 270 AdSelectionSignals.fromString( 271 "{\n" 272 + "\t\"render_uri_1\": \"signals_for_1\",\n" 273 + "\t\"render_uri_2\": \"signals_for_2\"\n" 274 + "}"); 275 private static final PerBuyerDecisionLogic BUYERS_DECISION_LOGIC = 276 new PerBuyerDecisionLogic( 277 ImmutableMap.of( 278 CommonFixture.VALID_BUYER_1, new DecisionLogic("reportWin()"), 279 CommonFixture.VALID_BUYER_2, new DecisionLogic("reportWin()"))); 280 281 // Interaction reporting contestants 282 private static final String CLICK_INTERACTION = "click"; 283 284 private static final String CLICK_SELLER_PATH = "/click/seller"; 285 private static final String HOVER_SELLER_PATH = "/hover/seller"; 286 287 private static final String CLICK_BUYER_PATH = "/click/buyer"; 288 private static final String HOVER_BUYER_PATH = "/hover/buyer"; 289 290 private static final String INTERACTION_DATA = "{\"key\":\"value\"}"; 291 292 private static final int BUYER_DESTINATION = 293 ReportEventRequest.FLAG_REPORTING_DESTINATION_BUYER; 294 private static final int SELLER_DESTINATION = 295 ReportEventRequest.FLAG_REPORTING_DESTINATION_SELLER; 296 297 private static final long BINDER_ELAPSED_TIMESTAMP = 100L; 298 private static final List<Double> BIDS_FOR_BUYER_1 = ImmutableList.of(1.1, 2.2); 299 private static final List<Double> BIDS_FOR_BUYER_2 = ImmutableList.of(4.5, 6.7, 10.0); 300 // A list of empty ad counter keys to apply to ads for buyer when not doing fcap filtering. 301 private static final List<Set<Integer>> EMPTY_AD_COUNTER_KEYS_FOR_BUYER_2 = 302 Arrays.asList(new HashSet[BIDS_FOR_BUYER_2.size()]); 303 private static final List<Double> INVALID_BIDS = ImmutableList.of(0.0, -1.0, -2.0); 304 305 private static final AdCost AD_COST_1 = new AdCost(1.2, NUM_BITS_STOCHASTIC_ROUNDING); 306 private static final AdCost AD_COST_2 = new AdCost(2.2, NUM_BITS_STOCHASTIC_ROUNDING); 307 private static final boolean CONSOLE_MESSAGE_IN_LOGS_ENABLED = true; 308 @Mock private AdServicesLogger mAdServicesLoggerMock; 309 310 // Every test in this class requires that the JS Sandbox be available. The JS Sandbox 311 // availability depends on an external component (the system webview) being higher than a 312 // certain minimum version. 313 @Rule(order = 11) 314 public final SupportedByConditionRule webViewSupportsJSSandbox = 315 WebViewSupportUtil.createJSSandboxAvailableRule( 316 ApplicationProvider.getApplicationContext()); 317 318 @Rule(order = 12) 319 public final MockWebServerRule mockWebServerRule = MockWebServerRuleFactory.createForHttps(); 320 321 @Mock private ConsentManager mConsentManagerMock; 322 @Mock private FledgeConsentFilter mFledgeConsentFilterMock; 323 // This object access some system APIs 324 @Mock private DevContextFilter mDevContextFilterMock; 325 @Mock private FledgeApiThrottleFilter mFledgeApiThrottleFilterMock; 326 private AdSelectionConfig mAdSelectionConfig; 327 private AdServicesHttpsClient mAdServicesHttpsClient; 328 private CustomAudienceDao mCustomAudienceDao; 329 private EncodedPayloadDao mEncodedPayloadDao; 330 private AdSelectionEntryDao mAdSelectionEntryDao; 331 private AppInstallDao mAppInstallDao; 332 private FrequencyCapDao mFrequencyCapDao; 333 private EncryptionKeyDao mEncryptionKeyDao; 334 private EnrollmentDao mEnrollmentDao; 335 private ExecutorService mLightweightExecutorService; 336 private ExecutorService mBackgroundExecutorService; 337 private ScheduledThreadPoolExecutor mScheduledExecutor; 338 private CustomAudienceServiceImpl mCustomAudienceService; 339 private AdSelectionServiceImpl mAdSelectionService; 340 341 private static final Flags DEFAULT_FLAGS = 342 new FledgeE2ETestFlags( 343 false, true, true, true, true, false, false, false, false, false, false, false); 344 private MockWebServerRule.RequestMatcher<String> mRequestMatcherPrefixMatch; 345 private Uri mLocalhostBuyerDomain; 346 private AdFilteringFeatureFactory mAdFilteringFeatureFactory; 347 private FledgeAllowListsFilter mFledgeAllowListsFilterSpy; 348 @Mock private FledgeAuthorizationFilter mFledgeAuthorizationFilterMock; 349 @Mock private File mMockDBAdSelectionFile; 350 @Mock private AdSelectionServiceFilter mAdSelectionServiceFilterMock; 351 @Mock private AppImportanceFilter mAppImportanceFilterMock; 352 @Mock private ObliviousHttpEncryptor mObliviousHttpEncryptor; 353 private MultiCloudSupportStrategy mMultiCloudSupportStrategy = 354 MultiCloudTestStrategyFactory.getDisabledTestStrategy(mObliviousHttpEncryptor); 355 private AdSelectionDebugReportDao mAdSelectionDebugReportDao; 356 private MockAdIdWorker mMockAdIdWorker; 357 private AdIdFetcher mAdIdFetcher; 358 @Mock private KAnonSignJoinFactory mUnusedKAnonSignJoinFactory; 359 private RetryStrategyFactory mRetryStrategyFactory; 360 private ConsentedDebugConfigurationDao mConsentedDebugConfigurationDao; 361 private ConsentedDebugConfigurationGeneratorFactory 362 mConsentedDebugConfigurationGeneratorFactory; 363 private EgressConfigurationGenerator mEgressConfigurationGenerator; 364 365 @Before setUp()366 public void setUp() throws Exception { 367 mocker.mockGetFlags(DEFAULT_FLAGS); 368 369 mFledgeAllowListsFilterSpy = 370 spy(new FledgeAllowListsFilter(DEFAULT_FLAGS, mAdServicesLoggerMock)); 371 372 mCustomAudienceDao = 373 Room.inMemoryDatabaseBuilder(mSpyContext, CustomAudienceDatabase.class) 374 .addTypeConverter(new DBCustomAudience.Converters(true, true, true)) 375 .build() 376 .customAudienceDao(); 377 mEncodedPayloadDao = 378 Room.inMemoryDatabaseBuilder(mSpyContext, ProtectedSignalsDatabase.class) 379 .build() 380 .getEncodedPayloadDao(); 381 382 mAdSelectionEntryDao = 383 Room.inMemoryDatabaseBuilder(mSpyContext, AdSelectionDatabase.class) 384 .build() 385 .adSelectionEntryDao(); 386 SharedStorageDatabase sharedDb = 387 Room.inMemoryDatabaseBuilder(mSpyContext, SharedStorageDatabase.class).build(); 388 mAppInstallDao = sharedDb.appInstallDao(); 389 mFrequencyCapDao = sharedDb.frequencyCapDao(); 390 AdSelectionServerDatabase serverDb = 391 Room.inMemoryDatabaseBuilder(mSpyContext, AdSelectionServerDatabase.class).build(); 392 mEncryptionKeyDao = EncryptionKeyDao.getInstance(); 393 mEnrollmentDao = EnrollmentDao.getInstance(); 394 mAdFilteringFeatureFactory = 395 new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDao, DEFAULT_FLAGS); 396 397 mLightweightExecutorService = AdServicesExecutors.getLightWeightExecutor(); 398 mBackgroundExecutorService = AdServicesExecutors.getBackgroundExecutor(); 399 mScheduledExecutor = AdServicesExecutors.getScheduler(); 400 401 mAdServicesHttpsClient = 402 new AdServicesHttpsClient( 403 AdServicesExecutors.getBlockingExecutor(), 404 CacheProviderFactory.createNoOpCache()); 405 mAdSelectionDebugReportDao = 406 Room.inMemoryDatabaseBuilder(mSpyContext, AdSelectionDebugReportingDatabase.class) 407 .build() 408 .getAdSelectionDebugReportDao(); 409 mMockAdIdWorker = new MockAdIdWorker(new AdIdCacheManager(mSpyContext)); 410 mAdIdFetcher = 411 new AdIdFetcher( 412 mSpyContext, 413 mMockAdIdWorker, 414 mLightweightExecutorService, 415 mScheduledExecutor); 416 mRetryStrategyFactory = RetryStrategyFactory.createInstanceForTesting(); 417 mConsentedDebugConfigurationDao = 418 Room.inMemoryDatabaseBuilder(mSpyContext, AdSelectionDatabase.class) 419 .build() 420 .consentedDebugConfigurationDao(); 421 mConsentedDebugConfigurationGeneratorFactory = 422 new ConsentedDebugConfigurationGeneratorFactory( 423 false, mConsentedDebugConfigurationDao); 424 mEgressConfigurationGenerator = 425 EgressConfigurationGenerator.createInstance( 426 Flags.DEFAULT_FLEDGE_AUCTION_SERVER_ENABLE_PAS_UNLIMITED_EGRESS, 427 mAdIdFetcher, 428 Flags.DEFAULT_AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 429 mLightweightExecutorService); 430 431 initClients(false, true, false, false, false, false); 432 433 mRequestMatcherPrefixMatch = (a, b) -> !b.isEmpty() && a.startsWith(b); 434 435 mLocalhostBuyerDomain = Uri.parse(mockWebServerRule.getServerBaseAddress()); 436 when(mSpyContext.getDatabasePath(DATABASE_NAME)).thenReturn(mMockDBAdSelectionFile); 437 when(mMockDBAdSelectionFile.length()).thenReturn(DB_AD_SELECTION_FILE_SIZE); 438 doNothing() 439 .when(mAdSelectionServiceFilterMock) 440 .filterRequest( 441 any(), 442 anyString(), 443 anyBoolean(), 444 anyBoolean(), 445 anyInt(), 446 anyInt(), 447 any(), 448 any()); 449 when(ConsentManager.getInstance()).thenReturn(mConsentManagerMock); 450 when(AppImportanceFilter.create(any(), anyInt(), any())) 451 .thenReturn(mAppImportanceFilterMock); 452 doNothing() 453 .when(mAppImportanceFilterMock) 454 .assertCallerIsInForeground(anyInt(), anyInt(), any()); 455 mMockAdIdWorker.setResult(AdId.ZERO_OUT, true); 456 } 457 458 @Test testFledgeFlowSuccessWithDevOverridesRegisterAdBeaconDisabled()459 public void testFledgeFlowSuccessWithDevOverridesRegisterAdBeaconDisabled() throws Exception { 460 // Re init clients with registerAdBeacon false 461 initClients(false, false, false, false, false, false); 462 463 setupConsentGivenStubs(); 464 465 setupAdSelectionConfig(); 466 467 String decisionLogicJs = getDecisionLogicJs(); 468 String biddingLogicJs = getBiddingLogicJs(); 469 470 MockWebServer server = 471 mockWebServerRule.startMockWebServer( 472 request -> new MockResponse().setResponseCode(404)); 473 474 when(mDevContextFilterMock.createDevContext()) 475 .thenReturn( 476 DevContext.builder() 477 .setDevOptionsEnabled(true) 478 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 479 .build()); 480 481 CustomAudience customAudience1 = 482 createCustomAudience( 483 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 484 485 CustomAudience customAudience2 = 486 createCustomAudience( 487 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 488 489 joinCustomAudienceAndAssertSuccess(customAudience1); 490 joinCustomAudienceAndAssertSuccess(customAudience2); 491 492 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 493 494 setupOverridesAndAssertSuccess( 495 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 496 497 // Run Ad Selection 498 AdSelectionTestCallback resultsCallback = 499 invokeRunAdSelection( 500 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 501 502 assertTrue(resultsCallback.mIsSuccess); 503 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 504 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 505 assertEquals( 506 CommonFixture.getUri( 507 mLocalhostBuyerDomain.getAuthority(), 508 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 509 resultsCallback.mAdSelectionResponse.getRenderUri()); 510 511 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 512 mockWebServerRule.verifyMockServerRequests( 513 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 514 } 515 516 @Test testFledgeFlowSuccessWithDevOverridesWithAdCostCpcBillingEnabled()517 public void testFledgeFlowSuccessWithDevOverridesWithAdCostCpcBillingEnabled() 518 throws Exception { 519 // Re init with cpc billing enabled 520 initClients(false, false, true, false, false, false); 521 522 setupConsentGivenStubs(); 523 524 setupAdSelectionConfig(); 525 526 String decisionLogicJs = getDecisionLogicJs(); 527 String biddingLogicJs = getBiddingLogicJsWithAdCost(); 528 529 MockWebServer server = 530 mockWebServerRule.startMockWebServer( 531 request -> new MockResponse().setResponseCode(404)); 532 533 when(mDevContextFilterMock.createDevContext()) 534 .thenReturn( 535 DevContext.builder() 536 .setDevOptionsEnabled(true) 537 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 538 .build()); 539 540 CustomAudience customAudience1 = 541 createCustomAudienceWithAdCost( 542 mLocalhostBuyerDomain, 543 CUSTOM_AUDIENCE_SEQ_1, 544 BIDS_FOR_BUYER_1, 545 AD_COST_1.getAdCost()); 546 547 CustomAudience customAudience2 = 548 createCustomAudienceWithAdCost( 549 mLocalhostBuyerDomain, 550 CUSTOM_AUDIENCE_SEQ_2, 551 BIDS_FOR_BUYER_2, 552 AD_COST_2.getAdCost()); 553 554 joinCustomAudienceAndAssertSuccess(customAudience1); 555 joinCustomAudienceAndAssertSuccess(customAudience2); 556 557 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 558 559 setupOverridesAndAssertSuccess( 560 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 561 562 // Run Ad Selection 563 AdSelectionTestCallback resultsCallback = 564 invokeRunAdSelection( 565 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 566 567 assertTrue(resultsCallback.mIsSuccess); 568 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 569 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 570 assertEquals( 571 CommonFixture.getUri( 572 mLocalhostBuyerDomain.getAuthority(), 573 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 574 resultsCallback.mAdSelectionResponse.getRenderUri()); 575 576 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 577 mockWebServerRule.verifyMockServerRequests( 578 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 579 } 580 581 @Test testFledgeFlowSuccessWithDevOverridesWithAdCostCpcBillingDisabled()582 public void testFledgeFlowSuccessWithDevOverridesWithAdCostCpcBillingDisabled() 583 throws Exception { 584 // Re init with cpc billing enabled 585 initClients(false, false, false, false, false, false); 586 587 setupConsentGivenStubs(); 588 589 setupAdSelectionConfig(); 590 591 String decisionLogicJs = getDecisionLogicJs(); 592 String biddingLogicJs = getBiddingLogicJsWithAdCost(); 593 594 MockWebServer server = 595 mockWebServerRule.startMockWebServer( 596 request -> new MockResponse().setResponseCode(404)); 597 598 when(mDevContextFilterMock.createDevContext()) 599 .thenReturn( 600 DevContext.builder() 601 .setDevOptionsEnabled(true) 602 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 603 .build()); 604 605 CustomAudience customAudience1 = 606 createCustomAudienceWithAdCost( 607 mLocalhostBuyerDomain, 608 CUSTOM_AUDIENCE_SEQ_1, 609 BIDS_FOR_BUYER_1, 610 AD_COST_1.getAdCost()); 611 612 CustomAudience customAudience2 = 613 createCustomAudienceWithAdCost( 614 mLocalhostBuyerDomain, 615 CUSTOM_AUDIENCE_SEQ_2, 616 BIDS_FOR_BUYER_2, 617 AD_COST_2.getAdCost()); 618 619 joinCustomAudienceAndAssertSuccess(customAudience1); 620 joinCustomAudienceAndAssertSuccess(customAudience2); 621 622 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 623 624 setupOverridesAndAssertSuccess( 625 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 626 627 // Run Ad Selection 628 AdSelectionTestCallback resultsCallback = 629 invokeRunAdSelection( 630 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 631 632 assertTrue(resultsCallback.mIsSuccess); 633 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 634 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 635 assertEquals( 636 CommonFixture.getUri( 637 mLocalhostBuyerDomain.getAuthority(), 638 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 639 resultsCallback.mAdSelectionResponse.getRenderUri()); 640 641 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 642 mockWebServerRule.verifyMockServerRequests( 643 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 644 } 645 646 @Test testFledgeFlowSuccessWithMockServerReportsAdCostCpcBillingEnabled()647 public void testFledgeFlowSuccessWithMockServerReportsAdCostCpcBillingEnabled() 648 throws Exception { 649 // Re init with cpc billing enabled 650 initClients(false, true, true, false, false, false); 651 doReturn(AdServicesApiConsent.GIVEN) 652 .when(mConsentManagerMock) 653 .getConsent(AdServicesApiType.FLEDGE); 654 doReturn(false) 655 .when(mConsentManagerMock) 656 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 657 658 setupAdSelectionConfig(); 659 String decisionLogicJs = getDecisionLogicWithBeacons(); 660 String biddingLogicJs = getBiddingLogicWithBeaconsWithAdCost(); 661 662 CustomAudience customAudience1 = 663 createCustomAudienceWithAdCost( 664 mLocalhostBuyerDomain, 665 CUSTOM_AUDIENCE_SEQ_1, 666 BIDS_FOR_BUYER_1, 667 AD_COST_1.getAdCost()); 668 669 CustomAudience customAudience2 = 670 createCustomAudienceWithAdCost( 671 mLocalhostBuyerDomain, 672 CUSTOM_AUDIENCE_SEQ_2, 673 BIDS_FOR_BUYER_2, 674 AD_COST_2.getAdCost()); 675 676 // We add permits to the semaphores when the MWS is called and remove them in the asserts 677 Semaphore impressionReportingSemaphore = new Semaphore(0); 678 Semaphore interactionReportingSemaphore = new Semaphore(0); 679 680 MockWebServer server = 681 getMockWebServer( 682 decisionLogicJs, 683 biddingLogicJs, 684 impressionReportingSemaphore, 685 interactionReportingSemaphore, 686 false); 687 688 joinCustomAudienceAndAssertSuccess(customAudience1); 689 joinCustomAudienceAndAssertSuccess(customAudience2); 690 691 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 692 693 selectAdsAndReport( 694 CommonFixture.getUri( 695 mLocalhostBuyerDomain.getAuthority(), 696 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 697 impressionReportingSemaphore, 698 interactionReportingSemaphore); 699 verifyStandardServerRequests(server); 700 } 701 702 @Test testFledgeFlowSuccessWithMockServerWithDataVersionHeaderEnabled()703 public void testFledgeFlowSuccessWithMockServerWithDataVersionHeaderEnabled() throws Exception { 704 // Re init with data version header enabled 705 initClients(false, true, false, true, false, false); 706 doReturn(AdServicesApiConsent.GIVEN) 707 .when(mConsentManagerMock) 708 .getConsent(AdServicesApiType.FLEDGE); 709 doReturn(false) 710 .when(mConsentManagerMock) 711 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 712 713 setupAdSelectionConfigWithDataVersionHeader(); 714 715 String decisionLogicJs = getDecisionLogicWithDataVersion(); 716 String biddingLogicJs = getBiddingLogicWithDataVersion(); 717 718 CustomAudience customAudience1 = 719 createCustomAudienceWithDataVersion( 720 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 721 722 CustomAudience customAudience2 = 723 createCustomAudienceWithDataVersion( 724 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 725 726 // We add permits to the semaphores when the MWS is called and remove them in the asserts 727 Semaphore impressionReportingSemaphore = new Semaphore(0); 728 Semaphore interactionReportingSemaphore = new Semaphore(0); 729 730 MockWebServer server = 731 getMockWebServer( 732 decisionLogicJs, 733 biddingLogicJs, 734 impressionReportingSemaphore, 735 interactionReportingSemaphore, 736 false); 737 738 joinCustomAudienceAndAssertSuccess(customAudience1); 739 joinCustomAudienceAndAssertSuccess(customAudience2); 740 741 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 742 743 AdSelectionTestCallback resultsCallback = 744 invokeRunAdSelection( 745 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 746 747 Uri expectedWinningrUi = 748 CommonFixture.getUri( 749 mLocalhostBuyerDomain.getAuthority(), 750 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"); 751 752 assertTrue(resultsCallback.mIsSuccess); 753 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 754 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 755 assertEquals(expectedWinningrUi, resultsCallback.mAdSelectionResponse.getRenderUri()); 756 757 reportImpressionAndAssertSuccess(resultSelectionId); 758 759 assertTrue(impressionReportingSemaphore.tryAcquire(2, 10, TimeUnit.SECONDS)); 760 assertEquals( 761 "Extra calls made to MockWebServer", 762 0, 763 impressionReportingSemaphore.availablePermits()); 764 765 // interaction should not happen, so there should be no permits 766 assertEquals( 767 "Extra calls made to MockWebServer", 768 0, 769 interactionReportingSemaphore.availablePermits()); 770 771 mockWebServerRule.verifyMockServerRequests( 772 server, 773 8, 774 ImmutableList.of( 775 SELLER_DECISION_LOGIC_URI_PATH, 776 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 777 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 778 BUYER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION, 779 SELLER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION 780 + SELLER_TRUSTED_SIGNAL_PARAMS, 781 SELLER_REPORTING_PATH + "?dataVersion=" + DATA_VERSION_2, 782 BUYER_REPORTING_PATH + "?dataVersion=" + DATA_VERSION_1), 783 mRequestMatcherPrefixMatch); 784 } 785 786 @Test testFledgeFlowSuccessWithMockServerWithDataVersionHeaderDisabled()787 public void testFledgeFlowSuccessWithMockServerWithDataVersionHeaderDisabled() 788 throws Exception { 789 // Re init with data version header disabled 790 initClients(false, true, false, false, false, false); 791 doReturn(AdServicesApiConsent.GIVEN) 792 .when(mConsentManagerMock) 793 .getConsent(AdServicesApiType.FLEDGE); 794 doReturn(false) 795 .when(mConsentManagerMock) 796 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 797 798 setupAdSelectionConfigWithDataVersionHeader(); 799 800 String decisionLogicJs = getDecisionLogicJs(); 801 String biddingLogicJs = getBiddingLogicJs(); 802 803 CustomAudience customAudience1 = 804 createCustomAudienceWithDataVersion( 805 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 806 807 CustomAudience customAudience2 = 808 createCustomAudienceWithDataVersion( 809 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 810 811 // We add permits to the semaphores when the MWS is called and remove them in the asserts 812 Semaphore impressionReportingSemaphore = new Semaphore(0); 813 Semaphore interactionReportingSemaphore = new Semaphore(0); 814 815 MockWebServer server = 816 getMockWebServer( 817 decisionLogicJs, 818 biddingLogicJs, 819 impressionReportingSemaphore, 820 interactionReportingSemaphore, 821 false); 822 823 joinCustomAudienceAndAssertSuccess(customAudience1); 824 joinCustomAudienceAndAssertSuccess(customAudience2); 825 826 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 827 828 AdSelectionTestCallback resultsCallback = 829 invokeRunAdSelection( 830 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 831 832 Uri expectedWinningrUi = 833 CommonFixture.getUri( 834 mLocalhostBuyerDomain.getAuthority(), 835 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"); 836 837 assertTrue(resultsCallback.mIsSuccess); 838 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 839 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 840 assertEquals(expectedWinningrUi, resultsCallback.mAdSelectionResponse.getRenderUri()); 841 842 reportImpressionAndAssertSuccess(resultSelectionId); 843 844 assertTrue(impressionReportingSemaphore.tryAcquire(2, 10, TimeUnit.SECONDS)); 845 assertEquals( 846 "Extra calls made to MockWebServer", 847 0, 848 impressionReportingSemaphore.availablePermits()); 849 850 // interaction should not happen, so there should be no permits 851 assertEquals( 852 "Extra calls made to MockWebServer", 853 0, 854 interactionReportingSemaphore.availablePermits()); 855 856 // Verify requests without data version header are made 857 mockWebServerRule.verifyMockServerRequests( 858 server, 859 8, 860 ImmutableList.of( 861 SELLER_DECISION_LOGIC_URI_PATH, 862 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 863 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 864 BUYER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION, 865 SELLER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION 866 + SELLER_TRUSTED_SIGNAL_PARAMS, 867 SELLER_REPORTING_PATH, 868 BUYER_REPORTING_PATH), 869 mRequestMatcherPrefixMatch); 870 } 871 872 @Test testFledgeFlowSuccessWithMockServerReportsAdCostCpcBillingDisabled()873 public void testFledgeFlowSuccessWithMockServerReportsAdCostCpcBillingDisabled() 874 throws Exception { 875 // Re init with cpc billing enabled 876 initClients(false, true, false, false, false, false); 877 doReturn(AdServicesApiConsent.GIVEN) 878 .when(mConsentManagerMock) 879 .getConsent(AdServicesApiType.FLEDGE); 880 doReturn(false) 881 .when(mConsentManagerMock) 882 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 883 884 setupAdSelectionConfig(); 885 String decisionLogicJs = getDecisionLogicWithBeacons(); 886 String biddingLogicJs = getBiddingLogicWithBeaconsWithAdCost(); 887 888 CustomAudience customAudience1 = 889 createCustomAudienceWithAdCost( 890 mLocalhostBuyerDomain, 891 CUSTOM_AUDIENCE_SEQ_1, 892 BIDS_FOR_BUYER_1, 893 AD_COST_1.getAdCost()); 894 895 CustomAudience customAudience2 = 896 createCustomAudienceWithAdCost( 897 mLocalhostBuyerDomain, 898 CUSTOM_AUDIENCE_SEQ_2, 899 BIDS_FOR_BUYER_2, 900 AD_COST_2.getAdCost()); 901 902 // We add permits to the semaphores when the MWS is called and remove them in the asserts 903 Semaphore impressionReportingSemaphore = new Semaphore(0); 904 Semaphore interactionReportingSemaphore = new Semaphore(0); 905 906 MockWebServer server = 907 getMockWebServer( 908 decisionLogicJs, 909 biddingLogicJs, 910 impressionReportingSemaphore, 911 interactionReportingSemaphore, 912 false); 913 914 joinCustomAudienceAndAssertSuccess(customAudience1); 915 joinCustomAudienceAndAssertSuccess(customAudience2); 916 917 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 918 919 selectAdsAndReport( 920 CommonFixture.getUri( 921 mLocalhostBuyerDomain.getAuthority(), 922 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 923 impressionReportingSemaphore, 924 interactionReportingSemaphore); 925 verifyStandardServerRequests(server); 926 } 927 928 @FlakyTest(bugId = 301009903) 929 @Test testFledgeFlowSuccessWithDevOverridesRegisterAdBeaconEnabled()930 public void testFledgeFlowSuccessWithDevOverridesRegisterAdBeaconEnabled() throws Exception { 931 setupConsentGivenStubs(); 932 933 setupAdSelectionConfig(); 934 String decisionLogicJs = getDecisionLogicWithBeacons(); 935 String biddingLogicJs = getBiddingLogicWithBeacons(); 936 937 MockWebServer server = 938 mockWebServerRule.startMockWebServer( 939 request -> new MockResponse().setResponseCode(404)); 940 941 when(mDevContextFilterMock.createDevContext()) 942 .thenReturn( 943 DevContext.builder() 944 .setDevOptionsEnabled(true) 945 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 946 .build()); 947 948 CustomAudience customAudience1 = 949 createCustomAudience( 950 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 951 952 CustomAudience customAudience2 = 953 createCustomAudience( 954 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 955 956 joinCustomAudienceAndAssertSuccess(customAudience1); 957 joinCustomAudienceAndAssertSuccess(customAudience2); 958 959 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 960 961 setupOverridesAndAssertSuccess( 962 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 963 964 // Run Ad Selection 965 AdSelectionTestCallback resultsCallback = 966 invokeRunAdSelection( 967 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 968 969 assertTrue(resultsCallback.mIsSuccess); 970 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 971 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 972 assertEquals( 973 CommonFixture.getUri( 974 mLocalhostBuyerDomain.getAuthority(), 975 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 976 resultsCallback.mAdSelectionResponse.getRenderUri()); 977 978 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 979 980 reportInteractionAndAssertSuccess(resultsCallback); 981 982 mockWebServerRule.verifyMockServerRequests( 983 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 984 } 985 986 @Test testFledgeFlowSuccessWithDevOverridesGaUxEnabled()987 public void testFledgeFlowSuccessWithDevOverridesGaUxEnabled() throws Exception { 988 initClients(true, true, false, false, false, false); 989 doReturn(AdServicesApiConsent.GIVEN) 990 .when(mConsentManagerMock) 991 .getConsent(AdServicesApiType.FLEDGE); 992 doReturn(false).when(mConsentManagerMock).isFledgeConsentRevokedForApp(any()); 993 doReturn(false) 994 .when(mConsentManagerMock) 995 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 996 997 setupAdSelectionConfig(); 998 String decisionLogicJs = getDecisionLogicWithBeacons(); 999 String biddingLogicJs = getBiddingLogicWithBeacons(); 1000 1001 MockWebServer server = 1002 mockWebServerRule.startMockWebServer( 1003 request -> new MockResponse().setResponseCode(404)); 1004 1005 when(mDevContextFilterMock.createDevContext()) 1006 .thenReturn( 1007 DevContext.builder() 1008 .setDevOptionsEnabled(true) 1009 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 1010 .build()); 1011 1012 CustomAudience customAudience1 = 1013 createCustomAudience( 1014 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 1015 1016 CustomAudience customAudience2 = 1017 createCustomAudience( 1018 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 1019 1020 // Join first custom audience 1021 joinCustomAudienceAndAssertSuccess(customAudience1); 1022 1023 // Join second custom audience 1024 joinCustomAudienceAndAssertSuccess(customAudience2); 1025 1026 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 1027 1028 setupOverridesAndAssertSuccess( 1029 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 1030 1031 // Run Ad Selection 1032 AdSelectionTestCallback resultsCallback = 1033 invokeRunAdSelection( 1034 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1035 1036 assertTrue(resultsCallback.mIsSuccess); 1037 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 1038 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 1039 assertEquals( 1040 CommonFixture.getUri( 1041 mLocalhostBuyerDomain.getAuthority(), 1042 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 1043 resultsCallback.mAdSelectionResponse.getRenderUri()); 1044 1045 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 1046 1047 reportInteractionAndAssertSuccess(resultsCallback); 1048 1049 mockWebServerRule.verifyMockServerRequests( 1050 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 1051 } 1052 1053 @FlakyTest(bugId = 301016443) 1054 @Test testFledgeFlowSuccessWithDevOverridesWithRevokedUserConsentForApp()1055 public void testFledgeFlowSuccessWithDevOverridesWithRevokedUserConsentForApp() 1056 throws Exception { 1057 doReturn(AdServicesApiConsent.GIVEN) 1058 .when(mConsentManagerMock) 1059 .getConsent(AdServicesApiType.FLEDGE); 1060 // Allow the first calls to succeed so that we can verify the rest of the flow works 1061 when(mConsentManagerMock.isFledgeConsentRevokedForApp(any())) 1062 .thenReturn(false) 1063 .thenReturn(true); 1064 when(mConsentManagerMock.isFledgeConsentRevokedForAppAfterSettingFledgeUse(any())) 1065 .thenReturn(false) 1066 .thenReturn(true); 1067 1068 setupAdSelectionConfig(); 1069 String decisionLogicJs = getDecisionLogicWithBeacons(); 1070 String biddingLogicJs = getBiddingLogicWithBeacons(); 1071 1072 MockWebServer server = 1073 mockWebServerRule.startMockWebServer( 1074 request -> new MockResponse().setResponseCode(404)); 1075 1076 when(mDevContextFilterMock.createDevContext()) 1077 .thenReturn( 1078 DevContext.builder() 1079 .setDevOptionsEnabled(true) 1080 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 1081 .build()); 1082 1083 CustomAudience customAudience1 = 1084 createCustomAudience( 1085 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 1086 1087 CustomAudience customAudience2 = 1088 createCustomAudience( 1089 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 1090 1091 joinCustomAudienceAndAssertSuccess(customAudience1); 1092 joinCustomAudienceAndAssertSuccess(customAudience2); 1093 1094 setupOverridesAndAssertSuccess( 1095 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 1096 1097 // Run Ad Selection 1098 AdSelectionTestCallback resultsCallback = 1099 invokeRunAdSelection( 1100 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1101 1102 // Verify that CA1/ad2 won because CA2 was not joined due to user consent 1103 assertTrue(resultsCallback.mIsSuccess); 1104 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 1105 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 1106 assertEquals( 1107 CommonFixture.getUri( 1108 mLocalhostBuyerDomain.getAuthority(), 1109 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_1 + "/ad2"), 1110 resultsCallback.mAdSelectionResponse.getRenderUri()); 1111 1112 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 1113 1114 reportInteractionAndAssertSuccess(resultsCallback); 1115 1116 mockWebServerRule.verifyMockServerRequests( 1117 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 1118 } 1119 1120 @Test testFledgeFlowSuccessWithDevOverridesWithRevokedUserConsentForAppGaUxEnabled()1121 public void testFledgeFlowSuccessWithDevOverridesWithRevokedUserConsentForAppGaUxEnabled() 1122 throws Exception { 1123 initClients(true, true, false, false, false, false); 1124 doReturn(AdServicesApiConsent.GIVEN) 1125 .when(mConsentManagerMock) 1126 .getConsent(AdServicesApiType.FLEDGE); 1127 // Allow the first calls to succeed so that we can verify the rest of the flow works 1128 when(mConsentManagerMock.isFledgeConsentRevokedForApp(any())) 1129 .thenReturn(false) 1130 .thenReturn(true); 1131 when(mConsentManagerMock.isFledgeConsentRevokedForAppAfterSettingFledgeUse(any())) 1132 .thenReturn(false) 1133 .thenReturn(true); 1134 1135 setupAdSelectionConfig(); 1136 String decisionLogicJs = getDecisionLogicWithBeacons(); 1137 String biddingLogicJs = getBiddingLogicWithBeacons(); 1138 1139 MockWebServer server = 1140 mockWebServerRule.startMockWebServer( 1141 request -> new MockResponse().setResponseCode(404)); 1142 1143 when(mDevContextFilterMock.createDevContext()) 1144 .thenReturn( 1145 DevContext.builder() 1146 .setDevOptionsEnabled(true) 1147 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 1148 .build()); 1149 1150 CustomAudience customAudience1 = 1151 createCustomAudience( 1152 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 1153 1154 CustomAudience customAudience2 = 1155 createCustomAudience( 1156 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 1157 1158 joinCustomAudienceAndAssertSuccess(customAudience1); 1159 joinCustomAudienceAndAssertSuccess(customAudience2); 1160 1161 setupOverridesAndAssertSuccess( 1162 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 1163 1164 // Run Ad Selection 1165 AdSelectionTestCallback resultsCallback = 1166 invokeRunAdSelection( 1167 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1168 1169 // Verify that CA1/ad2 won because CA2 was not joined due to user consent 1170 assertTrue(resultsCallback.mIsSuccess); 1171 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 1172 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 1173 assertEquals( 1174 CommonFixture.getUri( 1175 mLocalhostBuyerDomain.getAuthority(), 1176 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_1 + "/ad2"), 1177 resultsCallback.mAdSelectionResponse.getRenderUri()); 1178 1179 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 1180 1181 reportInteractionAndAssertSuccess(resultsCallback); 1182 1183 mockWebServerRule.verifyMockServerRequests( 1184 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 1185 } 1186 1187 @Test testFledgeFlowFailsWithMismatchedPackageNamesReportImpression()1188 public void testFledgeFlowFailsWithMismatchedPackageNamesReportImpression() throws Exception { 1189 setupConsentGivenStubs(); 1190 1191 String otherPackageName = CommonFixture.TEST_PACKAGE_NAME + "different_package"; 1192 1193 // Mocking PackageManager so it passes package name validation, but fails impression 1194 // reporting 1195 // due to package mismatch 1196 PackageManager packageManagerMock = mock(PackageManager.class); 1197 when(mSpyContext.getPackageManager()).thenReturn(packageManagerMock); 1198 when(packageManagerMock.getPackagesForUid(Process.myUid())) 1199 .thenReturn(new String[] {CommonFixture.TEST_PACKAGE_NAME, otherPackageName}); 1200 1201 // Reinitializing service so mocking takes effect 1202 // Create an instance of AdSelection Service with real dependencies 1203 mAdSelectionService = 1204 new AdSelectionServiceImpl( 1205 mAdSelectionEntryDao, 1206 mAppInstallDao, 1207 mCustomAudienceDao, 1208 mEncodedPayloadDao, 1209 mFrequencyCapDao, 1210 mEncryptionKeyDao, 1211 mEnrollmentDao, 1212 mAdServicesHttpsClient, 1213 mDevContextFilterMock, 1214 mLightweightExecutorService, 1215 mBackgroundExecutorService, 1216 mScheduledExecutor, 1217 mSpyContext, 1218 mAdServicesLoggerMock, 1219 DEFAULT_FLAGS, 1220 CallingAppUidSupplierProcessImpl.create(), 1221 mFledgeAuthorizationFilterMock, 1222 mAdSelectionServiceFilterMock, 1223 mAdFilteringFeatureFactory, 1224 mConsentManagerMock, 1225 mMultiCloudSupportStrategy, 1226 mAdSelectionDebugReportDao, 1227 mAdIdFetcher, 1228 mUnusedKAnonSignJoinFactory, 1229 false, 1230 mRetryStrategyFactory, 1231 mConsentedDebugConfigurationGeneratorFactory, 1232 mEgressConfigurationGenerator, 1233 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 1234 1235 mAdSelectionConfig = 1236 AdSelectionConfigFixture.anAdSelectionConfigBuilder() 1237 .setCustomAudienceBuyers( 1238 ImmutableList.of( 1239 AdTechIdentifier.fromString(BUYER_DOMAIN_1.getHost()), 1240 AdTechIdentifier.fromString(BUYER_DOMAIN_2.getHost()))) 1241 .setSeller( 1242 AdTechIdentifier.fromString( 1243 mockWebServerRule 1244 .uriForPath(SELLER_DECISION_LOGIC_URI_PATH) 1245 .getHost())) 1246 .setDecisionLogicUri( 1247 mockWebServerRule.uriForPath(SELLER_DECISION_LOGIC_URI_PATH)) 1248 .setTrustedScoringSignalsUri( 1249 mockWebServerRule.uriForPath(SELLER_TRUSTED_SIGNAL_URI_PATH)) 1250 .build(); 1251 1252 AdSelectionConfig adSelectionConfigWithDifferentCallerPackageName = 1253 AdSelectionConfigFixture.anAdSelectionConfigBuilder() 1254 .setCustomAudienceBuyers( 1255 ImmutableList.of( 1256 AdTechIdentifier.fromString(BUYER_DOMAIN_1.getHost()), 1257 AdTechIdentifier.fromString(BUYER_DOMAIN_2.getHost()))) 1258 .setSeller( 1259 AdTechIdentifier.fromString( 1260 mockWebServerRule 1261 .uriForPath(SELLER_DECISION_LOGIC_URI_PATH) 1262 .getHost())) 1263 .setDecisionLogicUri( 1264 mockWebServerRule.uriForPath(SELLER_DECISION_LOGIC_URI_PATH)) 1265 .setTrustedScoringSignalsUri( 1266 mockWebServerRule.uriForPath(SELLER_TRUSTED_SIGNAL_URI_PATH)) 1267 .build(); 1268 1269 String decisionLogicJs = 1270 "function scoreAd(ad, bid, auction_config, seller_signals," 1271 + " trusted_scoring_signals, contextual_signal, user_signal," 1272 + " custom_audience_signal) { \n" 1273 + " return {'status': 0, 'score': bid };\n" 1274 + "}\n" 1275 + "function reportResult(ad_selection_config, render_uri, bid," 1276 + " contextual_signals) { \n" 1277 + " return {'status': 0, 'results': {'signals_for_buyer':" 1278 + " '{\"signals_for_buyer\":1}', 'reporting_uri': '" 1279 + SELLER_REPORTING_PATH 1280 + "' } };\n" 1281 + "}"; 1282 String biddingLogicJs = 1283 "function generateBid(ad, auction_signals, per_buyer_signals," 1284 + " trusted_bidding_signals, contextual_signals, custom_audience_signals) { \n" 1285 + " return {'status': 0, 'ad': ad, 'bid': ad.metadata.result };\n" 1286 + "}\n" 1287 + "function reportWin(ad_selection_signals, per_buyer_signals," 1288 + " signals_for_buyer, contextual_signals, custom_audience_signals) { \n" 1289 + " return {'status': 0, 'results': {'reporting_uri': '" 1290 + BUYER_REPORTING_PATH 1291 + "' } };\n" 1292 + "}"; 1293 1294 mockWebServerRule.startMockWebServer(request -> new MockResponse().setResponseCode(404)); 1295 1296 when(mDevContextFilterMock.createDevContext()) 1297 .thenReturn( 1298 DevContext.builder() 1299 .setDevOptionsEnabled(true) 1300 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 1301 .build()); 1302 1303 CustomAudience customAudience1 = createCustomAudience(BUYER_DOMAIN_1, BIDS_FOR_BUYER_1); 1304 1305 CustomAudience customAudience2 = createCustomAudience(BUYER_DOMAIN_2, BIDS_FOR_BUYER_2); 1306 1307 joinCustomAudienceAndAssertSuccess(customAudience1); 1308 joinCustomAudienceAndAssertSuccess(customAudience2); 1309 1310 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 1311 1312 setupOverridesAndAssertSuccess( 1313 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 1314 1315 // Run Ad Selection 1316 AdSelectionTestCallback resultsCallback = 1317 invokeRunAdSelection( 1318 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1319 1320 assertTrue(resultsCallback.mIsSuccess); 1321 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 1322 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 1323 assertEquals( 1324 CommonFixture.getUri(BUYER_DOMAIN_2.getHost(), AD_URI_PREFIX + "/ad3"), 1325 resultsCallback.mAdSelectionResponse.getRenderUri()); 1326 1327 // Run Report Impression with different package name 1328 ReportImpressionInput input = 1329 new ReportImpressionInput.Builder() 1330 .setAdSelectionConfig(adSelectionConfigWithDifferentCallerPackageName) 1331 .setAdSelectionId(resultsCallback.mAdSelectionResponse.getAdSelectionId()) 1332 .setCallerPackageName(otherPackageName) 1333 .build(); 1334 1335 ReportImpressionTestCallback reportImpressionTestCallback = 1336 callReportImpression(mAdSelectionService, input); 1337 1338 assertFalse(reportImpressionTestCallback.mIsSuccess); 1339 assertEquals( 1340 reportImpressionTestCallback.mFledgeErrorResponse.getStatusCode(), 1341 AdServicesStatusUtils.STATUS_INVALID_ARGUMENT); 1342 assertEquals( 1343 reportImpressionTestCallback.mFledgeErrorResponse.getErrorMessage(), 1344 CALLER_PACKAGE_NAME_MISMATCH); 1345 1346 // Run Report Interaction, should fail silently due to no registered beacons 1347 reportInteractionAndAssertSuccess(resultsCallback); 1348 } 1349 1350 @Test testFledgeFlowFailsWithWrongPackageNameReportInteraction()1351 public void testFledgeFlowFailsWithWrongPackageNameReportInteraction() throws Exception { 1352 setupConsentGivenStubs(); 1353 1354 String otherPackageName = CommonFixture.TEST_PACKAGE_NAME + "different_package"; 1355 1356 // Mocking PackageManager so it passes package name validation, but fails in interaction 1357 // reporting 1358 // due to package mismatch 1359 PackageManager packageManagerMock = mock(PackageManager.class); 1360 when(mSpyContext.getPackageManager()).thenReturn(packageManagerMock); 1361 when(packageManagerMock.getPackagesForUid(Process.myUid())) 1362 .thenReturn(new String[] {CommonFixture.TEST_PACKAGE_NAME, otherPackageName}); 1363 1364 // Reinitializing service so mocking takes effect 1365 // Create an instance of AdSelection Service with real dependencies 1366 mAdSelectionService = 1367 new AdSelectionServiceImpl( 1368 mAdSelectionEntryDao, 1369 mAppInstallDao, 1370 mCustomAudienceDao, 1371 mEncodedPayloadDao, 1372 mFrequencyCapDao, 1373 mEncryptionKeyDao, 1374 mEnrollmentDao, 1375 mAdServicesHttpsClient, 1376 mDevContextFilterMock, 1377 mLightweightExecutorService, 1378 mBackgroundExecutorService, 1379 mScheduledExecutor, 1380 mSpyContext, 1381 mAdServicesLoggerMock, 1382 DEFAULT_FLAGS, 1383 CallingAppUidSupplierProcessImpl.create(), 1384 mFledgeAuthorizationFilterMock, 1385 mAdSelectionServiceFilterMock, 1386 mAdFilteringFeatureFactory, 1387 mConsentManagerMock, 1388 mMultiCloudSupportStrategy, 1389 mAdSelectionDebugReportDao, 1390 mAdIdFetcher, 1391 mUnusedKAnonSignJoinFactory, 1392 false, 1393 mRetryStrategyFactory, 1394 mConsentedDebugConfigurationGeneratorFactory, 1395 mEgressConfigurationGenerator, 1396 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 1397 1398 mAdSelectionConfig = 1399 AdSelectionConfigFixture.anAdSelectionConfigBuilder() 1400 .setCustomAudienceBuyers( 1401 ImmutableList.of( 1402 AdTechIdentifier.fromString(BUYER_DOMAIN_1.getHost()), 1403 AdTechIdentifier.fromString(BUYER_DOMAIN_2.getHost()))) 1404 .setSeller( 1405 AdTechIdentifier.fromString( 1406 mockWebServerRule 1407 .uriForPath(SELLER_DECISION_LOGIC_URI_PATH) 1408 .getHost())) 1409 .setDecisionLogicUri( 1410 mockWebServerRule.uriForPath(SELLER_DECISION_LOGIC_URI_PATH)) 1411 .setTrustedScoringSignalsUri( 1412 mockWebServerRule.uriForPath(SELLER_TRUSTED_SIGNAL_URI_PATH)) 1413 .build(); 1414 String decisionLogicJs = getDecisionLogicWithBeacons(); 1415 String biddingLogicJs = getBiddingLogicWithBeacons(); 1416 1417 mockWebServerRule.startMockWebServer(request -> new MockResponse().setResponseCode(404)); 1418 1419 when(mDevContextFilterMock.createDevContext()) 1420 .thenReturn( 1421 DevContext.builder() 1422 .setDevOptionsEnabled(true) 1423 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 1424 .build()); 1425 1426 CustomAudience customAudience1 = createCustomAudience(BUYER_DOMAIN_1, BIDS_FOR_BUYER_1); 1427 1428 CustomAudience customAudience2 = createCustomAudience(BUYER_DOMAIN_2, BIDS_FOR_BUYER_2); 1429 1430 joinCustomAudienceAndAssertSuccess(customAudience1); 1431 joinCustomAudienceAndAssertSuccess(customAudience2); 1432 1433 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 1434 1435 setupOverridesAndAssertSuccess( 1436 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 1437 1438 // Run Ad Selection 1439 AdSelectionTestCallback resultsCallback = 1440 invokeRunAdSelection( 1441 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1442 1443 assertTrue(resultsCallback.mIsSuccess); 1444 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 1445 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 1446 assertEquals( 1447 CommonFixture.getUri(BUYER_DOMAIN_2.getHost(), AD_URI_PREFIX + "/ad3"), 1448 resultsCallback.mAdSelectionResponse.getRenderUri()); 1449 1450 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 1451 1452 // Run Report Interaction with different package name 1453 ReportInteractionInput reportInteractionInput = 1454 new ReportInteractionInput.Builder() 1455 .setAdSelectionId(resultsCallback.mAdSelectionResponse.getAdSelectionId()) 1456 .setInteractionKey(CLICK_INTERACTION) 1457 .setInteractionData(INTERACTION_DATA) 1458 .setCallerPackageName(otherPackageName) 1459 .setReportingDestinations(BUYER_DESTINATION | SELLER_DESTINATION) 1460 .build(); 1461 1462 ReportInteractionTestCallback reportInteractionTestCallback = 1463 callReportInteraction(mAdSelectionService, reportInteractionInput); 1464 assertFalse(reportInteractionTestCallback.mIsSuccess); 1465 1466 assertEquals( 1467 reportInteractionTestCallback.mFledgeErrorResponse.getStatusCode(), 1468 AdServicesStatusUtils.STATUS_INVALID_ARGUMENT); 1469 assertEquals( 1470 reportInteractionTestCallback.mFledgeErrorResponse.getErrorMessage(), 1471 EventReporter.NO_MATCH_FOUND_IN_AD_SELECTION_DB); 1472 } 1473 1474 @Test 1475 @FlakyTest(bugId = 298130832) testFledgeFlowSuccessWithOneCAWithNegativeBidsWithDevOverrides()1476 public void testFledgeFlowSuccessWithOneCAWithNegativeBidsWithDevOverrides() throws Exception { 1477 setupConsentGivenStubs(); 1478 1479 setupAdSelectionConfig(); 1480 String decisionLogicJs = getDecisionLogicWithBeacons(); 1481 String biddingLogicJs = getBiddingLogicWithBeacons(); 1482 1483 MockWebServer server = 1484 mockWebServerRule.startMockWebServer( 1485 request -> { 1486 // With overrides the server should not be called 1487 return new MockResponse().setResponseCode(404); 1488 }); 1489 1490 when(mDevContextFilterMock.createDevContext()) 1491 .thenReturn( 1492 DevContext.builder() 1493 .setDevOptionsEnabled(true) 1494 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 1495 .build()); 1496 1497 CustomAudience customAudience1 = 1498 createCustomAudience( 1499 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 1500 1501 CustomAudience customAudience2 = 1502 createCustomAudience(mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, INVALID_BIDS); 1503 joinCustomAudienceAndAssertSuccess(customAudience1); 1504 joinCustomAudienceAndAssertSuccess(customAudience2); 1505 1506 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 1507 1508 setupOverridesAndAssertSuccess( 1509 customAudience1, customAudience2, biddingLogicJs, decisionLogicJs); 1510 1511 // Run Ad Selection 1512 AdSelectionTestCallback resultsCallback = 1513 invokeRunAdSelection( 1514 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1515 1516 assertTrue(resultsCallback.mIsSuccess); 1517 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 1518 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 1519 // Expect that ad from buyer 1 won since buyer 2 had negative bids 1520 assertEquals( 1521 CommonFixture.getUri( 1522 mLocalhostBuyerDomain.getAuthority(), 1523 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_1 + "/ad2"), 1524 resultsCallback.mAdSelectionResponse.getRenderUri()); 1525 1526 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 1527 reportInteractionAndAssertSuccess(resultsCallback); 1528 1529 mockWebServerRule.verifyMockServerRequests( 1530 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 1531 } 1532 1533 @Test testFledgeFlowSuccessWithOneCAWithNegativeBidsWithDevOverrides_v3BiddingLogic()1534 public void testFledgeFlowSuccessWithOneCAWithNegativeBidsWithDevOverrides_v3BiddingLogic() 1535 throws Exception { 1536 setupConsentGivenStubs(); 1537 1538 setupAdSelectionConfig(); 1539 String decisionLogicJs = getDecisionLogicWithBeacons(); 1540 String biddingLogicJs = 1541 "function generateBid(custom_audience, auction_signals, per_buyer_signals,\n" 1542 + " trusted_bidding_signals, contextual_signals) {\n" 1543 + " const ads = custom_audience.ads;\n" 1544 + " let result = null;\n" 1545 + " for (const ad of ads) {\n" 1546 + " if (!result || ad.metadata.result > result.metadata.result) {\n" 1547 + " result = ad;\n" 1548 + " }\n" 1549 + " }\n" 1550 + " return { 'status': 0, 'ad': result, 'bid': result.metadata.result, " 1551 + "'render': result.render_uri };\n" 1552 + "}\n" 1553 + "function reportWin(ad_selection_signals, per_buyer_signals," 1554 + " signals_for_buyer ,contextual_signals, custom_audience_signals) {\n" 1555 + "const beacons = {'click': '" 1556 + mockWebServerRule.uriForPath(CLICK_BUYER_PATH) 1557 + "', 'hover': '" 1558 + mockWebServerRule.uriForPath(HOVER_BUYER_PATH) 1559 + "'};\n" 1560 + "registerAdBeacon(beacons);" 1561 + " return {'status': 0, 'results': {'reporting_uri': '" 1562 + mockWebServerRule.uriForPath(BUYER_REPORTING_PATH) 1563 + "' } };\n" 1564 + "}"; 1565 1566 MockWebServer server = 1567 mockWebServerRule.startMockWebServer( 1568 request -> { 1569 // With overrides the server should not be called 1570 return new MockResponse().setResponseCode(404); 1571 }); 1572 1573 when(mDevContextFilterMock.createDevContext()) 1574 .thenReturn( 1575 DevContext.builder() 1576 .setDevOptionsEnabled(true) 1577 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 1578 .build()); 1579 1580 CustomAudience customAudience1 = 1581 createCustomAudience( 1582 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 1583 1584 CustomAudience customAudience2 = 1585 createCustomAudience(mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, INVALID_BIDS); 1586 joinCustomAudienceAndAssertSuccess(customAudience1); 1587 joinCustomAudienceAndAssertSuccess(customAudience2); 1588 1589 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 1590 1591 // Add AdSelection Override 1592 AdSelectionOverrideTestCallback adSelectionOverrideTestCallback = 1593 callAddAdSelectionOverride( 1594 mAdSelectionService, 1595 mAdSelectionConfig, 1596 decisionLogicJs, 1597 TRUSTED_SCORING_SIGNALS, 1598 BUYERS_DECISION_LOGIC); 1599 1600 assertTrue(adSelectionOverrideTestCallback.mIsSuccess); 1601 1602 // Add Custom Audience Overrides 1603 CustomAudienceOverrideTestCallback customAudienceOverrideTestCallback1 = 1604 callAddCustomAudienceOverride( 1605 CommonFixture.TEST_PACKAGE_NAME, 1606 customAudience1.getBuyer(), 1607 customAudience1.getName(), 1608 biddingLogicJs, 1609 JsVersionRegister.BUYER_BIDDING_LOGIC_VERSION_VERSION_3, 1610 TRUSTED_BIDDING_SIGNALS, 1611 mCustomAudienceService); 1612 1613 assertTrue(customAudienceOverrideTestCallback1.mIsSuccess); 1614 1615 CustomAudienceOverrideTestCallback customAudienceOverrideTestCallback2 = 1616 callAddCustomAudienceOverride( 1617 CommonFixture.TEST_PACKAGE_NAME, 1618 customAudience2.getBuyer(), 1619 customAudience2.getName(), 1620 biddingLogicJs, 1621 JsVersionRegister.BUYER_BIDDING_LOGIC_VERSION_VERSION_3, 1622 TRUSTED_BIDDING_SIGNALS, 1623 mCustomAudienceService); 1624 1625 assertTrue(customAudienceOverrideTestCallback2.mIsSuccess); 1626 1627 // Run Ad Selection 1628 AdSelectionTestCallback resultsCallback = 1629 invokeRunAdSelection( 1630 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1631 1632 assertTrue(resultsCallback.mIsSuccess); 1633 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 1634 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 1635 // Expect that ad from buyer 1 won since buyer 2 had negative bids 1636 assertEquals( 1637 CommonFixture.getUri( 1638 mLocalhostBuyerDomain.getAuthority(), 1639 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_1 + "/ad2"), 1640 resultsCallback.mAdSelectionResponse.getRenderUri()); 1641 1642 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 1643 1644 reportInteractionAndAssertSuccess(resultsCallback); 1645 1646 mockWebServerRule.verifyMockServerRequests( 1647 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 1648 } 1649 1650 @Test testFledgeFlowFailsWithBothCANegativeBidsWithDevOverrides()1651 public void testFledgeFlowFailsWithBothCANegativeBidsWithDevOverrides() throws Exception { 1652 setupConsentGivenStubs(); 1653 1654 mAdSelectionConfig = 1655 AdSelectionConfigFixture.anAdSelectionConfigBuilder() 1656 .setCustomAudienceBuyers( 1657 ImmutableList.of( 1658 AdTechIdentifier.fromString(BUYER_DOMAIN_1.getHost()), 1659 AdTechIdentifier.fromString(BUYER_DOMAIN_2.getHost()))) 1660 .setSeller( 1661 AdTechIdentifier.fromString( 1662 mockWebServerRule 1663 .uriForPath(SELLER_DECISION_LOGIC_URI_PATH) 1664 .getHost())) 1665 .setDecisionLogicUri( 1666 mockWebServerRule.uriForPath(SELLER_DECISION_LOGIC_URI_PATH)) 1667 .setTrustedScoringSignalsUri( 1668 mockWebServerRule.uriForPath(SELLER_TRUSTED_SIGNAL_URI_PATH)) 1669 .build(); 1670 1671 String decisionLogicJs = 1672 "function scoreAd(ad, bid, auction_config, seller_signals," 1673 + " trusted_scoring_signals, contextual_signal, user_signal," 1674 + " custom_audience_signal) { \n" 1675 + " return {'status': 0, 'score': bid };\n" 1676 + "}\n" 1677 + "function reportResult(ad_selection_config, render_uri, bid," 1678 + " contextual_signals) { \n" 1679 + " return {'status': 0, 'results': {'signals_for_buyer':" 1680 + " '{\"signals_for_buyer\":1}', 'reporting_uri': '" 1681 + SELLER_REPORTING_PATH 1682 + "' } };\n" 1683 + "}"; 1684 String biddingLogicJs = 1685 "function generateBid(ad, auction_signals, per_buyer_signals," 1686 + " trusted_bidding_signals, contextual_signals, custom_audience_signals) { \n" 1687 + " return {'status': 0, 'ad': ad, 'bid': ad.metadata.result };\n" 1688 + "}\n" 1689 + "function reportWin(ad_selection_signals, per_buyer_signals," 1690 + " signals_for_buyer, contextual_signals, custom_audience_signals) { \n" 1691 + " return {'status': 0, 'results': {'reporting_uri': '" 1692 + BUYER_REPORTING_PATH 1693 + "' } };\n" 1694 + "}"; 1695 1696 MockWebServer server = 1697 mockWebServerRule.startMockWebServer( 1698 request -> { 1699 // with overrides the server should not be invoked 1700 return new MockResponse().setResponseCode(404); 1701 }); 1702 1703 when(mDevContextFilterMock.createDevContext()) 1704 .thenReturn( 1705 DevContext.builder() 1706 .setDevOptionsEnabled(true) 1707 .setCallingAppPackageName(CommonFixture.TEST_PACKAGE_NAME) 1708 .build()); 1709 1710 CustomAudience customAudience1 = createCustomAudience(BUYER_DOMAIN_1, INVALID_BIDS); 1711 1712 CustomAudience customAudience2 = createCustomAudience(BUYER_DOMAIN_2, INVALID_BIDS); 1713 1714 joinCustomAudienceAndAssertSuccess(customAudience1); 1715 joinCustomAudienceAndAssertSuccess(customAudience2); 1716 1717 // Add AdSelection Override 1718 AdSelectionOverrideTestCallback adSelectionOverrideTestCallback = 1719 callAddAdSelectionOverride( 1720 mAdSelectionService, 1721 mAdSelectionConfig, 1722 decisionLogicJs, 1723 TRUSTED_SCORING_SIGNALS, 1724 BUYERS_DECISION_LOGIC); 1725 1726 assertTrue(adSelectionOverrideTestCallback.mIsSuccess); 1727 1728 // Add Custom Audience Overrides 1729 CustomAudienceOverrideTestCallback customAudienceOverrideTestCallback1 = 1730 callAddCustomAudienceOverride( 1731 CommonFixture.TEST_PACKAGE_NAME, 1732 customAudience1.getBuyer(), 1733 customAudience1.getName(), 1734 biddingLogicJs, 1735 null, 1736 AdSelectionSignals.EMPTY, 1737 mCustomAudienceService); 1738 1739 assertTrue(customAudienceOverrideTestCallback1.mIsSuccess); 1740 1741 CustomAudienceOverrideTestCallback customAudienceOverrideTestCallback2 = 1742 callAddCustomAudienceOverride( 1743 CommonFixture.TEST_PACKAGE_NAME, 1744 customAudience2.getBuyer(), 1745 customAudience2.getName(), 1746 biddingLogicJs, 1747 null, 1748 AdSelectionSignals.EMPTY, 1749 mCustomAudienceService); 1750 1751 assertTrue(customAudienceOverrideTestCallback2.mIsSuccess); 1752 1753 // Run Ad Selection 1754 AdSelectionTestCallback resultsCallback = 1755 invokeRunAdSelection( 1756 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1757 1758 // Assert that ad selection fails since both Custom Audiences have invalid bids 1759 assertFalse(resultsCallback.mIsSuccess); 1760 assertNull(resultsCallback.mAdSelectionResponse); 1761 1762 // Run Report Impression with random ad selection id 1763 ReportImpressionInput input = 1764 new ReportImpressionInput.Builder() 1765 .setAdSelectionConfig(mAdSelectionConfig) 1766 .setAdSelectionId(1) 1767 .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME) 1768 .build(); 1769 1770 ReportImpressionTestCallback reportImpressionTestCallback = 1771 callReportImpression(mAdSelectionService, input); 1772 1773 assertFalse(reportImpressionTestCallback.mIsSuccess); 1774 1775 // Run Report Interaction with random ad selection id 1776 ReportInteractionInput reportInteractionInput = 1777 new ReportInteractionInput.Builder() 1778 .setAdSelectionId(1) 1779 .setInteractionKey(CLICK_INTERACTION) 1780 .setInteractionData(INTERACTION_DATA) 1781 .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME) 1782 .setReportingDestinations(BUYER_DESTINATION | SELLER_DESTINATION) 1783 .build(); 1784 1785 ReportInteractionTestCallback reportInteractionTestCallback = 1786 callReportInteraction(mAdSelectionService, reportInteractionInput); 1787 assertFalse(reportInteractionTestCallback.mIsSuccess); 1788 1789 mockWebServerRule.verifyMockServerRequests( 1790 server, 0, Collections.emptyList(), mRequestMatcherPrefixMatch); 1791 } 1792 1793 @Test testFledgeFlowSuccessWithMockServer_preV3BiddingLogic()1794 public void testFledgeFlowSuccessWithMockServer_preV3BiddingLogic() throws Exception { 1795 doReturn(AdServicesApiConsent.GIVEN) 1796 .when(mConsentManagerMock) 1797 .getConsent(AdServicesApiType.FLEDGE); 1798 doReturn(false) 1799 .when(mConsentManagerMock) 1800 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 1801 1802 setupAdSelectionConfig(); 1803 String decisionLogicJs = getDecisionLogicWithBeacons(); 1804 String biddingLogicJs = getBiddingLogicWithBeacons(); 1805 1806 CustomAudience customAudience1 = 1807 createCustomAudience( 1808 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 1809 1810 CustomAudience customAudience2 = 1811 createCustomAudience( 1812 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 1813 1814 // We add permits to the semaphores when the MWS is called and remove them in the asserts 1815 Semaphore impressionReportingSemaphore = new Semaphore(0); 1816 Semaphore interactionReportingSemaphore = new Semaphore(0); 1817 1818 MockWebServer server = 1819 getMockWebServer( 1820 decisionLogicJs, 1821 biddingLogicJs, 1822 impressionReportingSemaphore, 1823 interactionReportingSemaphore, 1824 false); 1825 1826 joinCustomAudienceAndAssertSuccess(customAudience1); 1827 joinCustomAudienceAndAssertSuccess(customAudience2); 1828 1829 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 1830 1831 selectAdsAndReport( 1832 CommonFixture.getUri( 1833 mLocalhostBuyerDomain.getAuthority(), 1834 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 1835 impressionReportingSemaphore, 1836 interactionReportingSemaphore); 1837 verifyStandardServerRequests(server); 1838 } 1839 1840 @Test testFledgeFlowSuccessWithMockServer_v3BiddingLogic()1841 public void testFledgeFlowSuccessWithMockServer_v3BiddingLogic() throws Exception { 1842 doReturn(AdServicesApiConsent.GIVEN) 1843 .when(mConsentManagerMock) 1844 .getConsent(AdServicesApiType.FLEDGE); 1845 doReturn(false) 1846 .when(mConsentManagerMock) 1847 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 1848 1849 setupAdSelectionConfig(); 1850 1851 CustomAudience customAudience1 = 1852 createCustomAudience( 1853 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 1854 1855 CustomAudience customAudience2 = 1856 createCustomAudience( 1857 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 1858 1859 // We add permits to the semaphores when the MWS is called and remove them in the asserts 1860 Semaphore impressionReportingSemaphore = new Semaphore(0); 1861 Semaphore interactionReportingSemaphore = new Semaphore(0); 1862 1863 MockWebServer server = 1864 getMockWebServer( 1865 getDecisionLogicWithBeacons(), 1866 getV3BiddingLogicJs(), 1867 impressionReportingSemaphore, 1868 interactionReportingSemaphore, 1869 true); 1870 1871 joinCustomAudienceAndAssertSuccess(customAudience1); 1872 joinCustomAudienceAndAssertSuccess(customAudience2); 1873 1874 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 1875 1876 // Run Ad Selection 1877 selectAdsAndReport( 1878 CommonFixture.getUri( 1879 mLocalhostBuyerDomain.getAuthority(), 1880 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 1881 impressionReportingSemaphore, 1882 interactionReportingSemaphore); 1883 verifyStandardServerRequests(server); 1884 } 1885 1886 @Test testFledgeFlowSuccessWithDebugReportingSentImmediately()1887 public void testFledgeFlowSuccessWithDebugReportingSentImmediately() throws Exception { 1888 initClients(false, false, true, true, false, false, true, false, true, false, false, false); 1889 doReturn(AdServicesApiConsent.GIVEN) 1890 .when(mConsentManagerMock) 1891 .getConsent(AdServicesApiType.FLEDGE); 1892 setupAdSelectionConfig(); 1893 joinCustomAudienceAndAssertSuccess( 1894 createCustomAudience( 1895 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1)); 1896 joinCustomAudienceAndAssertSuccess( 1897 createCustomAudience( 1898 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2)); 1899 CountDownLatch debugReportingLatch = new CountDownLatch(4); 1900 MockWebServer server = 1901 getMockWebServer( 1902 getDecisionLogicJsWithDebugReporting( 1903 mLocalhostBuyerDomain 1904 .buildUpon() 1905 .path(SELLER_DEBUG_REPORT_WIN_PATH) 1906 .build() 1907 + DEBUG_REPORT_WINNING_BID_PARAM, 1908 mLocalhostBuyerDomain 1909 .buildUpon() 1910 .path(SELLER_DEBUG_REPORT_LOSS_PATH) 1911 .build() 1912 + DEBUG_REPORT_WINNING_BID_PARAM), 1913 getBiddingLogicWithDebugReporting( 1914 mLocalhostBuyerDomain 1915 .buildUpon() 1916 .path(BUYER_DEBUG_REPORT_WIN_PATH) 1917 .build() 1918 + DEBUG_REPORT_WINNING_BID_PARAM, 1919 mLocalhostBuyerDomain 1920 .buildUpon() 1921 .path(BUYER_DEBUG_REPORT_LOSS_PATH) 1922 .build() 1923 + DEBUG_REPORT_WINNING_BID_PARAM), 1924 /* debugReportingLatch= */ debugReportingLatch); 1925 1926 mMockAdIdWorker.setResult(MockAdIdWorker.MOCK_AD_ID, false); 1927 1928 AdSelectionTestCallback resultsCallback = 1929 invokeRunAdSelection( 1930 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1931 1932 assertTrue(resultsCallback.mIsSuccess); 1933 debugReportingLatch.await(10, TimeUnit.SECONDS); 1934 mockWebServerRule.verifyMockServerRequests( 1935 server, 1936 9, 1937 ImmutableList.of( 1938 SELLER_DECISION_LOGIC_URI_PATH, 1939 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 1940 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 1941 BUYER_TRUSTED_SIGNAL_URI_PATH, 1942 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS, 1943 BUYER_DEBUG_REPORT_WIN_PATH + DEBUG_REPORT_WINNING_BID_RESPONSE, 1944 BUYER_DEBUG_REPORT_LOSS_PATH + DEBUG_REPORT_WINNING_BID_RESPONSE, 1945 SELLER_DEBUG_REPORT_WIN_PATH + DEBUG_REPORT_WINNING_BID_RESPONSE, 1946 SELLER_DEBUG_REPORT_LOSS_PATH + DEBUG_REPORT_WINNING_BID_RESPONSE), 1947 mRequestMatcherPrefixMatch); 1948 } 1949 1950 @Test testFledgeFlowSuccessWithDebugReportingSentInBatch()1951 public void testFledgeFlowSuccessWithDebugReportingSentInBatch() throws Exception { 1952 initClients( 1953 false, false, true, true, false, false, true, false, false, false, false, false); 1954 doReturn(AdServicesApiConsent.GIVEN) 1955 .when(mConsentManagerMock) 1956 .getConsent(AdServicesApiType.FLEDGE); 1957 setupAdSelectionConfig(); 1958 joinCustomAudienceAndAssertSuccess( 1959 createCustomAudience( 1960 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1)); 1961 joinCustomAudienceAndAssertSuccess( 1962 createCustomAudience( 1963 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2)); 1964 MockWebServer server = 1965 getMockWebServer( 1966 getDecisionLogicJsWithDebugReporting( 1967 mLocalhostBuyerDomain 1968 .buildUpon() 1969 .path(SELLER_DEBUG_REPORT_WIN_PATH) 1970 .build() 1971 + DEBUG_REPORT_WINNING_BID_PARAM, 1972 mLocalhostBuyerDomain 1973 .buildUpon() 1974 .path(SELLER_DEBUG_REPORT_LOSS_PATH) 1975 .build() 1976 + DEBUG_REPORT_WINNING_BID_PARAM), 1977 getBiddingLogicWithDebugReporting( 1978 mLocalhostBuyerDomain 1979 .buildUpon() 1980 .path(BUYER_DEBUG_REPORT_WIN_PATH) 1981 .build() 1982 + DEBUG_REPORT_WINNING_BID_PARAM, 1983 mLocalhostBuyerDomain 1984 .buildUpon() 1985 .path(BUYER_DEBUG_REPORT_LOSS_PATH) 1986 .build() 1987 + DEBUG_REPORT_WINNING_BID_PARAM), 1988 /* debugReportingLatch= */ null); 1989 1990 doNothing().when(() -> DebugReportSenderJobService.scheduleIfNeeded(any(), anyBoolean())); 1991 mMockAdIdWorker.setResult(MockAdIdWorker.MOCK_AD_ID, false); 1992 1993 AdSelectionTestCallback resultsCallback = 1994 invokeRunAdSelectionAndWaitForFullCallback( 1995 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 1996 1997 assertTrue(resultsCallback.mIsSuccess); 1998 mockWebServerRule.verifyMockServerRequests( 1999 server, 2000 5, 2001 ImmutableList.of( 2002 SELLER_DECISION_LOGIC_URI_PATH, 2003 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 2004 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 2005 BUYER_TRUSTED_SIGNAL_URI_PATH, 2006 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 2007 mRequestMatcherPrefixMatch); 2008 List<DBAdSelectionDebugReport> debugReports = 2009 mAdSelectionDebugReportDao.getDebugReportsBeforeTime( 2010 CommonFixture.FIXED_NEXT_ONE_DAY, 1000); 2011 assertNotNull(debugReports); 2012 assertFalse(debugReports.isEmpty()); 2013 assertEquals(4, debugReports.size()); 2014 String buyerReportWinUrl = 2015 mLocalhostBuyerDomain.buildUpon().path(BUYER_DEBUG_REPORT_WIN_PATH).build() 2016 + DEBUG_REPORT_WINNING_BID_RESPONSE; 2017 String buyerReportLossUrl = 2018 mLocalhostBuyerDomain.buildUpon().path(BUYER_DEBUG_REPORT_LOSS_PATH).build() 2019 + DEBUG_REPORT_WINNING_BID_RESPONSE; 2020 String sellerReportWinUrl = 2021 mLocalhostBuyerDomain.buildUpon().path(SELLER_DEBUG_REPORT_WIN_PATH).build() 2022 + DEBUG_REPORT_WINNING_BID_RESPONSE; 2023 String sellerReportLossUrl = 2024 mLocalhostBuyerDomain.buildUpon().path(SELLER_DEBUG_REPORT_LOSS_PATH).build() 2025 + DEBUG_REPORT_WINNING_BID_RESPONSE; 2026 Set<String> expectedDebugUris = 2027 ImmutableSet.of( 2028 buyerReportWinUrl, 2029 buyerReportLossUrl, 2030 sellerReportWinUrl, 2031 sellerReportLossUrl); 2032 Set<String> actualDebugUris = 2033 debugReports.stream() 2034 .map( 2035 debugReport -> { 2036 return debugReport.getDebugReportUri().toString(); 2037 }) 2038 .collect(Collectors.toSet()); 2039 assertEquals(expectedDebugUris, actualDebugUris); 2040 verify( 2041 () -> DebugReportSenderJobService.scheduleIfNeeded(any(Context.class), eq(false)), 2042 times(1)); 2043 } 2044 2045 @Test testFledgeFlowSuccessWithDebugReportingDisabledWhenLatEnabled()2046 public void testFledgeFlowSuccessWithDebugReportingDisabledWhenLatEnabled() throws Exception { 2047 initClients( 2048 false, false, true, true, false, false, true, false, false, false, false, false); 2049 doReturn(AdServicesApiConsent.GIVEN) 2050 .when(mConsentManagerMock) 2051 .getConsent(AdServicesApiType.FLEDGE); 2052 setupAdSelectionConfig(); 2053 joinCustomAudienceAndAssertSuccess( 2054 createCustomAudience( 2055 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1)); 2056 joinCustomAudienceAndAssertSuccess( 2057 createCustomAudience( 2058 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2)); 2059 MockWebServer server = 2060 getMockWebServer( 2061 getDecisionLogicJsWithDebugReporting( 2062 mLocalhostBuyerDomain 2063 .buildUpon() 2064 .path(SELLER_DEBUG_REPORT_WIN_PATH) 2065 .build() 2066 + DEBUG_REPORT_WINNING_BID_PARAM, 2067 mLocalhostBuyerDomain 2068 .buildUpon() 2069 .path(SELLER_DEBUG_REPORT_LOSS_PATH) 2070 .build() 2071 + DEBUG_REPORT_WINNING_BID_PARAM), 2072 getBiddingLogicWithDebugReporting( 2073 mLocalhostBuyerDomain 2074 .buildUpon() 2075 .path(BUYER_DEBUG_REPORT_WIN_PATH) 2076 .build() 2077 + DEBUG_REPORT_WINNING_BID_PARAM, 2078 mLocalhostBuyerDomain 2079 .buildUpon() 2080 .path(BUYER_DEBUG_REPORT_LOSS_PATH) 2081 .build() 2082 + DEBUG_REPORT_WINNING_BID_PARAM), 2083 /* debugReportingLatch= */ null); 2084 2085 doNothing().when(() -> DebugReportSenderJobService.scheduleIfNeeded(any(), anyBoolean())); 2086 mMockAdIdWorker.setResult(MockAdIdWorker.MOCK_AD_ID, true); 2087 2088 AdSelectionTestCallback resultsCallback = 2089 invokeRunAdSelectionAndWaitForFullCallback( 2090 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 2091 2092 assertTrue(resultsCallback.mIsSuccess); 2093 mockWebServerRule.verifyMockServerRequests( 2094 server, 2095 5, 2096 ImmutableList.of( 2097 SELLER_DECISION_LOGIC_URI_PATH, 2098 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 2099 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 2100 BUYER_TRUSTED_SIGNAL_URI_PATH, 2101 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 2102 mRequestMatcherPrefixMatch); 2103 List<DBAdSelectionDebugReport> debugReports = 2104 mAdSelectionDebugReportDao.getDebugReportsBeforeTime( 2105 CommonFixture.FIXED_NEXT_ONE_DAY, 1000); 2106 assertNotNull(debugReports); 2107 assertTrue(debugReports.isEmpty()); 2108 verify( 2109 () -> DebugReportSenderJobService.scheduleIfNeeded(any(Context.class), eq(false)), 2110 never()); 2111 } 2112 2113 @Test testFledgeFlowSuccessWithDebugReportingDisabledWhenAdIdServiceDisabled()2114 public void testFledgeFlowSuccessWithDebugReportingDisabledWhenAdIdServiceDisabled() 2115 throws Exception { 2116 initClients(false, false, true, true, false, false, true, false, false, true, false, false); 2117 doReturn(AdServicesApiConsent.GIVEN) 2118 .when(mConsentManagerMock) 2119 .getConsent(AdServicesApiType.FLEDGE); 2120 setupAdSelectionConfig(); 2121 joinCustomAudienceAndAssertSuccess( 2122 createCustomAudience( 2123 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1)); 2124 joinCustomAudienceAndAssertSuccess( 2125 createCustomAudience( 2126 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2)); 2127 MockWebServer server = 2128 getMockWebServer( 2129 getDecisionLogicJsWithDebugReporting( 2130 mLocalhostBuyerDomain 2131 .buildUpon() 2132 .path(SELLER_DEBUG_REPORT_WIN_PATH) 2133 .build() 2134 + DEBUG_REPORT_WINNING_BID_PARAM, 2135 mLocalhostBuyerDomain 2136 .buildUpon() 2137 .path(SELLER_DEBUG_REPORT_LOSS_PATH) 2138 .build() 2139 + DEBUG_REPORT_WINNING_BID_PARAM), 2140 getBiddingLogicWithDebugReporting( 2141 mLocalhostBuyerDomain 2142 .buildUpon() 2143 .path(BUYER_DEBUG_REPORT_WIN_PATH) 2144 .build() 2145 + DEBUG_REPORT_WINNING_BID_PARAM, 2146 mLocalhostBuyerDomain 2147 .buildUpon() 2148 .path(BUYER_DEBUG_REPORT_LOSS_PATH) 2149 .build() 2150 + DEBUG_REPORT_WINNING_BID_PARAM), 2151 /* debugReportingLatch= */ null); 2152 2153 doNothing().when(() -> DebugReportSenderJobService.scheduleIfNeeded(any(), anyBoolean())); 2154 mMockAdIdWorker.setResult(MockAdIdWorker.MOCK_AD_ID, false); 2155 2156 AdSelectionTestCallback resultsCallback = 2157 invokeRunAdSelectionAndWaitForFullCallback( 2158 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 2159 2160 assertTrue(resultsCallback.mIsSuccess); 2161 mockWebServerRule.verifyMockServerRequests( 2162 server, 2163 5, 2164 ImmutableList.of( 2165 SELLER_DECISION_LOGIC_URI_PATH, 2166 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 2167 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 2168 BUYER_TRUSTED_SIGNAL_URI_PATH, 2169 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 2170 mRequestMatcherPrefixMatch); 2171 List<DBAdSelectionDebugReport> debugReports = 2172 mAdSelectionDebugReportDao.getDebugReportsBeforeTime( 2173 CommonFixture.FIXED_NEXT_ONE_DAY, 1000); 2174 assertNotNull(debugReports); 2175 assertTrue(debugReports.isEmpty()); 2176 verify( 2177 () -> DebugReportSenderJobService.scheduleIfNeeded(any(Context.class), eq(false)), 2178 never()); 2179 } 2180 2181 @Test testFledgeFlowSuccessWithMockServer_DoesNotReportToBuyerWhenEnrollmentFails()2182 public void testFledgeFlowSuccessWithMockServer_DoesNotReportToBuyerWhenEnrollmentFails() 2183 throws Exception { 2184 initClients( 2185 false, true, true, true, false, false, false, false, false, false, false, false); 2186 doReturn(AdServicesApiConsent.GIVEN) 2187 .when(mConsentManagerMock) 2188 .getConsent(AdServicesApiType.FLEDGE); 2189 doReturn(false) 2190 .when(mConsentManagerMock) 2191 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 2192 2193 setupAdSelectionConfig(); 2194 2195 CustomAudience customAudience1 = 2196 createCustomAudience( 2197 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 2198 2199 CustomAudience customAudience2 = 2200 createCustomAudience( 2201 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 2202 2203 // We add permits to the semaphores when the MWS is called and remove them in the asserts 2204 Semaphore impressionReportingSemaphore = new Semaphore(0); 2205 Semaphore interactionReportingSemaphore = new Semaphore(0); 2206 2207 MockWebServer server = 2208 getMockWebServer( 2209 getDecisionLogicWithBeacons(), 2210 getV3BiddingLogicJs(), 2211 impressionReportingSemaphore, 2212 interactionReportingSemaphore, 2213 true); 2214 2215 // Make buyer impression reporting fail enrollment check 2216 doThrow(new FledgeAuthorizationFilter.AdTechNotAllowedException()) 2217 .when(mFledgeAuthorizationFilterMock) 2218 .assertAdTechEnrolled( 2219 AdTechIdentifier.fromString( 2220 mockWebServerRule.uriForPath(BUYER_REPORTING_PATH).getHost()), 2221 AD_SERVICES_API_CALLED__API_NAME__REPORT_IMPRESSION); 2222 2223 doThrow(new FledgeAuthorizationFilter.AdTechNotAllowedException()) 2224 .when(mFledgeAuthorizationFilterMock) 2225 .assertAdTechEnrolled( 2226 AdTechIdentifier.fromString( 2227 mockWebServerRule.uriForPath(BUYER_REPORTING_PATH).getHost()), 2228 AD_SERVICES_API_CALLED__API_NAME__REPORT_INTERACTION); 2229 2230 joinCustomAudienceAndAssertSuccess(customAudience1); 2231 joinCustomAudienceAndAssertSuccess(customAudience2); 2232 2233 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 2234 2235 // Run Ad Selection 2236 AdSelectionTestCallback resultsCallback = 2237 invokeRunAdSelection( 2238 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 2239 2240 assertTrue(resultsCallback.mIsSuccess); 2241 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 2242 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 2243 assertEquals( 2244 CommonFixture.getUri( 2245 mLocalhostBuyerDomain.getAuthority(), 2246 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 2247 resultsCallback.mAdSelectionResponse.getRenderUri()); 2248 2249 reportImpressionAndAssertSuccess(resultSelectionId); 2250 reportOnlyBuyerInteractionAndAssertSuccess(resultsCallback); 2251 2252 // Assert only seller impression reporting happened since buyer enrollment check fails 2253 assertTrue(impressionReportingSemaphore.tryAcquire(1, 10, TimeUnit.SECONDS)); 2254 2255 // Assert buyer interaction reporting did not happen 2256 assertTrue(interactionReportingSemaphore.tryAcquire(0, 10, TimeUnit.SECONDS)); 2257 2258 assertEquals( 2259 "Extra calls made to MockWebServer", 2260 0, 2261 impressionReportingSemaphore.availablePermits()); 2262 assertEquals( 2263 "Extra calls made to MockWebServer", 2264 0, 2265 interactionReportingSemaphore.availablePermits()); 2266 2267 // Verify 3 less requests than normal since only seller impression reporting happens 2268 mockWebServerRule.verifyMockServerRequests( 2269 server, 2270 7, 2271 ImmutableList.of( 2272 SELLER_DECISION_LOGIC_URI_PATH, 2273 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 2274 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 2275 BUYER_TRUSTED_SIGNAL_URI_PATH, 2276 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 2277 mRequestMatcherPrefixMatch); 2278 } 2279 2280 @Test testFledgeFlowSuccessWithMockServer_allFilters()2281 public void testFledgeFlowSuccessWithMockServer_allFilters() throws Exception { 2282 testFledgeFlowSuccessAllFilters(false, false); 2283 } 2284 2285 @Test 2286 public void testFledgeFlowSuccessWithMockServer_allFiltersWithUnifiedTablesAuctionServerDisabled()2287 testFledgeFlowSuccessWithMockServer_allFiltersWithUnifiedTablesAuctionServerDisabled() 2288 throws Exception { 2289 testFledgeFlowSuccessAllFilters(true, false); 2290 } 2291 2292 @Test 2293 public void testFledgeFlowSuccessWithMockServer_allFiltersWithUnifiedTablesAuctionServerEnabled()2294 testFledgeFlowSuccessWithMockServer_allFiltersWithUnifiedTablesAuctionServerEnabled() 2295 throws Exception { 2296 testFledgeFlowSuccessAllFilters(true, true); 2297 } 2298 2299 @Test testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_noFilters()2300 public void testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_noFilters() 2301 throws Exception { 2302 initClients(true, true, false, false, false, false); 2303 doReturn(LOCALHOST_BUYER) 2304 .when(mFledgeAuthorizationFilterMock) 2305 .getAndAssertAdTechFromUriAllowed(any(), any(), any(), anyInt(), anyInt()); 2306 doReturn(AdServicesApiConsent.GIVEN) 2307 .when(mConsentManagerMock) 2308 .getConsent(AdServicesApiType.FLEDGE); 2309 doReturn(false) 2310 .when(mConsentManagerMock) 2311 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 2312 2313 setupAdSelectionConfig(); 2314 CustomAudience customAudience1 = 2315 createCustomAudience( 2316 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 2317 2318 // Using the same generic key across all ads in the CA 2319 List<Set<Integer>> adCounterKeysForCa2 = 2320 Arrays.asList( 2321 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 2322 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 2323 Collections.singleton(KeyedFrequencyCapFixture.KEY1)); 2324 /* The final ad with the highest bid has both fcap and app install filters, the second ad 2325 * with the middle bid has only an app install filter and the first ad with the lowest bid 2326 * in this ca has only a fcap filter. 2327 */ 2328 List<AdFilters> adFiltersForCa2 = 2329 Arrays.asList( 2330 new AdFilters.Builder() 2331 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 2332 .build(), 2333 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build(), 2334 new AdFilters.Builder() 2335 .setAppInstallFilters(CURRENT_APP_FILTER) 2336 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 2337 .build()); 2338 CustomAudience customAudience2 = 2339 createCustomAudience( 2340 mLocalhostBuyerDomain, 2341 CUSTOM_AUDIENCE_SEQ_2, 2342 BIDS_FOR_BUYER_2, 2343 adCounterKeysForCa2, 2344 adFiltersForCa2, 2345 false); 2346 2347 // We add permits to the semaphores when the MWS is called and remove them in the asserts 2348 Semaphore impressionReportingSemaphore = new Semaphore(0); 2349 Semaphore interactionReportingSemaphore = new Semaphore(0); 2350 2351 // Prepare the custom audiences as json responses we expect from the server. 2352 AdDataConversionStrategy adDataConversionStrategy = 2353 AdDataConversionStrategyFactory.getAdDataConversionStrategy(false, false, true); 2354 List<DBAdData> ads1 = new ArrayList<>(); 2355 for (AdData ad : customAudience1.getAds()) { 2356 ads1.add( 2357 new DBAdData.Builder() 2358 .setRenderUri(ad.getRenderUri()) 2359 .setMetadata(ad.getMetadata()) 2360 .setAdCounterKeys(ad.getAdCounterKeys()) 2361 .setAdFilters(ad.getAdFilters()) 2362 .build()); 2363 } 2364 String customAudience1JsonString = 2365 CustomAudienceBlobFixture.asJSONObjectString( 2366 null, 2367 null, 2368 customAudience1.getName(), 2369 customAudience1.getActivationTime(), 2370 customAudience1.getExpirationTime(), 2371 customAudience1.getDailyUpdateUri(), 2372 customAudience1.getBiddingLogicUri(), 2373 customAudience1.getUserBiddingSignals().toString(), 2374 DBTrustedBiddingData.fromServiceObject( 2375 customAudience1.getTrustedBiddingData()), 2376 ads1); 2377 List<DBAdData> ads2 = new ArrayList<>(); 2378 for (AdData ad : customAudience2.getAds()) { 2379 ads2.add( 2380 new DBAdData.Builder() 2381 .setRenderUri(ad.getRenderUri()) 2382 .setMetadata(ad.getMetadata()) 2383 .setAdCounterKeys(ad.getAdCounterKeys()) 2384 .setAdFilters(ad.getAdFilters()) 2385 .build()); 2386 } 2387 String customAudience2JsonString = 2388 CustomAudienceBlobFixture.asJSONObjectString( 2389 null, 2390 null, 2391 customAudience2.getName(), 2392 customAudience2.getActivationTime(), 2393 customAudience2.getExpirationTime(), 2394 customAudience2.getDailyUpdateUri(), 2395 customAudience2.getBiddingLogicUri(), 2396 customAudience2.getUserBiddingSignals().toString(), 2397 DBTrustedBiddingData.fromServiceObject( 2398 customAudience2.getTrustedBiddingData()), 2399 ads2); 2400 HashMap<String, String> remoteCustomAudiencesMap = new HashMap<>(); 2401 String customAudience1Id = String.valueOf(customAudience1.hashCode()); 2402 String customAudience2Id = String.valueOf(customAudience2.hashCode()); 2403 remoteCustomAudiencesMap.put(customAudience1Id, customAudience1JsonString); 2404 remoteCustomAudiencesMap.put(customAudience2Id, customAudience2JsonString); 2405 2406 MockWebServer server = 2407 getMockWebServer( 2408 remoteCustomAudiencesMap, 2409 getDecisionLogicWithBeacons(), 2410 getV3BiddingLogicJs(), 2411 impressionReportingSemaphore, 2412 interactionReportingSemaphore, 2413 /* debugReportingLatch= */ null, 2414 true); 2415 2416 // TODO(b/289276159): Schedule background fetch if needed once added to fetchCA. 2417 // doNothing() 2418 // .when(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), anyBoolean())); 2419 2420 fetchAndJoinCustomAudienceAndAssertSuccess( 2421 new FetchAndJoinCustomAudienceInput.Builder( 2422 CommonFixture.getUri( 2423 mLocalhostBuyerDomain.getAuthority(), 2424 FETCH_CA_PATH + "/" + customAudience1Id), 2425 VALID_OWNER) 2426 .build()); 2427 fetchAndJoinCustomAudienceAndAssertSuccess( 2428 new FetchAndJoinCustomAudienceInput.Builder( 2429 CommonFixture.getUri( 2430 mLocalhostBuyerDomain.getAuthority(), 2431 FETCH_CA_PATH + "/" + customAudience2Id), 2432 VALID_OWNER) 2433 .build()); 2434 2435 // TODO(b/289276159): Verify background fetch is scheduled if needed once added to fetchCA. 2436 // verify(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), eq(false))) 2437 2438 // Run Ad Selection no filters active 2439 selectAdsAndReport( 2440 CommonFixture.getUri( 2441 mLocalhostBuyerDomain.getAuthority(), 2442 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 2443 impressionReportingSemaphore, 2444 interactionReportingSemaphore); 2445 2446 // 2 fetch CA requests and 10 requests for the auction with both CAs 2447 mockWebServerRule.verifyMockServerRequests( 2448 server, 2449 12, 2450 ImmutableList.of( 2451 FETCH_CA_PATH + "/" + customAudience1Id, 2452 FETCH_CA_PATH + "/" + customAudience2Id, 2453 SELLER_DECISION_LOGIC_URI_PATH, 2454 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 2455 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 2456 BUYER_TRUSTED_SIGNAL_URI_PATH, 2457 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 2458 mRequestMatcherPrefixMatch); 2459 } 2460 2461 @Test testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudience_appInstallFilters()2462 public void testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudience_appInstallFilters() 2463 throws Exception { 2464 initClients(true, true, false, false, false, false); 2465 doReturn(LOCALHOST_BUYER) 2466 .when(mFledgeAuthorizationFilterMock) 2467 .getAndAssertAdTechFromUriAllowed(any(), any(), any(), anyInt(), anyInt()); 2468 doReturn(AdServicesApiConsent.GIVEN) 2469 .when(mConsentManagerMock) 2470 .getConsent(AdServicesApiType.FLEDGE); 2471 doReturn(false) 2472 .when(mConsentManagerMock) 2473 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 2474 2475 setupAdSelectionConfig(); 2476 CustomAudience customAudience1 = 2477 createCustomAudience( 2478 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 2479 2480 // Using the same generic key across all ads in the CA 2481 List<Set<Integer>> adCounterKeysForCa2 = 2482 Arrays.asList( 2483 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 2484 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 2485 Collections.singleton(KeyedFrequencyCapFixture.KEY1)); 2486 /* The final ad with the highest bid has both fcap and app install filters, the second ad 2487 * with the middle bid has only an app install filter and the first ad with the lowest bid 2488 * in this ca has only a fcap filter. 2489 */ 2490 List<AdFilters> adFiltersForCa2 = 2491 Arrays.asList( 2492 new AdFilters.Builder() 2493 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 2494 .build(), 2495 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build(), 2496 new AdFilters.Builder() 2497 .setAppInstallFilters(CURRENT_APP_FILTER) 2498 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 2499 .build()); 2500 CustomAudience customAudience2 = 2501 createCustomAudience( 2502 mLocalhostBuyerDomain, 2503 CUSTOM_AUDIENCE_SEQ_2, 2504 BIDS_FOR_BUYER_2, 2505 adCounterKeysForCa2, 2506 adFiltersForCa2, 2507 false); 2508 2509 // We add permits to the semaphores when the MWS is called and remove them in the asserts 2510 Semaphore impressionReportingSemaphore = new Semaphore(0); 2511 Semaphore interactionReportingSemaphore = new Semaphore(0); 2512 2513 // Prepare the custom audiences as json responses we expect from the server. 2514 AdDataConversionStrategy adDataConversionStrategy = 2515 AdDataConversionStrategyFactory.getAdDataConversionStrategy(true, true, true); 2516 List<DBAdData> ads1 = new ArrayList<>(); 2517 for (AdData ad : customAudience1.getAds()) { 2518 ads1.add( 2519 new DBAdData.Builder() 2520 .setRenderUri(ad.getRenderUri()) 2521 .setMetadata(ad.getMetadata()) 2522 .setAdCounterKeys(ad.getAdCounterKeys()) 2523 .setAdFilters(ad.getAdFilters()) 2524 .build()); 2525 } 2526 String customAudience1JsonString = 2527 CustomAudienceBlobFixture.asJSONObjectString( 2528 null, 2529 null, 2530 customAudience1.getName(), 2531 customAudience1.getActivationTime(), 2532 customAudience1.getExpirationTime(), 2533 customAudience1.getDailyUpdateUri(), 2534 customAudience1.getBiddingLogicUri(), 2535 customAudience1.getUserBiddingSignals().toString(), 2536 DBTrustedBiddingData.fromServiceObject( 2537 customAudience1.getTrustedBiddingData()), 2538 ads1); 2539 List<DBAdData> ads2 = new ArrayList<>(); 2540 for (AdData ad : customAudience2.getAds()) { 2541 ads2.add( 2542 new DBAdData.Builder() 2543 .setRenderUri(ad.getRenderUri()) 2544 .setMetadata(ad.getMetadata()) 2545 .setAdCounterKeys(ad.getAdCounterKeys()) 2546 .setAdFilters(ad.getAdFilters()) 2547 .build()); 2548 } 2549 String customAudience2JsonString = 2550 CustomAudienceBlobFixture.asJSONObjectString( 2551 null, 2552 null, 2553 customAudience2.getName(), 2554 customAudience2.getActivationTime(), 2555 customAudience2.getExpirationTime(), 2556 customAudience2.getDailyUpdateUri(), 2557 customAudience2.getBiddingLogicUri(), 2558 customAudience2.getUserBiddingSignals().toString(), 2559 DBTrustedBiddingData.fromServiceObject( 2560 customAudience2.getTrustedBiddingData()), 2561 ads2); 2562 HashMap<String, String> remoteCustomAudiencesMap = new HashMap<>(); 2563 String customAudience1Id = String.valueOf(customAudience1.hashCode()); 2564 String customAudience2Id = String.valueOf(customAudience2.hashCode()); 2565 remoteCustomAudiencesMap.put(customAudience1Id, customAudience1JsonString); 2566 remoteCustomAudiencesMap.put(customAudience2Id, customAudience2JsonString); 2567 2568 MockWebServer server = 2569 getMockWebServer( 2570 remoteCustomAudiencesMap, 2571 getDecisionLogicWithBeacons(), 2572 getV3BiddingLogicJs(), 2573 impressionReportingSemaphore, 2574 interactionReportingSemaphore, 2575 /* debugReportingLatch= */ null, 2576 true); 2577 2578 // TODO(b/289276159): Schedule background fetch if needed once added to fetchCA. 2579 // doNothing() 2580 // .when(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), anyBoolean())); 2581 2582 fetchAndJoinCustomAudienceAndAssertSuccess( 2583 new FetchAndJoinCustomAudienceInput.Builder( 2584 CommonFixture.getUri( 2585 mLocalhostBuyerDomain.getAuthority(), 2586 FETCH_CA_PATH + "/" + customAudience1Id), 2587 VALID_OWNER) 2588 .build()); 2589 fetchAndJoinCustomAudienceAndAssertSuccess( 2590 new FetchAndJoinCustomAudienceInput.Builder( 2591 CommonFixture.getUri( 2592 mLocalhostBuyerDomain.getAuthority(), 2593 FETCH_CA_PATH + "/" + customAudience2Id), 2594 VALID_OWNER) 2595 .build()); 2596 2597 // TODO(b/289276159): Verify background fetch is scheduled if needed once added to fetchCA. 2598 // verify(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), eq(false))) 2599 2600 // Run Ad Selection with app install filtering 2601 registerForAppInstallFiltering(); 2602 long adSelectionId = 2603 selectAdsAndReport( 2604 CommonFixture.getUri( 2605 mLocalhostBuyerDomain.getAuthority(), 2606 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad1"), 2607 impressionReportingSemaphore, 2608 interactionReportingSemaphore); 2609 2610 // 2 fetch CA requests and 10 requests for the auctions with both CAs. 2611 mockWebServerRule.verifyMockServerRequests( 2612 server, 2613 12, 2614 ImmutableList.of( 2615 FETCH_CA_PATH + "/" + customAudience1Id, 2616 FETCH_CA_PATH + "/" + customAudience2Id, 2617 SELLER_DECISION_LOGIC_URI_PATH, 2618 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 2619 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 2620 BUYER_TRUSTED_SIGNAL_URI_PATH, 2621 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 2622 mRequestMatcherPrefixMatch); 2623 } 2624 2625 @Test testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_bothFilters()2626 public void testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_bothFilters() 2627 throws Exception { 2628 initClients(true, true, false, false, false, false); 2629 doReturn(LOCALHOST_BUYER) 2630 .when(mFledgeAuthorizationFilterMock) 2631 .getAndAssertAdTechFromUriAllowed(any(), any(), any(), anyInt(), anyInt()); 2632 doReturn(AdServicesApiConsent.GIVEN) 2633 .when(mConsentManagerMock) 2634 .getConsent(AdServicesApiType.FLEDGE); 2635 doReturn(false) 2636 .when(mConsentManagerMock) 2637 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 2638 2639 setupAdSelectionConfig(); 2640 CustomAudience customAudience1 = 2641 createCustomAudience( 2642 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 2643 2644 // Using the same generic key across all ads in the CA 2645 List<Set<Integer>> adCounterKeysForCa2 = 2646 Arrays.asList( 2647 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 2648 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 2649 Collections.singleton(KeyedFrequencyCapFixture.KEY1)); 2650 /* The final ad with the highest bid has both fcap and app install filters, the second ad 2651 * with the middle bid has only an app install filter and the first ad with the lowest bid 2652 * in this ca has only a fcap filter. 2653 */ 2654 List<AdFilters> adFiltersForCa2 = 2655 Arrays.asList( 2656 new AdFilters.Builder() 2657 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 2658 .build(), 2659 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build(), 2660 new AdFilters.Builder() 2661 .setAppInstallFilters(CURRENT_APP_FILTER) 2662 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 2663 .build()); 2664 CustomAudience customAudience2 = 2665 createCustomAudience( 2666 mLocalhostBuyerDomain, 2667 CUSTOM_AUDIENCE_SEQ_2, 2668 BIDS_FOR_BUYER_2, 2669 adCounterKeysForCa2, 2670 adFiltersForCa2, 2671 false); 2672 2673 // We add permits to the semaphores when the MWS is called and remove them in the asserts 2674 Semaphore impressionReportingSemaphore = new Semaphore(0); 2675 Semaphore interactionReportingSemaphore = new Semaphore(0); 2676 2677 // Prepare the custom audiences as json responses we expect from the server. 2678 AdDataConversionStrategy adDataConversionStrategy = 2679 AdDataConversionStrategyFactory.getAdDataConversionStrategy(true, true, true); 2680 List<DBAdData> ads1 = new ArrayList<>(); 2681 for (AdData ad : customAudience1.getAds()) { 2682 ads1.add( 2683 new DBAdData.Builder() 2684 .setRenderUri(ad.getRenderUri()) 2685 .setMetadata(ad.getMetadata()) 2686 .setAdCounterKeys(ad.getAdCounterKeys()) 2687 .setAdFilters(ad.getAdFilters()) 2688 .build()); 2689 } 2690 String customAudience1JsonString = 2691 CustomAudienceBlobFixture.asJSONObjectString( 2692 null, 2693 null, 2694 customAudience1.getName(), 2695 customAudience1.getActivationTime(), 2696 customAudience1.getExpirationTime(), 2697 customAudience1.getDailyUpdateUri(), 2698 customAudience1.getBiddingLogicUri(), 2699 customAudience1.getUserBiddingSignals().toString(), 2700 DBTrustedBiddingData.fromServiceObject( 2701 customAudience1.getTrustedBiddingData()), 2702 ads1); 2703 List<DBAdData> ads2 = new ArrayList<>(); 2704 for (AdData ad : customAudience2.getAds()) { 2705 ads2.add( 2706 new DBAdData.Builder() 2707 .setRenderUri(ad.getRenderUri()) 2708 .setMetadata(ad.getMetadata()) 2709 .setAdCounterKeys(ad.getAdCounterKeys()) 2710 .setAdFilters(ad.getAdFilters()) 2711 .build()); 2712 } 2713 String customAudience2JsonString = 2714 CustomAudienceBlobFixture.asJSONObjectString( 2715 null, 2716 null, 2717 customAudience2.getName(), 2718 customAudience2.getActivationTime(), 2719 customAudience2.getExpirationTime(), 2720 customAudience2.getDailyUpdateUri(), 2721 customAudience2.getBiddingLogicUri(), 2722 customAudience2.getUserBiddingSignals().toString(), 2723 DBTrustedBiddingData.fromServiceObject( 2724 customAudience2.getTrustedBiddingData()), 2725 ads2); 2726 HashMap<String, String> remoteCustomAudiencesMap = new HashMap<>(); 2727 String customAudience1Id = String.valueOf(customAudience1.hashCode()); 2728 String customAudience2Id = String.valueOf(customAudience2.hashCode()); 2729 remoteCustomAudiencesMap.put(customAudience1Id, customAudience1JsonString); 2730 remoteCustomAudiencesMap.put(customAudience2Id, customAudience2JsonString); 2731 2732 MockWebServer server = 2733 getMockWebServer( 2734 remoteCustomAudiencesMap, 2735 getDecisionLogicWithBeacons(), 2736 getV3BiddingLogicJs(), 2737 impressionReportingSemaphore, 2738 interactionReportingSemaphore, 2739 /* debugReportingLatch= */ null, 2740 true); 2741 2742 // TODO(b/289276159): Schedule background fetch if needed once added to fetchCA. 2743 // doNothing() 2744 // .when(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), anyBoolean())); 2745 2746 fetchAndJoinCustomAudienceAndAssertSuccess( 2747 new FetchAndJoinCustomAudienceInput.Builder( 2748 CommonFixture.getUri( 2749 mLocalhostBuyerDomain.getAuthority(), 2750 FETCH_CA_PATH + "/" + customAudience1Id), 2751 VALID_OWNER) 2752 .build()); 2753 fetchAndJoinCustomAudienceAndAssertSuccess( 2754 new FetchAndJoinCustomAudienceInput.Builder( 2755 CommonFixture.getUri( 2756 mLocalhostBuyerDomain.getAuthority(), 2757 FETCH_CA_PATH + "/" + customAudience2Id), 2758 VALID_OWNER) 2759 .build()); 2760 2761 // TODO(b/289276159): Verify background fetch is scheduled if needed once added to fetchCA. 2762 // verify(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), eq(false))) 2763 2764 // Run Ad Selection with app install filtering 2765 registerForAppInstallFiltering(); 2766 long adSelectionId = 2767 selectAdsAndReport( 2768 CommonFixture.getUri( 2769 mLocalhostBuyerDomain.getAuthority(), 2770 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad1"), 2771 impressionReportingSemaphore, 2772 interactionReportingSemaphore); 2773 2774 // Run Ad Selection with both filters 2775 updateHistogramAndAssertSuccess(adSelectionId, FrequencyCapFilters.AD_EVENT_TYPE_CLICK); 2776 selectAdsAndReport( 2777 CommonFixture.getUri( 2778 mLocalhostBuyerDomain.getAuthority(), 2779 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_1 + "/ad2"), 2780 impressionReportingSemaphore, 2781 interactionReportingSemaphore); 2782 2783 // 2 fetch CA requests, 10 requests for the auction with both CAs and 9 requests for the 2784 // auctions with one CA. 2785 mockWebServerRule.verifyMockServerRequests( 2786 server, 2787 21, 2788 ImmutableList.of( 2789 FETCH_CA_PATH + "/" + customAudience1Id, 2790 FETCH_CA_PATH + "/" + customAudience2Id, 2791 SELLER_DECISION_LOGIC_URI_PATH, 2792 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 2793 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 2794 BUYER_TRUSTED_SIGNAL_URI_PATH, 2795 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 2796 mRequestMatcherPrefixMatch); 2797 } 2798 2799 @Test 2800 public void testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_FCapEnabled_AppInstallDisabled()2801 testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_FCapEnabled_AppInstallDisabled() 2802 throws Exception { 2803 initClients( 2804 false, 2805 true, 2806 /* frequencyCapFilteringEnabled= */ true, 2807 /* appInstallFilteringEnabled= */ false, 2808 true, 2809 false, 2810 false, 2811 false, 2812 false, 2813 false, 2814 false, 2815 false); 2816 doReturn(LOCALHOST_BUYER) 2817 .when(mFledgeAuthorizationFilterMock) 2818 .getAndAssertAdTechFromUriAllowed(any(), any(), any(), anyInt(), anyInt()); 2819 doReturn(AdServicesApiConsent.GIVEN) 2820 .when(mConsentManagerMock) 2821 .getConsent(AdServicesApiType.FLEDGE); 2822 doReturn(false) 2823 .when(mConsentManagerMock) 2824 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 2825 2826 setupAdSelectionConfig(); 2827 CustomAudience customAudience1 = 2828 createCustomAudience( 2829 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 2830 2831 // Using the same generic key across all ads in the CA 2832 List<Set<Integer>> adCounterKeysForCa2 = 2833 Arrays.asList( 2834 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 2835 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 2836 Collections.singleton(KeyedFrequencyCapFixture.KEY1)); 2837 /* The final ad with the highest bid has only fcap filters, the second ad 2838 * with the middle bid has both filters and the first ad with the lowest bid 2839 * in this ca has only an app install filter. 2840 */ 2841 List<AdFilters> adFiltersForCa2 = 2842 Arrays.asList( 2843 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build(), 2844 new AdFilters.Builder() 2845 .setAppInstallFilters(CURRENT_APP_FILTER) 2846 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 2847 .build(), 2848 new AdFilters.Builder() 2849 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 2850 .build()); 2851 CustomAudience customAudience2 = 2852 createCustomAudience( 2853 mLocalhostBuyerDomain, 2854 CUSTOM_AUDIENCE_SEQ_2, 2855 BIDS_FOR_BUYER_2, 2856 adCounterKeysForCa2, 2857 adFiltersForCa2, 2858 false); 2859 2860 // We add permits to the semaphores when the MWS is called and remove them in the asserts 2861 Semaphore impressionReportingSemaphore = new Semaphore(0); 2862 Semaphore interactionReportingSemaphore = new Semaphore(0); 2863 2864 List<DBAdData> ads1 = new ArrayList<>(); 2865 for (AdData ad : customAudience1.getAds()) { 2866 ads1.add( 2867 new DBAdData.Builder() 2868 .setRenderUri(ad.getRenderUri()) 2869 .setMetadata(ad.getMetadata()) 2870 .setAdCounterKeys(ad.getAdCounterKeys()) 2871 .setAdFilters(ad.getAdFilters()) 2872 .build()); 2873 } 2874 String customAudience1JsonString = 2875 CustomAudienceBlobFixture.asJSONObjectString( 2876 null, 2877 null, 2878 customAudience1.getName(), 2879 customAudience1.getActivationTime(), 2880 customAudience1.getExpirationTime(), 2881 customAudience1.getDailyUpdateUri(), 2882 customAudience1.getBiddingLogicUri(), 2883 customAudience1.getUserBiddingSignals().toString(), 2884 DBTrustedBiddingData.fromServiceObject( 2885 customAudience1.getTrustedBiddingData()), 2886 ads1); 2887 List<DBAdData> ads2 = new ArrayList<>(); 2888 for (AdData ad : customAudience2.getAds()) { 2889 ads2.add( 2890 new DBAdData.Builder() 2891 .setRenderUri(ad.getRenderUri()) 2892 .setMetadata(ad.getMetadata()) 2893 .setAdCounterKeys(ad.getAdCounterKeys()) 2894 .setAdFilters(ad.getAdFilters()) 2895 .build()); 2896 } 2897 String customAudience2JsonString = 2898 CustomAudienceBlobFixture.asJSONObjectString( 2899 null, 2900 null, 2901 customAudience2.getName(), 2902 customAudience2.getActivationTime(), 2903 customAudience2.getExpirationTime(), 2904 customAudience2.getDailyUpdateUri(), 2905 customAudience2.getBiddingLogicUri(), 2906 customAudience2.getUserBiddingSignals().toString(), 2907 DBTrustedBiddingData.fromServiceObject( 2908 customAudience2.getTrustedBiddingData()), 2909 ads2); 2910 HashMap<String, String> remoteCustomAudiencesMap = new HashMap<>(); 2911 String customAudience1Id = String.valueOf(customAudience1.hashCode()); 2912 String customAudience2Id = String.valueOf(customAudience2.hashCode()); 2913 remoteCustomAudiencesMap.put(customAudience1Id, customAudience1JsonString); 2914 remoteCustomAudiencesMap.put(customAudience2Id, customAudience2JsonString); 2915 2916 MockWebServer server = 2917 getMockWebServer( 2918 remoteCustomAudiencesMap, 2919 getDecisionLogicWithBeacons(), 2920 getV3BiddingLogicJs(), 2921 impressionReportingSemaphore, 2922 interactionReportingSemaphore, 2923 /* debugReportingLatch= */ null, 2924 true); 2925 2926 // TODO(b/289276159): Schedule background fetch if needed once added to fetchCA. 2927 // doNothing() 2928 // .when(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), anyBoolean())); 2929 2930 fetchAndJoinCustomAudienceAndAssertSuccess( 2931 new FetchAndJoinCustomAudienceInput.Builder( 2932 CommonFixture.getUri( 2933 mLocalhostBuyerDomain.getAuthority(), 2934 FETCH_CA_PATH + "/" + customAudience1Id), 2935 VALID_OWNER) 2936 .build()); 2937 fetchAndJoinCustomAudienceAndAssertSuccess( 2938 new FetchAndJoinCustomAudienceInput.Builder( 2939 CommonFixture.getUri( 2940 mLocalhostBuyerDomain.getAuthority(), 2941 FETCH_CA_PATH + "/" + customAudience2Id), 2942 VALID_OWNER) 2943 .build()); 2944 2945 // TODO(b/289276159): Verify background fetch is scheduled if needed once added to fetchCA. 2946 // verify(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), eq(false))) 2947 2948 long adSelectionId = 2949 selectAdsAndReport( 2950 CommonFixture.getUri( 2951 mLocalhostBuyerDomain.getAuthority(), 2952 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 2953 impressionReportingSemaphore, 2954 interactionReportingSemaphore); 2955 2956 // Run Ad Selection, app install ad should now win as it is not filtered and fcap is 2957 // filtered 2958 updateHistogramAndAssertSuccess(adSelectionId, FrequencyCapFilters.AD_EVENT_TYPE_CLICK); 2959 selectAdsAndReport( 2960 CommonFixture.getUri( 2961 mLocalhostBuyerDomain.getAuthority(), 2962 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad1"), 2963 impressionReportingSemaphore, 2964 interactionReportingSemaphore); 2965 2966 // 2 fetch CA requests, 10 requests for the auction with both CAs and 9 requests for the 2967 // auctions with one CA. 2968 mockWebServerRule.verifyMockServerRequests( 2969 server, 2970 22, 2971 ImmutableList.of( 2972 FETCH_CA_PATH + "/" + customAudience1Id, 2973 FETCH_CA_PATH + "/" + customAudience2Id, 2974 SELLER_DECISION_LOGIC_URI_PATH, 2975 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 2976 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 2977 BUYER_TRUSTED_SIGNAL_URI_PATH, 2978 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 2979 mRequestMatcherPrefixMatch); 2980 } 2981 2982 @Test 2983 public void testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_AppInstallEnabled_FCapDisabled()2984 testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_AppInstallEnabled_FCapDisabled() 2985 throws Exception { 2986 // Only app install is enabled 2987 initClients( 2988 false, 2989 true, 2990 /* frequencyCapFilteringEnabled= */ false, 2991 /* appInstallFilteringEnabled= */ true, 2992 true, 2993 false, 2994 false, 2995 false, 2996 false, 2997 false, 2998 false, 2999 false); 3000 doReturn(LOCALHOST_BUYER) 3001 .when(mFledgeAuthorizationFilterMock) 3002 .getAndAssertAdTechFromUriAllowed(any(), any(), any(), anyInt(), anyInt()); 3003 doReturn(AdServicesApiConsent.GIVEN) 3004 .when(mConsentManagerMock) 3005 .getConsent(AdServicesApiType.FLEDGE); 3006 doReturn(false) 3007 .when(mConsentManagerMock) 3008 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 3009 3010 setupAdSelectionConfig(); 3011 CustomAudience customAudience1 = 3012 createCustomAudience( 3013 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 3014 3015 // Using the same generic key across all ads in the CA 3016 List<Set<Integer>> adCounterKeysForCa2 = 3017 Arrays.asList( 3018 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 3019 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 3020 Collections.singleton(KeyedFrequencyCapFixture.KEY1)); 3021 /* The final ad with the highest bid has only app install filters, the second ad 3022 * with the middle bid has both filters and the first ad with the lowest bid 3023 * in this ca has only an fcap filter. 3024 */ 3025 List<AdFilters> adFiltersForCa2 = 3026 Arrays.asList( 3027 new AdFilters.Builder() 3028 .setFrequencyCapFilters(WIN_ONCE_PER_DAY_KEY1) 3029 .build(), 3030 new AdFilters.Builder() 3031 .setAppInstallFilters(CURRENT_APP_FILTER) 3032 .setFrequencyCapFilters(WIN_ONCE_PER_DAY_KEY1) 3033 .build(), 3034 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build()); 3035 CustomAudience customAudience2 = 3036 createCustomAudience( 3037 mLocalhostBuyerDomain, 3038 CUSTOM_AUDIENCE_SEQ_2, 3039 BIDS_FOR_BUYER_2, 3040 adCounterKeysForCa2, 3041 adFiltersForCa2, 3042 false); 3043 3044 // We add permits to the semaphores when the MWS is called and remove them in the asserts 3045 Semaphore impressionReportingSemaphore = new Semaphore(0); 3046 Semaphore interactionReportingSemaphore = new Semaphore(0); 3047 3048 // Prepare the custom audiences as json responses we expect from the server. 3049 List<DBAdData> ads1 = new ArrayList<>(); 3050 for (AdData ad : customAudience1.getAds()) { 3051 ads1.add( 3052 new DBAdData.Builder() 3053 .setRenderUri(ad.getRenderUri()) 3054 .setMetadata(ad.getMetadata()) 3055 .setAdCounterKeys(ad.getAdCounterKeys()) 3056 .setAdFilters(ad.getAdFilters()) 3057 .build()); 3058 } 3059 String customAudience1JsonString = 3060 CustomAudienceBlobFixture.asJSONObjectString( 3061 null, 3062 null, 3063 customAudience1.getName(), 3064 customAudience1.getActivationTime(), 3065 customAudience1.getExpirationTime(), 3066 customAudience1.getDailyUpdateUri(), 3067 customAudience1.getBiddingLogicUri(), 3068 customAudience1.getUserBiddingSignals().toString(), 3069 DBTrustedBiddingData.fromServiceObject( 3070 customAudience1.getTrustedBiddingData()), 3071 ads1); 3072 List<DBAdData> ads2 = new ArrayList<>(); 3073 for (AdData ad : customAudience2.getAds()) { 3074 ads2.add( 3075 new DBAdData.Builder() 3076 .setRenderUri(ad.getRenderUri()) 3077 .setMetadata(ad.getMetadata()) 3078 .setAdCounterKeys(ad.getAdCounterKeys()) 3079 .setAdFilters(ad.getAdFilters()) 3080 .build()); 3081 } 3082 String customAudience2JsonString = 3083 CustomAudienceBlobFixture.asJSONObjectString( 3084 null, 3085 null, 3086 customAudience2.getName(), 3087 customAudience2.getActivationTime(), 3088 customAudience2.getExpirationTime(), 3089 customAudience2.getDailyUpdateUri(), 3090 customAudience2.getBiddingLogicUri(), 3091 customAudience2.getUserBiddingSignals().toString(), 3092 DBTrustedBiddingData.fromServiceObject( 3093 customAudience2.getTrustedBiddingData()), 3094 ads2); 3095 HashMap<String, String> remoteCustomAudiencesMap = new HashMap<>(); 3096 String customAudience1Id = String.valueOf(customAudience1.hashCode()); 3097 String customAudience2Id = String.valueOf(customAudience2.hashCode()); 3098 remoteCustomAudiencesMap.put(customAudience1Id, customAudience1JsonString); 3099 remoteCustomAudiencesMap.put(customAudience2Id, customAudience2JsonString); 3100 3101 MockWebServer server = 3102 getMockWebServer( 3103 remoteCustomAudiencesMap, 3104 getDecisionLogicWithBeacons(), 3105 getV3BiddingLogicJs(), 3106 impressionReportingSemaphore, 3107 interactionReportingSemaphore, 3108 /* debugReportingLatch= */ null, 3109 true); 3110 3111 // TODO(b/289276159): Schedule background fetch if needed once added to fetchCA. 3112 // doNothing() 3113 // .when(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), anyBoolean())); 3114 3115 fetchAndJoinCustomAudienceAndAssertSuccess( 3116 new FetchAndJoinCustomAudienceInput.Builder( 3117 CommonFixture.getUri( 3118 mLocalhostBuyerDomain.getAuthority(), 3119 FETCH_CA_PATH + "/" + customAudience1Id), 3120 VALID_OWNER) 3121 .build()); 3122 fetchAndJoinCustomAudienceAndAssertSuccess( 3123 new FetchAndJoinCustomAudienceInput.Builder( 3124 CommonFixture.getUri( 3125 mLocalhostBuyerDomain.getAuthority(), 3126 FETCH_CA_PATH + "/" + customAudience2Id), 3127 VALID_OWNER) 3128 .build()); 3129 3130 // TODO(b/289276159): Verify background fetch is scheduled if needed once added to fetchCA. 3131 // verify(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), eq(false))) 3132 3133 selectAdsAndReport( 3134 CommonFixture.getUri( 3135 mLocalhostBuyerDomain.getAuthority(), 3136 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 3137 impressionReportingSemaphore, 3138 interactionReportingSemaphore); 3139 3140 registerForAppInstallFiltering(); 3141 3142 // All lowest bid fcap wins since app install is enabled and fcap is disabled 3143 selectAdsAndReport( 3144 CommonFixture.getUri( 3145 mLocalhostBuyerDomain.getAuthority(), 3146 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad1"), 3147 impressionReportingSemaphore, 3148 interactionReportingSemaphore); 3149 3150 // 2 fetch CA requests, 10 requests for the auction with both CAs and 9 requests for the 3151 // auctions with one CA. 3152 mockWebServerRule.verifyMockServerRequests( 3153 server, 3154 22, 3155 ImmutableList.of( 3156 FETCH_CA_PATH + "/" + customAudience1Id, 3157 FETCH_CA_PATH + "/" + customAudience2Id, 3158 SELLER_DECISION_LOGIC_URI_PATH, 3159 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 3160 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 3161 BUYER_TRUSTED_SIGNAL_URI_PATH, 3162 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 3163 mRequestMatcherPrefixMatch); 3164 } 3165 3166 @Test testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_fcapFilters()3167 public void testFledgeFlowSuccessWithMockServer_fetchAndJoinCustomAudienceFlow_fcapFilters() 3168 throws Exception { 3169 initClients(true, true, false, false, false, false); 3170 doReturn(LOCALHOST_BUYER) 3171 .when(mFledgeAuthorizationFilterMock) 3172 .getAndAssertAdTechFromUriAllowed(any(), any(), any(), anyInt(), anyInt()); 3173 doReturn(AdServicesApiConsent.GIVEN) 3174 .when(mConsentManagerMock) 3175 .getConsent(AdServicesApiType.FLEDGE); 3176 doReturn(false) 3177 .when(mConsentManagerMock) 3178 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 3179 3180 setupAdSelectionConfig(); 3181 CustomAudience customAudience1 = 3182 createCustomAudience( 3183 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 3184 3185 // Using the same generic key across all ads in the CA 3186 List<Set<Integer>> adCounterKeysForCa2 = 3187 Arrays.asList( 3188 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 3189 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 3190 Collections.singleton(KeyedFrequencyCapFixture.KEY1)); 3191 /* The final ad with the highest bid has both fcap and app install filters, the second ad 3192 * with the middle bid has only an app install filter and the first ad with the lowest bid 3193 * in this ca has only a fcap filter. 3194 */ 3195 List<AdFilters> adFiltersForCa2 = 3196 Arrays.asList( 3197 new AdFilters.Builder() 3198 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 3199 .build(), 3200 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build(), 3201 new AdFilters.Builder() 3202 .setAppInstallFilters(CURRENT_APP_FILTER) 3203 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 3204 .build()); 3205 CustomAudience customAudience2 = 3206 createCustomAudience( 3207 mLocalhostBuyerDomain, 3208 CUSTOM_AUDIENCE_SEQ_2, 3209 BIDS_FOR_BUYER_2, 3210 adCounterKeysForCa2, 3211 adFiltersForCa2, 3212 false); 3213 3214 // We add permits to the semaphores when the MWS is called and remove them in the asserts 3215 Semaphore impressionReportingSemaphore = new Semaphore(0); 3216 Semaphore interactionReportingSemaphore = new Semaphore(0); 3217 3218 // Prepare the custom audiences as json responses we expect from the server. 3219 AdDataConversionStrategy adDataConversionStrategy = 3220 AdDataConversionStrategyFactory.getAdDataConversionStrategy(true, true, true); 3221 List<DBAdData> ads1 = new ArrayList<>(); 3222 for (AdData ad : customAudience1.getAds()) { 3223 ads1.add( 3224 new DBAdData.Builder() 3225 .setRenderUri(ad.getRenderUri()) 3226 .setMetadata(ad.getMetadata()) 3227 .setAdCounterKeys(ad.getAdCounterKeys()) 3228 .setAdFilters(ad.getAdFilters()) 3229 .build()); 3230 } 3231 String customAudience1JsonString = 3232 CustomAudienceBlobFixture.asJSONObjectString( 3233 null, 3234 null, 3235 customAudience1.getName(), 3236 customAudience1.getActivationTime(), 3237 customAudience1.getExpirationTime(), 3238 customAudience1.getDailyUpdateUri(), 3239 customAudience1.getBiddingLogicUri(), 3240 customAudience1.getUserBiddingSignals().toString(), 3241 DBTrustedBiddingData.fromServiceObject( 3242 customAudience1.getTrustedBiddingData()), 3243 ads1); 3244 List<DBAdData> ads2 = new ArrayList<>(); 3245 for (AdData ad : customAudience2.getAds()) { 3246 ads2.add( 3247 new DBAdData.Builder() 3248 .setRenderUri(ad.getRenderUri()) 3249 .setMetadata(ad.getMetadata()) 3250 .setAdCounterKeys(ad.getAdCounterKeys()) 3251 .setAdFilters(ad.getAdFilters()) 3252 .build()); 3253 } 3254 String customAudience2JsonString = 3255 CustomAudienceBlobFixture.asJSONObjectString( 3256 null, 3257 null, 3258 customAudience2.getName(), 3259 customAudience2.getActivationTime(), 3260 customAudience2.getExpirationTime(), 3261 customAudience2.getDailyUpdateUri(), 3262 customAudience2.getBiddingLogicUri(), 3263 customAudience2.getUserBiddingSignals().toString(), 3264 DBTrustedBiddingData.fromServiceObject( 3265 customAudience2.getTrustedBiddingData()), 3266 ads2); 3267 HashMap<String, String> remoteCustomAudiencesMap = new HashMap<>(); 3268 String customAudience1Id = String.valueOf(customAudience1.hashCode()); 3269 String customAudience2Id = String.valueOf(customAudience2.hashCode()); 3270 remoteCustomAudiencesMap.put(customAudience1Id, customAudience1JsonString); 3271 remoteCustomAudiencesMap.put(customAudience2Id, customAudience2JsonString); 3272 3273 MockWebServer server = 3274 getMockWebServer( 3275 remoteCustomAudiencesMap, 3276 getDecisionLogicWithBeacons(), 3277 getV3BiddingLogicJs(), 3278 impressionReportingSemaphore, 3279 interactionReportingSemaphore, 3280 /* debugReportingLatch= */ null, 3281 true); 3282 3283 // TODO(b/289276159): Schedule background fetch if needed once added to fetchCA. 3284 // doNothing() 3285 // .when(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), anyBoolean())); 3286 3287 fetchAndJoinCustomAudienceAndAssertSuccess( 3288 new FetchAndJoinCustomAudienceInput.Builder( 3289 CommonFixture.getUri( 3290 mLocalhostBuyerDomain.getAuthority(), 3291 FETCH_CA_PATH + "/" + customAudience1Id), 3292 VALID_OWNER) 3293 .build()); 3294 fetchAndJoinCustomAudienceAndAssertSuccess( 3295 new FetchAndJoinCustomAudienceInput.Builder( 3296 CommonFixture.getUri( 3297 mLocalhostBuyerDomain.getAuthority(), 3298 FETCH_CA_PATH + "/" + customAudience2Id), 3299 VALID_OWNER) 3300 .build()); 3301 3302 // TODO(b/289276159): Verify background fetch is scheduled if needed once added to fetchCA. 3303 // verify(() -> BackgroundFetchJobService.scheduleIfNeeded(any(), any(), eq(false))) 3304 3305 // Run Ad Selection no filters active 3306 long adSelectionId = 3307 selectAdsAndReport( 3308 CommonFixture.getUri( 3309 mLocalhostBuyerDomain.getAuthority(), 3310 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 3311 impressionReportingSemaphore, 3312 interactionReportingSemaphore); 3313 3314 // Run Ad Selection with just fcap filtering 3315 updateHistogramAndAssertSuccess(adSelectionId, FrequencyCapFilters.AD_EVENT_TYPE_CLICK); 3316 selectAdsAndReport( 3317 CommonFixture.getUri( 3318 mLocalhostBuyerDomain.getAuthority(), 3319 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad2"), 3320 impressionReportingSemaphore, 3321 interactionReportingSemaphore); 3322 3323 // 2 fetch CA requests and 20 requests for the 2 auctions with both CAs. 3324 mockWebServerRule.verifyMockServerRequests( 3325 server, 3326 22, 3327 ImmutableList.of( 3328 FETCH_CA_PATH + "/" + customAudience1Id, 3329 FETCH_CA_PATH + "/" + customAudience2Id, 3330 SELLER_DECISION_LOGIC_URI_PATH, 3331 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 3332 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 3333 BUYER_TRUSTED_SIGNAL_URI_PATH, 3334 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 3335 mRequestMatcherPrefixMatch); 3336 } 3337 3338 @Test testFledgeFlowSuccessWithMockServer_crossAppFcapFiltering()3339 public void testFledgeFlowSuccessWithMockServer_crossAppFcapFiltering() throws Exception { 3340 testFledgeFlowSuccessWithCrossAppFcapFiltering(/* shouldUseUnifiedTables= */ false); 3341 } 3342 3343 @Test testFledgeFlowSuccessWithMockServer_crossAppFcapFiltering_useUnifiedTables()3344 public void testFledgeFlowSuccessWithMockServer_crossAppFcapFiltering_useUnifiedTables() 3345 throws Exception { 3346 testFledgeFlowSuccessWithCrossAppFcapFiltering(/* shouldUseUnifiedTables= */ true); 3347 } 3348 testFledgeFlowSuccessWithCrossAppFcapFiltering(boolean shouldUseUnifiedTables)3349 public void testFledgeFlowSuccessWithCrossAppFcapFiltering(boolean shouldUseUnifiedTables) 3350 throws Exception { 3351 doNothing() 3352 .when(mFledgeAllowListsFilterSpy) 3353 .assertAppInAllowlist(any(), anyInt(), anyInt()); 3354 doReturn(AdServicesApiConsent.GIVEN) 3355 .when(mConsentManagerMock) 3356 .getConsent(AdServicesApiType.FLEDGE); 3357 doReturn(false) 3358 .when(mConsentManagerMock) 3359 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 3360 initClients( 3361 /* gaUXEnabled= */ true, 3362 /* registerAdBeaconEnabled= */ true, 3363 /* cpcBillingEnabled= */ false, 3364 /* dataVersionHeaderEnabled= */ false, 3365 shouldUseUnifiedTables, 3366 /* auctionServerEnabledReportImpression= */ false); 3367 3368 setupAdSelectionConfig(); 3369 3370 /* Create common CAs for App #1 and App #2 */ 3371 // Create CA_1 without filters 3372 CustomAudience customAudience1 = 3373 createCustomAudience( 3374 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 3375 3376 // Create CA_2 with 1 non-win filter 3377 List<Set<Integer>> adCounterKeysForCa2 = 3378 Arrays.asList(Collections.singleton(KeyedFrequencyCapFixture.KEY1)); 3379 List<AdFilters> adFiltersForCa2 = 3380 Arrays.asList( 3381 new AdFilters.Builder() 3382 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 3383 .build()); 3384 CustomAudience customAudience2 = 3385 createCustomAudience( 3386 mLocalhostBuyerDomain, 3387 CUSTOM_AUDIENCE_SEQ_2, 3388 BIDS_FOR_BUYER_2.subList( 3389 BIDS_FOR_BUYER_2.size() - 1, BIDS_FOR_BUYER_2.size()), 3390 adCounterKeysForCa2, 3391 adFiltersForCa2, 3392 false); 3393 3394 // We add permits to the semaphores when the MWS is called and remove them in the asserts 3395 Semaphore impressionReportingSemaphore = new Semaphore(0); 3396 Semaphore interactionReportingSemaphore = new Semaphore(0); 3397 3398 MockWebServer server = 3399 getMockWebServer( 3400 getDecisionLogicWithBeacons(), 3401 getV3BiddingLogicJs(), 3402 impressionReportingSemaphore, 3403 interactionReportingSemaphore, 3404 true); 3405 3406 /* 3407 * App #1 3408 * - Join CA_1 and CA_2 3409 * - Run ad selection 3410 * - Update ad counter histogram 3411 * - Leave CA_1 and CA_2 3412 */ 3413 String app1PackageName = CommonFixture.TEST_PACKAGE_NAME; 3414 3415 // Join CA_1 and CA_2 3416 joinCustomAudienceAndAssertSuccess(customAudience1, app1PackageName); 3417 joinCustomAudienceAndAssertSuccess(customAudience2, app1PackageName); 3418 3419 // Run Ad Selection 3420 long adSelectionId = 3421 selectAdsAndReport( 3422 CommonFixture.getUri( 3423 mLocalhostBuyerDomain.getAuthority(), 3424 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad1"), 3425 impressionReportingSemaphore, 3426 interactionReportingSemaphore, 3427 app1PackageName); 3428 3429 // Update ad counter histogram 3430 updateHistogramAndAssertSuccess( 3431 adSelectionId, FrequencyCapFilters.AD_EVENT_TYPE_CLICK, app1PackageName); 3432 3433 // Leave CA_1 and CA_2 3434 leaveCustomAudienceAndAssertSuccess( 3435 app1PackageName, 3436 AdTechIdentifier.fromString(mLocalhostBuyerDomain.getHost()), 3437 customAudience1.getName()); 3438 leaveCustomAudienceAndAssertSuccess( 3439 app1PackageName, 3440 AdTechIdentifier.fromString(mLocalhostBuyerDomain.getHost()), 3441 customAudience2.getName()); 3442 3443 /* 3444 * App #2 3445 * - Join CA_1 and CA_2 3446 * - Run ad selection 3447 */ 3448 String app2PackageName = CommonFixture.TEST_PACKAGE_NAME_1; 3449 3450 // Join CA_1 and CA_2 3451 joinCustomAudienceAndAssertSuccess(customAudience1, app2PackageName); 3452 joinCustomAudienceAndAssertSuccess(customAudience2, app2PackageName); 3453 3454 // Run Ad Selection 3455 selectAdsAndReport( 3456 CommonFixture.getUri( 3457 mLocalhostBuyerDomain.getAuthority(), 3458 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_1 + "/ad2"), 3459 impressionReportingSemaphore, 3460 interactionReportingSemaphore, 3461 CommonFixture.TEST_PACKAGE_NAME_1); 3462 3463 /* 3464 * 20 requests for: 3465 * - 10 requests for auction #1 with both CA_1 and CA_2 3466 * - 9 requests for auction #2 with only CA_1 since CA_2 is filtered out 3467 */ 3468 mockWebServerRule.verifyMockServerRequests( 3469 server, 3470 19, 3471 ImmutableList.of( 3472 SELLER_DECISION_LOGIC_URI_PATH, 3473 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 3474 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 3475 BUYER_TRUSTED_SIGNAL_URI_PATH, 3476 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 3477 mRequestMatcherPrefixMatch); 3478 } 3479 3480 @Test testFledgeFlowSuccessWithMockServer_ContextualAdsFlow()3481 public void testFledgeFlowSuccessWithMockServer_ContextualAdsFlow() throws Exception { 3482 // Reinitializing service so default flags are used 3483 // Create an instance of AdSelection Service with real dependencies 3484 mAdSelectionService = 3485 new AdSelectionServiceImpl( 3486 mAdSelectionEntryDao, 3487 mAppInstallDao, 3488 mCustomAudienceDao, 3489 mEncodedPayloadDao, 3490 mFrequencyCapDao, 3491 mEncryptionKeyDao, 3492 mEnrollmentDao, 3493 mAdServicesHttpsClient, 3494 mDevContextFilterMock, 3495 mLightweightExecutorService, 3496 mBackgroundExecutorService, 3497 mScheduledExecutor, 3498 mSpyContext, 3499 mAdServicesLoggerMock, 3500 DEFAULT_FLAGS, 3501 CallingAppUidSupplierProcessImpl.create(), 3502 mFledgeAuthorizationFilterMock, 3503 mAdSelectionServiceFilterMock, 3504 mAdFilteringFeatureFactory, 3505 mConsentManagerMock, 3506 mMultiCloudSupportStrategy, 3507 mAdSelectionDebugReportDao, 3508 mAdIdFetcher, 3509 mUnusedKAnonSignJoinFactory, 3510 false, 3511 mRetryStrategyFactory, 3512 mConsentedDebugConfigurationGeneratorFactory, 3513 mEgressConfigurationGenerator, 3514 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 3515 3516 doReturn(AdServicesApiConsent.GIVEN) 3517 .when(mConsentManagerMock) 3518 .getConsent(AdServicesApiType.FLEDGE); 3519 doReturn(false) 3520 .when(mConsentManagerMock) 3521 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 3522 3523 Uri sellerReportingUri = mockWebServerRule.uriForPath(SELLER_REPORTING_PATH); 3524 Uri buyerReportingUri = mockWebServerRule.uriForPath(BUYER_REPORTING_PATH); 3525 3526 mAdSelectionConfig = 3527 AdSelectionConfigFixture.anAdSelectionConfigBuilder() 3528 // Setting empty buyers 3529 .setCustomAudienceBuyers(ImmutableList.of()) 3530 .setSeller( 3531 AdTechIdentifier.fromString( 3532 mockWebServerRule 3533 .uriForPath(SELLER_DECISION_LOGIC_URI_PATH) 3534 .getHost())) 3535 .setDecisionLogicUri( 3536 mockWebServerRule.uriForPath(SELLER_DECISION_LOGIC_URI_PATH)) 3537 .setTrustedScoringSignalsUri( 3538 mockWebServerRule.uriForPath(SELLER_TRUSTED_SIGNAL_URI_PATH)) 3539 .setPerBuyerSignals( 3540 ImmutableMap.of( 3541 AdTechIdentifier.fromString( 3542 mLocalhostBuyerDomain.getHost()), 3543 AdSelectionSignals.fromString("{\"buyer_signals\":0}"))) 3544 .setPerBuyerSignedContextualAds(createContextualAds()) 3545 .build(); 3546 3547 String decisionLogicJs = 3548 "function scoreAd(ad, bid, auction_config, seller_signals," 3549 + " trusted_scoring_signals, contextual_signal, user_signal," 3550 + " custom_audience_signal) { \n" 3551 + " return {'status': 0, 'score': bid };\n" 3552 + "}\n" 3553 + "function reportResult(ad_selection_config, render_uri, bid," 3554 + " contextual_signals) { \n" 3555 + " return {'status': 0, 'results': {'signals_for_buyer':" 3556 + " '{\"signals_for_buyer\":1}', 'reporting_uri': '" 3557 + sellerReportingUri 3558 + "' } };\n" 3559 + "}"; 3560 3561 String buyerDecisionLogic = 3562 "function reportWin(ad_selection_signals, per_buyer_signals," 3563 + " signals_for_buyer, contextual_signals, custom_audience_signals) { \n" 3564 + " return {'status': 0, 'results': {'reporting_uri': '" 3565 + buyerReportingUri 3566 + "' } };\n" 3567 + "}"; 3568 3569 CountDownLatch reportingResponseLatch = new CountDownLatch(2); 3570 3571 MockWebServer server = 3572 mockWebServerRule.startMockWebServer( 3573 request -> { 3574 String versionHeaderName = 3575 JsVersionHelper.getVersionHeaderName( 3576 JsVersionHelper.JS_PAYLOAD_TYPE_BUYER_BIDDING_LOGIC_JS); 3577 long jsVersion = 3578 JsVersionRegister.BUYER_BIDDING_LOGIC_VERSION_VERSION_3; 3579 switch (request.getPath()) { 3580 case SELLER_DECISION_LOGIC_URI_PATH: 3581 return new MockResponse().setBody(decisionLogicJs); 3582 case BUYER_BIDDING_LOGIC_URI_PATH: 3583 return new MockResponse().setBody(buyerDecisionLogic); 3584 case SELLER_REPORTING_PATH: // Intentional fallthrough 3585 case BUYER_REPORTING_PATH: 3586 reportingResponseLatch.countDown(); 3587 return new MockResponse().setResponseCode(200); 3588 } 3589 3590 // The seller params vary based on runtime, so we are returning trusted 3591 // signals based on correct path prefix 3592 if (request.getPath() 3593 .startsWith( 3594 SELLER_TRUSTED_SIGNAL_URI_PATH 3595 + SELLER_TRUSTED_SIGNAL_PARAMS)) { 3596 return new MockResponse() 3597 .setBody(TRUSTED_SCORING_SIGNALS.toString()); 3598 } 3599 if (request.getPath().startsWith(BUYER_TRUSTED_SIGNAL_URI_PATH)) { 3600 return new MockResponse() 3601 .setBody(TRUSTED_BIDDING_SIGNALS.toString()); 3602 } 3603 return new MockResponse().setResponseCode(404); 3604 }); 3605 3606 // Run Ad Selection 3607 AdSelectionTestCallback resultsCallback = 3608 invokeRunAdSelection( 3609 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 3610 3611 assertTrue(resultsCallback.mIsSuccess); 3612 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 3613 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 3614 assertEquals( 3615 AdDataFixture.getValidRenderUriByBuyer( 3616 AdTechIdentifier.fromString( 3617 mockWebServerRule 3618 .uriForPath( 3619 BUYER_BIDDING_LOGIC_URI_PATH 3620 + CommonFixture.VALID_BUYER_1) 3621 .getHost()), 3622 500), 3623 resultsCallback.mAdSelectionResponse.getRenderUri()); 3624 3625 // Run Report Impression 3626 ReportImpressionInput reportImpressioninput = 3627 new ReportImpressionInput.Builder() 3628 .setAdSelectionConfig(mAdSelectionConfig) 3629 .setAdSelectionId(resultSelectionId) 3630 .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME) 3631 .build(); 3632 3633 ReportImpressionTestCallback reportImpressionTestCallback = 3634 callReportImpression(mAdSelectionService, reportImpressioninput); 3635 3636 assertTrue(reportImpressionTestCallback.mIsSuccess); 3637 reportingResponseLatch.await(); 3638 mockWebServerRule.verifyMockServerRequests( 3639 server, 3640 6, 3641 ImmutableList.of( 3642 SELLER_DECISION_LOGIC_URI_PATH, 3643 BUYER_BIDDING_LOGIC_URI_PATH, 3644 BUYER_REPORTING_PATH, 3645 SELLER_REPORTING_PATH, 3646 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 3647 mRequestMatcherPrefixMatch); 3648 } 3649 3650 @Test testFledgeFlowSuccessWithAppInstallWithMockServer()3651 public void testFledgeFlowSuccessWithAppInstallWithMockServer() throws Exception { 3652 initClients(true, true, false, false, false, false); 3653 doReturn(AdServicesApiConsent.GIVEN) 3654 .when(mConsentManagerMock) 3655 .getConsent(AdServicesApiType.FLEDGE); 3656 doReturn(false) 3657 .when(mConsentManagerMock) 3658 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 3659 3660 setupAdSelectionConfig(); 3661 String decisionLogicJs = getDecisionLogicWithBeacons(); 3662 String biddingLogicJs = 3663 "function generateBid(ad, auction_signals, per_buyer_signals," 3664 + " trusted_bidding_signals, contextual_signals, custom_audience_signals) " 3665 + "{ \n" 3666 + " return {'status': 0, 'ad': ad, 'bid': ad.metadata.result };\n" 3667 + "}\n" 3668 + "function reportWin(ad_selection_signals, per_buyer_signals," 3669 + " signals_for_buyer ,contextual_signals, custom_audience_signals) {\n" 3670 + "const beacons = {'click': '" 3671 + mockWebServerRule.uriForPath(CLICK_BUYER_PATH) 3672 + "', 'hover': '" 3673 + mockWebServerRule.uriForPath(HOVER_BUYER_PATH) 3674 + "'};\n" 3675 + "registerAdBeacon(beacons);" 3676 + " return {'status': 0, 'results': {'reporting_uri': '" 3677 + mockWebServerRule.uriForPath(BUYER_REPORTING_PATH) 3678 + "' } };\n" 3679 + "}"; 3680 3681 CustomAudience customAudience1 = 3682 createCustomAudience( 3683 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 3684 3685 List<AdFilters> adFiltersForCa2 = 3686 Arrays.asList( 3687 null, 3688 null, 3689 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build()); 3690 CustomAudience customAudience2 = 3691 createCustomAudience( 3692 mLocalhostBuyerDomain, 3693 CUSTOM_AUDIENCE_SEQ_2, 3694 BIDS_FOR_BUYER_2, 3695 EMPTY_AD_COUNTER_KEYS_FOR_BUYER_2, 3696 adFiltersForCa2, 3697 false); 3698 3699 // We add permits to the semaphores when the MWS is called and remove them in the asserts 3700 Semaphore impressionReportingSemaphore = new Semaphore(0); 3701 Semaphore interactionReportingSemaphore = new Semaphore(0); 3702 3703 MockWebServer server = 3704 getMockWebServer( 3705 decisionLogicJs, 3706 biddingLogicJs, 3707 impressionReportingSemaphore, 3708 interactionReportingSemaphore, 3709 false); 3710 3711 registerForAppInstallFiltering(); 3712 3713 joinCustomAudienceAndAssertSuccess(customAudience1); 3714 joinCustomAudienceAndAssertSuccess(customAudience2); 3715 3716 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 3717 3718 // Run Ad Selection 3719 selectAdsAndReport( 3720 CommonFixture.getUri( 3721 mLocalhostBuyerDomain.getAuthority(), 3722 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad2"), 3723 impressionReportingSemaphore, 3724 interactionReportingSemaphore); 3725 verifyStandardServerRequests(server); 3726 } 3727 3728 @Test testFledgeFlowSuccessWithAppInstallFlagOffWithMockServer()3729 public void testFledgeFlowSuccessWithAppInstallFlagOffWithMockServer() throws Exception { 3730 initClients( 3731 false, true, false, false, true, false, false, false, false, false, false, false); 3732 doReturn(AdServicesApiConsent.GIVEN) 3733 .when(mConsentManagerMock) 3734 .getConsent(AdServicesApiType.FLEDGE); 3735 doReturn(false) 3736 .when(mConsentManagerMock) 3737 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 3738 3739 setupAdSelectionConfig(); 3740 String decisionLogicJs = getDecisionLogicWithBeacons(); 3741 String biddingLogicJs = 3742 "function generateBid(ad, auction_signals, per_buyer_signals," 3743 + " trusted_bidding_signals, contextual_signals, custom_audience_signals) " 3744 + "{ \n" 3745 + " return {'status': 0, 'ad': ad, 'bid': ad.metadata.result };\n" 3746 + "}\n" 3747 + "function reportWin(ad_selection_signals, per_buyer_signals," 3748 + " signals_for_buyer ,contextual_signals, custom_audience_signals) {\n" 3749 + "const beacons = {'click': '" 3750 + mockWebServerRule.uriForPath(CLICK_BUYER_PATH) 3751 + "', 'hover': '" 3752 + mockWebServerRule.uriForPath(HOVER_BUYER_PATH) 3753 + "'};\n" 3754 + "registerAdBeacon(beacons);" 3755 + " return {'status': 0, 'results': {'reporting_uri': '" 3756 + mockWebServerRule.uriForPath(BUYER_REPORTING_PATH) 3757 + "' } };\n" 3758 + "}"; 3759 3760 CustomAudience customAudience1 = 3761 createCustomAudience( 3762 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 3763 3764 List<AdFilters> filtersForCa2 = 3765 Arrays.asList( 3766 null, 3767 null, 3768 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build()); 3769 CustomAudience customAudience2 = 3770 createCustomAudience( 3771 mLocalhostBuyerDomain, 3772 CUSTOM_AUDIENCE_SEQ_2, 3773 BIDS_FOR_BUYER_2, 3774 EMPTY_AD_COUNTER_KEYS_FOR_BUYER_2, 3775 filtersForCa2, 3776 false); 3777 3778 // We add permits to the semaphores when the MWS is called and remove them in the asserts 3779 Semaphore impressionReportingSemaphore = new Semaphore(0); 3780 Semaphore interactionReportingSemaphore = new Semaphore(0); 3781 3782 MockWebServer server = 3783 getMockWebServer( 3784 decisionLogicJs, 3785 biddingLogicJs, 3786 impressionReportingSemaphore, 3787 interactionReportingSemaphore, 3788 false); 3789 3790 // Registers the test app for app install filtering 3791 // Should fail since flag is turned off 3792 // Everything else should pass 3793 AppInstallResultCapturingCallback callback = invokeSetAppInstallAdvertisers(); 3794 assertFalse(callback.isSuccess()); 3795 assertTrue(callback.getException() instanceof IllegalStateException); 3796 3797 joinCustomAudienceAndAssertSuccess(customAudience1); 3798 joinCustomAudienceAndAssertSuccess(customAudience2); 3799 3800 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 3801 3802 // CA 2's ad3 should win even though it tried to filter itself 3803 selectAdsAndReport( 3804 CommonFixture.getUri( 3805 mLocalhostBuyerDomain.getAuthority(), 3806 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 3807 impressionReportingSemaphore, 3808 interactionReportingSemaphore); 3809 verifyStandardServerRequests(server); 3810 } 3811 3812 @Test testFledgeFlowSuccessWithRevokedUserConsentForApp()3813 public void testFledgeFlowSuccessWithRevokedUserConsentForApp() throws Exception { 3814 doReturn(AdServicesApiConsent.GIVEN) 3815 .when(mConsentManagerMock) 3816 .getConsent(AdServicesApiType.FLEDGE); 3817 // Allow the first join call to succeed so that we can verify the rest of the flow works 3818 when(mConsentManagerMock.isFledgeConsentRevokedForAppAfterSettingFledgeUse(any())) 3819 .thenReturn(false) 3820 .thenReturn(true); 3821 3822 setupAdSelectionConfig(); 3823 String decisionLogicJs = getDecisionLogicWithBeacons(); 3824 String biddingLogicJs = getBiddingLogicWithBeacons(); 3825 3826 CustomAudience customAudience1 = 3827 createCustomAudience( 3828 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 3829 3830 CustomAudience customAudience2 = 3831 createCustomAudience( 3832 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 3833 3834 // We add permits to the semaphores when the MWS is called and remove them in the asserts 3835 Semaphore impressionReportingSemaphore = new Semaphore(0); 3836 Semaphore interactionReportingSemaphore = new Semaphore(0); 3837 3838 MockWebServer server = 3839 mockWebServerRule.startMockWebServer( 3840 request -> { 3841 switch (request.getPath()) { 3842 case SELLER_DECISION_LOGIC_URI_PATH: 3843 return new MockResponse().setBody(decisionLogicJs); 3844 case BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1: 3845 return new MockResponse().setBody(biddingLogicJs); 3846 case BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2: 3847 throw new IllegalStateException( 3848 "This should not be called without user consent"); 3849 case CLICK_SELLER_PATH: // Intentional fallthrough 3850 case CLICK_BUYER_PATH: 3851 interactionReportingSemaphore.release(); 3852 return new MockResponse().setResponseCode(200); 3853 case SELLER_REPORTING_PATH: // Intentional fallthrough 3854 case BUYER_REPORTING_PATH: 3855 impressionReportingSemaphore.release(); 3856 return new MockResponse().setResponseCode(200); 3857 } 3858 3859 // The seller params vary based on runtime, so we are returning trusted 3860 // signals based on correct path prefix 3861 if (request.getPath() 3862 .startsWith( 3863 SELLER_TRUSTED_SIGNAL_URI_PATH 3864 + SELLER_TRUSTED_SIGNAL_PARAMS)) { 3865 return new MockResponse() 3866 .setBody(TRUSTED_SCORING_SIGNALS.toString()); 3867 } 3868 if (request.getPath().startsWith(BUYER_TRUSTED_SIGNAL_URI_PATH)) { 3869 return new MockResponse() 3870 .setBody(TRUSTED_BIDDING_SIGNALS.toString()); 3871 } 3872 return new MockResponse().setResponseCode(404); 3873 }); 3874 3875 joinCustomAudienceAndAssertSuccess(customAudience1); 3876 joinCustomAudienceAndAssertSuccess(customAudience2); 3877 3878 // Run Ad Selection 3879 selectAdsAndReport( 3880 CommonFixture.getUri( 3881 mLocalhostBuyerDomain.getAuthority(), 3882 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_1 + "/ad2"), 3883 impressionReportingSemaphore, 3884 interactionReportingSemaphore); 3885 mockWebServerRule.verifyMockServerRequests( 3886 server, 3887 9, 3888 ImmutableList.of( 3889 SELLER_DECISION_LOGIC_URI_PATH, 3890 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 3891 BUYER_TRUSTED_SIGNAL_URI_PATH, 3892 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 3893 mRequestMatcherPrefixMatch); 3894 } 3895 3896 @Test testFledgeFlowSuccessWithRevokedUserConsentForFledge()3897 public void testFledgeFlowSuccessWithRevokedUserConsentForFledge() throws Exception { 3898 doReturn(AdServicesApiConsent.REVOKED).when(mConsentManagerMock).getConsent(); 3899 doReturn(true) 3900 .when(mConsentManagerMock) 3901 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 3902 doThrow(new FilterException(new ConsentManager.RevokedConsentException())) 3903 .when(mAdSelectionServiceFilterMock) 3904 .filterRequest( 3905 any(), 3906 anyString(), 3907 anyBoolean(), 3908 anyBoolean(), 3909 anyInt(), 3910 anyInt(), 3911 any(), 3912 any()); 3913 3914 setupAdSelectionConfig(); 3915 3916 CustomAudience customAudience1 = 3917 createCustomAudience( 3918 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 3919 3920 CustomAudience customAudience2 = 3921 createCustomAudience( 3922 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, BIDS_FOR_BUYER_2); 3923 3924 MockWebServer server = 3925 mockWebServerRule.startMockWebServer( 3926 request -> { 3927 throw new IllegalStateException( 3928 "No calls should be made without user consent"); 3929 }); 3930 3931 joinCustomAudienceAndAssertSuccess(customAudience1); 3932 joinCustomAudienceAndAssertSuccess(customAudience2); 3933 3934 // Run Ad Selection 3935 AdSelectionTestCallback resultsCallback = 3936 invokeRunAdSelection( 3937 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 3938 3939 assertTrue(resultsCallback.mIsSuccess); 3940 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 3941 assertFalse(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 3942 assertEquals(Uri.EMPTY, resultsCallback.mAdSelectionResponse.getRenderUri()); 3943 3944 reportImpressionAndAssertSuccess(resultSelectionId); 3945 reportInteractionAndAssertSuccess(resultsCallback); 3946 3947 mockWebServerRule.verifyMockServerRequests( 3948 server, 0, ImmutableList.of(), mRequestMatcherPrefixMatch); 3949 } 3950 3951 @Test testFledgeFlowSuccessWithOneCAWithNegativeBidsWithMockServer()3952 public void testFledgeFlowSuccessWithOneCAWithNegativeBidsWithMockServer() throws Exception { 3953 doReturn(AdServicesApiConsent.GIVEN) 3954 .when(mConsentManagerMock) 3955 .getConsent(AdServicesApiType.FLEDGE); 3956 doReturn(false) 3957 .when(mConsentManagerMock) 3958 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 3959 3960 setupAdSelectionConfig(); 3961 String decisionLogicJs = getDecisionLogicWithBeacons(); 3962 String biddingLogicJs = getBiddingLogicWithBeacons(); 3963 3964 CustomAudience customAudience1 = 3965 createCustomAudience( 3966 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 3967 3968 CustomAudience customAudience2 = 3969 createCustomAudience(mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_2, INVALID_BIDS); 3970 3971 // We add permits to the semaphores when the MWS is called and remove them in the asserts 3972 Semaphore impressionReportingSemaphore = new Semaphore(0); 3973 Semaphore interactionReportingSemaphore = new Semaphore(0); 3974 3975 MockWebServer server = 3976 getMockWebServer( 3977 decisionLogicJs, 3978 biddingLogicJs, 3979 impressionReportingSemaphore, 3980 interactionReportingSemaphore, 3981 false); 3982 3983 joinCustomAudienceAndAssertSuccess(customAudience1); 3984 joinCustomAudienceAndAssertSuccess(customAudience2); 3985 3986 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 3987 3988 // Run Ad Selection 3989 AdSelectionTestCallback resultsCallback = 3990 invokeRunAdSelection( 3991 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 3992 3993 assertTrue(resultsCallback.mIsSuccess); 3994 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 3995 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 3996 3997 // Expect that ad from buyer 1 won since buyer 2 had negative bids 3998 assertEquals( 3999 CommonFixture.getUri( 4000 mLocalhostBuyerDomain.getAuthority(), 4001 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_1 + "/ad2"), 4002 resultsCallback.mAdSelectionResponse.getRenderUri()); 4003 4004 reportImpressionAndAssertSuccess(resultsCallback.mAdSelectionResponse.getAdSelectionId()); 4005 4006 reportInteractionAndAssertSuccess(resultsCallback); 4007 4008 /* We add a permit on every call received by the MockWebServer and remove them in the 4009 * tryAcquires below. If there are any left over it means that there were extra calls to the 4010 * mockserver. 4011 */ 4012 assertTrue(impressionReportingSemaphore.tryAcquire(2, 10, TimeUnit.SECONDS)); 4013 assertTrue(interactionReportingSemaphore.tryAcquire(2, 10, TimeUnit.SECONDS)); 4014 assertEquals( 4015 "Extra calls made to MockWebServer", 4016 0, 4017 impressionReportingSemaphore.availablePermits()); 4018 assertEquals( 4019 "Extra calls made to MockWebServer", 4020 0, 4021 interactionReportingSemaphore.availablePermits()); 4022 4023 mockWebServerRule.verifyMockServerRequests( 4024 server, 4025 10, 4026 ImmutableList.of( 4027 SELLER_DECISION_LOGIC_URI_PATH, 4028 BUYER_BIDDING_LOGIC_URI_PATH, 4029 BUYER_TRUSTED_SIGNAL_URI_PATH, 4030 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 4031 mRequestMatcherPrefixMatch); 4032 } 4033 4034 @Test testFledgeFlowFailsWithOnlyCANegativeBidsWithMockServer()4035 public void testFledgeFlowFailsWithOnlyCANegativeBidsWithMockServer() throws Exception { 4036 doReturn(AdServicesApiConsent.GIVEN) 4037 .when(mConsentManagerMock) 4038 .getConsent(AdServicesApiType.FLEDGE); 4039 doReturn(false) 4040 .when(mConsentManagerMock) 4041 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 4042 4043 setupAdSelectionConfig(); 4044 String decisionLogicJs = getDecisionLogicWithBeacons(); 4045 String biddingLogicJs = getBiddingLogicWithBeacons(); 4046 4047 CustomAudience customAudience1 = createCustomAudience(mLocalhostBuyerDomain, INVALID_BIDS); 4048 4049 MockWebServer server = 4050 mockWebServerRule.startMockWebServer( 4051 request -> { 4052 switch (request.getPath()) { 4053 case SELLER_DECISION_LOGIC_URI_PATH: 4054 return new MockResponse().setBody(decisionLogicJs); 4055 case BUYER_BIDDING_LOGIC_URI_PATH: 4056 return new MockResponse().setBody(biddingLogicJs); 4057 } 4058 4059 // The seller params vary based on runtime, so we are returning trusted 4060 // signals based on correct path prefix 4061 if (request.getPath() 4062 .startsWith( 4063 SELLER_TRUSTED_SIGNAL_URI_PATH 4064 + SELLER_TRUSTED_SIGNAL_PARAMS)) { 4065 return new MockResponse() 4066 .setBody(TRUSTED_SCORING_SIGNALS.toString()); 4067 } 4068 if (request.getPath().startsWith(BUYER_TRUSTED_SIGNAL_URI_PATH)) { 4069 return new MockResponse() 4070 .setBody(TRUSTED_BIDDING_SIGNALS.toString()); 4071 } 4072 return new MockResponse().setResponseCode(404); 4073 }); 4074 4075 // Join custom audience 4076 joinCustomAudienceAndAssertSuccess(customAudience1); 4077 4078 // Run Ad Selection 4079 AdSelectionTestCallback resultsCallback = 4080 invokeRunAdSelection( 4081 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 4082 4083 assertFalse(resultsCallback.mIsSuccess); 4084 assertNull(resultsCallback.mAdSelectionResponse); 4085 4086 // Run Report Impression with random ad selection id 4087 ReportImpressionInput input = 4088 new ReportImpressionInput.Builder() 4089 .setAdSelectionConfig(mAdSelectionConfig) 4090 .setAdSelectionId(1) 4091 .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME) 4092 .build(); 4093 4094 ReportImpressionTestCallback reportImpressionTestCallback = 4095 callReportImpression(mAdSelectionService, input); 4096 4097 assertFalse(reportImpressionTestCallback.mIsSuccess); 4098 4099 // Run Report Interaction with random ad selection id 4100 ReportInteractionInput reportInteractionInput = 4101 new ReportInteractionInput.Builder() 4102 .setAdSelectionId(1) 4103 .setInteractionKey(CLICK_INTERACTION) 4104 .setInteractionData(INTERACTION_DATA) 4105 .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME) 4106 .setReportingDestinations(BUYER_DESTINATION | SELLER_DESTINATION) 4107 .build(); 4108 4109 ReportInteractionTestCallback reportInteractionTestCallback = 4110 callReportInteraction(mAdSelectionService, reportInteractionInput); 4111 assertFalse(reportInteractionTestCallback.mIsSuccess); 4112 4113 mockWebServerRule.verifyMockServerRequests( 4114 server, 4115 2, 4116 ImmutableList.of(BUYER_BIDDING_LOGIC_URI_PATH, BUYER_TRUSTED_SIGNAL_URI_PATH), 4117 mRequestMatcherPrefixMatch); 4118 } 4119 4120 @Test testSelectAdsWithFilterExceptionFromNullPointerExceptionDoesNotCrash()4121 public void testSelectAdsWithFilterExceptionFromNullPointerExceptionDoesNotCrash() 4122 throws Exception { 4123 initClients(false, false, false, false, false, false); 4124 setupConsentGivenStubs(); 4125 setupAdSelectionConfig(); 4126 4127 doThrow(new FilterException(new NullPointerException("Intentional test failure"))) 4128 .when(mAdSelectionServiceFilterMock) 4129 .filterRequest( 4130 any(), 4131 anyString(), 4132 anyBoolean(), 4133 anyBoolean(), 4134 anyInt(), 4135 anyInt(), 4136 any(), 4137 any()); 4138 4139 // Run Ad Selection 4140 AdSelectionTestCallback resultsCallback = 4141 invokeRunAdSelection( 4142 mAdSelectionService, mAdSelectionConfig, CommonFixture.TEST_PACKAGE_NAME); 4143 4144 assertWithMessage("Callback success").that(resultsCallback.mIsSuccess).isFalse(); 4145 assertWithMessage("Callback AdSelectionResponse") 4146 .that(resultsCallback.mAdSelectionResponse) 4147 .isNull(); 4148 assertWithMessage("Callback FledgeErrorResponse") 4149 .that(resultsCallback.mFledgeErrorResponse) 4150 .isNotNull(); 4151 assertWithMessage("Callback FledgeErrorResponse") 4152 .that(resultsCallback.mFledgeErrorResponse.getStatusCode()) 4153 .isEqualTo(AdServicesStatusUtils.STATUS_INTERNAL_ERROR); 4154 } 4155 updateHistogramAndAssertSuccess(long adSelectionId, int adEventType)4156 private void updateHistogramAndAssertSuccess(long adSelectionId, int adEventType) 4157 throws InterruptedException { 4158 updateHistogramAndAssertSuccess( 4159 adSelectionId, adEventType, CommonFixture.TEST_PACKAGE_NAME); 4160 } 4161 updateHistogramAndAssertSuccess( long adSelectionId, int adEventType, String callerAppPackageName)4162 private void updateHistogramAndAssertSuccess( 4163 long adSelectionId, int adEventType, String callerAppPackageName) 4164 throws InterruptedException { 4165 UpdateAdCounterHistogramInput inputParams = 4166 new UpdateAdCounterHistogramInput.Builder( 4167 adSelectionId, 4168 adEventType, 4169 AdTechIdentifier.fromString(mLocalhostBuyerDomain.getHost()), 4170 callerAppPackageName) 4171 .build(); 4172 CountDownLatch callbackLatch = new CountDownLatch(1); 4173 UpdateAdCounterHistogramWorkerTest.UpdateAdCounterHistogramTestCallback callback = 4174 new UpdateAdCounterHistogramWorkerTest.UpdateAdCounterHistogramTestCallback( 4175 callbackLatch); 4176 4177 mAdSelectionService.updateAdCounterHistogram(inputParams, callback); 4178 4179 assertThat(callbackLatch.await(5, TimeUnit.SECONDS)).isTrue(); 4180 4181 assertWithMessage("Callback failed, was: %s", callback).that(callback.isSuccess()).isTrue(); 4182 } 4183 selectAdsAndReport( Uri winningRenderUri, Semaphore impressionReportingSemaphore, Semaphore interactionReportingSemaphore)4184 private long selectAdsAndReport( 4185 Uri winningRenderUri, 4186 Semaphore impressionReportingSemaphore, 4187 Semaphore interactionReportingSemaphore) 4188 throws Exception { 4189 return selectAdsAndReport( 4190 winningRenderUri, 4191 impressionReportingSemaphore, 4192 interactionReportingSemaphore, 4193 CommonFixture.TEST_PACKAGE_NAME); 4194 } 4195 selectAdsAndReport( Uri winningRenderUri, Semaphore impressionReportingSemaphore, Semaphore interactionReportingSemaphore, String callerAppPackageName)4196 private long selectAdsAndReport( 4197 Uri winningRenderUri, 4198 Semaphore impressionReportingSemaphore, 4199 Semaphore interactionReportingSemaphore, 4200 String callerAppPackageName) 4201 throws Exception { 4202 AdSelectionTestCallback resultsCallback = 4203 invokeRunAdSelection(mAdSelectionService, mAdSelectionConfig, callerAppPackageName); 4204 4205 assertTrue(resultsCallback.mIsSuccess); 4206 long resultSelectionId = resultsCallback.mAdSelectionResponse.getAdSelectionId(); 4207 assertTrue(mAdSelectionEntryDao.doesAdSelectionIdExist(resultSelectionId)); 4208 assertEquals(winningRenderUri, resultsCallback.mAdSelectionResponse.getRenderUri()); 4209 4210 reportImpressionAndAssertSuccess(resultSelectionId, callerAppPackageName); 4211 reportInteractionAndAssertSuccess(resultsCallback, callerAppPackageName); 4212 4213 /* We add a permit on every call received by the MockWebServer and remove them in the 4214 * tryAcquires below. If there are any left over it means that there were extra calls to the 4215 * mockserver. 4216 */ 4217 assertTrue(impressionReportingSemaphore.tryAcquire(2, 10, TimeUnit.SECONDS)); 4218 assertTrue(interactionReportingSemaphore.tryAcquire(2, 10, TimeUnit.SECONDS)); 4219 assertEquals( 4220 "Extra calls made to MockWebServer", 4221 0, 4222 impressionReportingSemaphore.availablePermits()); 4223 assertEquals( 4224 "Extra calls made to MockWebServer", 4225 0, 4226 interactionReportingSemaphore.availablePermits()); 4227 return resultSelectionId; 4228 } 4229 verifyStandardServerRequests(MockWebServer server)4230 void verifyStandardServerRequests(MockWebServer server) { 4231 /* 4232 * We expect ten requests: 4233 * 2 bidding logic requests (one for each CA) 4234 * 2 decision logic requests (scoring and reporting) 4235 * 1 trusted bidding signals requests 4236 * 1 trusted seller signals request 4237 * 1 reportWin 4238 * 1 reportResult 4239 * 1 buyer click interaction report 4240 * 1 seller click interaction report 4241 */ 4242 mockWebServerRule.verifyMockServerRequests( 4243 server, 4244 10, 4245 ImmutableList.of( 4246 SELLER_DECISION_LOGIC_URI_PATH, 4247 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 4248 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 4249 BUYER_TRUSTED_SIGNAL_URI_PATH, 4250 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 4251 mRequestMatcherPrefixMatch); 4252 } 4253 registerForAppInstallFiltering()4254 private void registerForAppInstallFiltering() throws RemoteException, InterruptedException { 4255 setAppInstallAdvertisers( 4256 Collections.singleton( 4257 AdTechIdentifier.fromString(mLocalhostBuyerDomain.getHost()))); 4258 } 4259 deregisterForAppInstallFiltering()4260 private void deregisterForAppInstallFiltering() throws RemoteException, InterruptedException { 4261 setAppInstallAdvertisers(Collections.EMPTY_SET); 4262 } 4263 setAppInstallAdvertisers(Set<AdTechIdentifier> advertisers)4264 private void setAppInstallAdvertisers(Set<AdTechIdentifier> advertisers) 4265 throws RemoteException, InterruptedException { 4266 SetAppInstallAdvertisersInput setAppInstallAdvertisersInput = 4267 new SetAppInstallAdvertisersInput.Builder() 4268 .setAdvertisers(advertisers) 4269 .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME) 4270 .build(); 4271 AppInstallResultCapturingCallback appInstallCallback = 4272 invokeSetAppInstallAdvertisers(setAppInstallAdvertisersInput); 4273 assertTrue( 4274 "App Install call failed with: " + appInstallCallback.getException(), 4275 appInstallCallback.isSuccess()); 4276 } 4277 invokeSetAppInstallAdvertisers()4278 private AppInstallResultCapturingCallback invokeSetAppInstallAdvertisers() 4279 throws RemoteException, InterruptedException { 4280 Set<AdTechIdentifier> advertisers = 4281 Collections.singleton(AdTechIdentifier.fromString(mLocalhostBuyerDomain.getHost())); 4282 SetAppInstallAdvertisersInput setAppInstallAdvertisersInput = 4283 new SetAppInstallAdvertisersInput.Builder() 4284 .setAdvertisers(advertisers) 4285 .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME) 4286 .build(); 4287 return invokeSetAppInstallAdvertisers(setAppInstallAdvertisersInput); 4288 } 4289 invokeSetAppInstallAdvertisers( SetAppInstallAdvertisersInput input)4290 private AppInstallResultCapturingCallback invokeSetAppInstallAdvertisers( 4291 SetAppInstallAdvertisersInput input) throws RemoteException, InterruptedException { 4292 CountDownLatch appInstallDone = new CountDownLatch(1); 4293 AppInstallResultCapturingCallback appInstallCallback = 4294 new AppInstallResultCapturingCallback(appInstallDone); 4295 mAdSelectionService.setAppInstallAdvertisers(input, appInstallCallback); 4296 assertTrue(appInstallDone.await(5, TimeUnit.SECONDS)); 4297 return appInstallCallback; 4298 } 4299 getV3BiddingLogicJs()4300 private String getV3BiddingLogicJs() { 4301 return "function generateBid(custom_audience, auction_signals, per_buyer_signals,\n" 4302 + " trusted_bidding_signals, contextual_signals) {\n" 4303 + " const ads = custom_audience.ads;\n" 4304 + " let result = null;\n" 4305 + " for (const ad of ads) {\n" 4306 + " if (!result || ad.metadata.result > result.metadata.result) {\n" 4307 + " result = ad;\n" 4308 + " }\n" 4309 + " }\n" 4310 + " return { 'status': 0, 'ad': result, 'bid': result.metadata.result, " 4311 + "'render': result.render_uri };\n" 4312 + "}\n" 4313 + "function reportWin(ad_selection_signals, per_buyer_signals," 4314 + " signals_for_buyer ,contextual_signals, custom_audience_signals) {\n" 4315 + "const beacons = {'click': '" 4316 + mockWebServerRule.uriForPath(CLICK_BUYER_PATH) 4317 + "', 'hover': '" 4318 + mockWebServerRule.uriForPath(HOVER_BUYER_PATH) 4319 + "'};\n" 4320 + "registerAdBeacon(beacons);" 4321 + " return {'status': 0, 'results': {'reporting_uri': '" 4322 + mockWebServerRule.uriForPath(BUYER_REPORTING_PATH) 4323 + "' } };\n" 4324 + "}"; 4325 } 4326 getBiddingLogicJs()4327 private String getBiddingLogicJs() { 4328 return "function generateBid(ad, auction_signals, per_buyer_signals," 4329 + " trusted_bidding_signals, contextual_signals, custom_audience_signals) { \n" 4330 + " return {'status': 0, 'ad': ad, 'bid': ad.metadata.result };\n" 4331 + "}\n" 4332 + "function reportWin(ad_selection_signals, per_buyer_signals," 4333 + " signals_for_buyer, contextual_signals, custom_audience_signals) { \n" 4334 + " return {'status': 0, 'results': {'reporting_uri': '" 4335 + mockWebServerRule.uriForPath(BUYER_REPORTING_PATH) 4336 + "' } };\n" 4337 + "}"; 4338 } 4339 getBiddingLogicJsWithAdCost()4340 private String getBiddingLogicJsWithAdCost() { 4341 return "function generateBid(ad, auction_signals, per_buyer_signals," 4342 + " trusted_bidding_signals, contextual_signals, custom_audience_signals) { \n" 4343 + " return {'status': 0, 'ad': ad, 'bid': ad.metadata.result, 'adCost':" 4344 + " ad.metadata.adCost };\n" 4345 + "}\n" 4346 + "\n" 4347 + "function reportWin(ad_selection_signals, per_buyer_signals," 4348 + " signals_for_buyer,\n" 4349 + " contextual_signals, custom_audience_reporting_signals) {\n" 4350 + " let reporting_address = '" 4351 + mockWebServerRule.uriForPath(BUYER_REPORTING_PATH) 4352 + "';\n" 4353 + " return {'status': 0, 'results': {'reporting_uri':\n" 4354 + " reporting_address + '?adCost=' + contextual_signals.adCost} };\n" 4355 + "}"; 4356 } 4357 getDecisionLogicJs()4358 private String getDecisionLogicJs() { 4359 return "function scoreAd(ad, bid, auction_config, seller_signals," 4360 + " trusted_scoring_signals, contextual_signal, user_signal," 4361 + " custom_audience_signal) { \n" 4362 + " return {'status': 0, 'score': bid };\n" 4363 + "}\n" 4364 + "function reportResult(ad_selection_config, render_uri, bid," 4365 + " contextual_signals) { \n" 4366 + " return {'status': 0, 'results': {'signals_for_buyer':" 4367 + " '{\"signals_for_buyer\":1}', 'reporting_uri': '" 4368 + mockWebServerRule.uriForPath(SELLER_REPORTING_PATH) 4369 + "' } };\n" 4370 + "}"; 4371 } 4372 getDecisionLogicJsWithDebugReporting(String reportWinUrl, String reportLossUrl)4373 private String getDecisionLogicJsWithDebugReporting(String reportWinUrl, String reportLossUrl) { 4374 return "function scoreAd(ad, bid, auction_config, seller_signals," 4375 + " trusted_scoring_signals, contextual_signal, user_signal," 4376 + " custom_audience_signal) { \n" 4377 + " forDebuggingOnly.reportAdAuctionWin('" 4378 + reportWinUrl 4379 + "');" 4380 + " forDebuggingOnly.reportAdAuctionLoss('" 4381 + reportLossUrl 4382 + "');" 4383 + " return {'status': 0, 'score': bid };\n" 4384 + "}"; 4385 } 4386 getBiddingLogicWithBeacons()4387 private String getBiddingLogicWithBeacons() { 4388 return "function generateBid(ad, auction_signals, per_buyer_signals," 4389 + " trusted_bidding_signals, contextual_signals, custom_audience_signals) { \n" 4390 + " return {'status': 0, 'ad': ad, 'bid': ad.metadata.result };\n" 4391 + "}\n" 4392 + "function reportWin(ad_selection_signals, per_buyer_signals," 4393 + " signals_for_buyer ,contextual_signals, custom_audience_signals) {\n" 4394 + "const beacons = {'click': '" 4395 + mockWebServerRule.uriForPath(CLICK_BUYER_PATH) 4396 + "', 'hover': '" 4397 + mockWebServerRule.uriForPath(HOVER_BUYER_PATH) 4398 + "'};\n" 4399 + "registerAdBeacon(beacons);" 4400 + " return {'status': 0, 'results': {'reporting_uri': '" 4401 + mockWebServerRule.uriForPath(BUYER_REPORTING_PATH) 4402 + "' } };\n" 4403 + "}"; 4404 } 4405 getBiddingLogicWithDebugReporting(String reportWinUrl, String reportLossUrl)4406 private String getBiddingLogicWithDebugReporting(String reportWinUrl, String reportLossUrl) { 4407 return "function generateBid(custom_audience, auction_signals, per_buyer_signals,\n" 4408 + " trusted_bidding_signals, contextual_signals) {\n" 4409 + " const ads = custom_audience.ads;\n" 4410 + " let result = null;\n" 4411 + " for (const ad of ads) {\n" 4412 + " if (!result || ad.metadata.result > result.metadata.result) {\n" 4413 + " result = ad;\n" 4414 + " forDebuggingOnly.reportAdAuctionWin('" 4415 + reportWinUrl 4416 + "');" 4417 + " forDebuggingOnly.reportAdAuctionLoss('" 4418 + reportLossUrl 4419 + "');" 4420 + " }\n" 4421 + " }\n" 4422 + " return { 'status': 0, 'ad': result, 'bid': result.metadata.result, " 4423 + "'render': result.render_uri };\n" 4424 + "}"; 4425 } 4426 getDecisionLogicWithBeacons()4427 private String getDecisionLogicWithBeacons() { 4428 return "function scoreAd(ad, bid, auction_config, seller_signals," 4429 + " trusted_scoring_signals, contextual_signal, user_signal," 4430 + " custom_audience_signal) { \n" 4431 + " return {'status': 0, 'score': bid };\n" 4432 + "}\n" 4433 + "function reportResult(ad_selection_config, render_uri, bid," 4434 + " contextual_signals) {\n" 4435 + "const beacons = {'click': '" 4436 + mockWebServerRule.uriForPath(CLICK_SELLER_PATH) 4437 + "', 'hover': '" 4438 + mockWebServerRule.uriForPath(HOVER_SELLER_PATH) 4439 + "'};\n" 4440 + "registerAdBeacon(beacons);" 4441 + " return {'status': 0, 'results': {'signals_for_buyer':" 4442 + " '{\"signals_for_buyer\":1}', 'reporting_uri': '" 4443 + mockWebServerRule.uriForPath(SELLER_REPORTING_PATH) 4444 + "' } };\n" 4445 + "}"; 4446 } 4447 getBiddingLogicWithBeaconsWithAdCost()4448 private String getBiddingLogicWithBeaconsWithAdCost() { 4449 return "function generateBid(ad, auction_signals, per_buyer_signals," 4450 + " trusted_bidding_signals, contextual_signals, custom_audience_signals) { \n" 4451 + " return {'status': 0, 'ad': ad, 'bid': ad.metadata.result, 'adCost':" 4452 + " ad.metadata.adCost };\n" 4453 + "}\n" 4454 + "function reportWin(ad_selection_signals, per_buyer_signals," 4455 + " signals_for_buyer, contextual_signals, custom_audience_signals) {\n" 4456 + "const beacons = {'click': '" 4457 + mockWebServerRule.uriForPath(CLICK_BUYER_PATH) 4458 + "', 'hover': '" 4459 + mockWebServerRule.uriForPath(HOVER_BUYER_PATH) 4460 + "'};\n" 4461 + "registerAdBeacon(beacons);" 4462 + " let reporting_address = '" 4463 + mockWebServerRule.uriForPath(BUYER_REPORTING_PATH) 4464 + "';\n" 4465 + " return {'status': 0, 'results': {'reporting_uri':\n" 4466 + " reporting_address + '?adCost=' + contextual_signals.adCost} };\n" 4467 + "}"; 4468 } 4469 getBiddingLogicWithDataVersion()4470 private String getBiddingLogicWithDataVersion() { 4471 return "function generateBid(ad, auction_signals, per_buyer_signals," 4472 + " trusted_bidding_signals, contextual_signals, custom_audience_signals) { \n" 4473 + " return {'status': 0, 'ad': ad, 'bid': ad.metadata.result, 'adCost':" 4474 + " ad.metadata.adCost };\n" 4475 + "}\n" 4476 + "function reportWin(ad_selection_signals, per_buyer_signals," 4477 + " signals_for_buyer, contextual_signals, custom_audience_signals) {\n" 4478 + " let reporting_address = '" 4479 + mockWebServerRule.uriForPath(BUYER_REPORTING_PATH) 4480 + "';\n" 4481 + " return {'status': 0, 'results': {'reporting_uri':\n" 4482 + " reporting_address + '?dataVersion=' +" 4483 + " contextual_signals.dataVersion} };\n" 4484 + "}"; 4485 } 4486 getDecisionLogicWithDataVersion()4487 private String getDecisionLogicWithDataVersion() { 4488 return "function scoreAd(ad, bid, auction_config, seller_signals," 4489 + " trusted_scoring_signals, contextual_signal, user_signal," 4490 + " custom_audience_signal) { \n" 4491 + " return {'status': 0, 'score': bid };\n" 4492 + "}\n" 4493 + "function reportResult(ad_selection_config, render_uri, bid," 4494 + " contextual_signals) {\n" 4495 + " let reporting_address = '" 4496 + mockWebServerRule.uriForPath(SELLER_REPORTING_PATH) 4497 + "';\n" 4498 + " return {'status': 0, 'results': {'signals_for_buyer':" 4499 + " '{\"signals_for_buyer\":1}', 'reporting_uri':\n" 4500 + " reporting_address + '?dataVersion=' +" 4501 + " contextual_signals.dataVersion} };\n" 4502 + "}"; 4503 } 4504 getMockWebServer( String decisionLogicJs, String biddingLogicJs, Semaphore impressionReportingSemaphore, Semaphore interactionReportingSemaphore, boolean jsVersioning)4505 private MockWebServer getMockWebServer( 4506 String decisionLogicJs, 4507 String biddingLogicJs, 4508 Semaphore impressionReportingSemaphore, 4509 Semaphore interactionReportingSemaphore, 4510 boolean jsVersioning) 4511 throws Exception { 4512 return getMockWebServer( 4513 new HashMap<>(), 4514 decisionLogicJs, 4515 biddingLogicJs, 4516 impressionReportingSemaphore, 4517 interactionReportingSemaphore, 4518 null, 4519 jsVersioning); 4520 } 4521 getMockWebServer( String decisionLogicJs, String biddingLogicJs, CountDownLatch debugReportingLatch)4522 private MockWebServer getMockWebServer( 4523 String decisionLogicJs, String biddingLogicJs, CountDownLatch debugReportingLatch) 4524 throws Exception { 4525 return getMockWebServer( 4526 new HashMap<>(), 4527 decisionLogicJs, 4528 biddingLogicJs, 4529 null, 4530 null, 4531 debugReportingLatch, 4532 true); 4533 } 4534 getMockWebServer( HashMap<String, String> remoteCustomAudiencesMap, String decisionLogicJs, String biddingLogicJs, Semaphore impressionReportingSemaphore, Semaphore interactionReportingSemaphore, CountDownLatch debugReportingLatch, boolean jsVersioning)4535 private MockWebServer getMockWebServer( 4536 HashMap<String, String> remoteCustomAudiencesMap, 4537 String decisionLogicJs, 4538 String biddingLogicJs, 4539 Semaphore impressionReportingSemaphore, 4540 Semaphore interactionReportingSemaphore, 4541 CountDownLatch debugReportingLatch, 4542 boolean jsVersioning) 4543 throws Exception { 4544 String versionHeaderName = 4545 JsVersionHelper.getVersionHeaderName( 4546 JsVersionHelper.JS_PAYLOAD_TYPE_BUYER_BIDDING_LOGIC_JS); 4547 long jsVersion = JsVersionRegister.BUYER_BIDDING_LOGIC_VERSION_VERSION_3; 4548 return mockWebServerRule.startMockWebServer( 4549 request -> { 4550 String requestPath = request.getPath(); 4551 switch (requestPath) { 4552 case SELLER_DECISION_LOGIC_URI_PATH: 4553 return new MockResponse().setBody(decisionLogicJs); 4554 case BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1: 4555 case BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2: 4556 if (jsVersioning) { 4557 if (Objects.equals( 4558 request.getHeader(versionHeaderName), 4559 Long.toString(jsVersion))) { 4560 return new MockResponse() 4561 .setBody(biddingLogicJs) 4562 .setHeader(versionHeaderName, jsVersion); 4563 } 4564 break; 4565 } else { 4566 return new MockResponse().setBody(biddingLogicJs); 4567 } 4568 case BUYER_DEBUG_REPORT_WIN_PATH + DEBUG_REPORT_WINNING_BID_RESPONSE: 4569 case BUYER_DEBUG_REPORT_LOSS_PATH + DEBUG_REPORT_WINNING_BID_RESPONSE: 4570 case SELLER_DEBUG_REPORT_WIN_PATH + DEBUG_REPORT_WINNING_BID_RESPONSE: 4571 case SELLER_DEBUG_REPORT_LOSS_PATH + DEBUG_REPORT_WINNING_BID_RESPONSE: 4572 if (Objects.nonNull(debugReportingLatch)) { 4573 debugReportingLatch.countDown(); 4574 } 4575 return new MockResponse().setResponseCode(200); 4576 case CLICK_SELLER_PATH: // Intentional fallthrough 4577 case CLICK_BUYER_PATH: 4578 interactionReportingSemaphore.release(); 4579 return new MockResponse().setResponseCode(200); 4580 case SELLER_REPORTING_PATH: // Intentional fallthrough 4581 case BUYER_REPORTING_PATH: 4582 impressionReportingSemaphore.release(); 4583 return new MockResponse().setResponseCode(200); 4584 } 4585 4586 if (requestPath.contains(FETCH_CA_PATH)) { 4587 String[] pathSegments = requestPath.split("/"); 4588 String customAudienceId = pathSegments[pathSegments.length - 1]; 4589 if (remoteCustomAudiencesMap.containsKey(customAudienceId)) { 4590 return new MockResponse() 4591 .setBody(remoteCustomAudiencesMap.get(customAudienceId)); 4592 } else { 4593 return new MockResponse().setResponseCode(404); 4594 } 4595 } 4596 4597 // Case where adCost / data version is reported in the Uri 4598 if (request.getPath().startsWith(BUYER_REPORTING_PATH)) { 4599 impressionReportingSemaphore.release(); 4600 return new MockResponse().setResponseCode(200); 4601 } 4602 4603 // Case where data version is reported in the Uri 4604 if (request.getPath().startsWith(SELLER_REPORTING_PATH)) { 4605 impressionReportingSemaphore.release(); 4606 return new MockResponse().setResponseCode(200); 4607 } 4608 4609 // The seller params vary based on runtime, so we are returning trusted 4610 // signals based on correct path prefix 4611 if (request.getPath() 4612 .startsWith( 4613 SELLER_TRUSTED_SIGNAL_URI_PATH 4614 + SELLER_TRUSTED_SIGNAL_PARAMS)) { 4615 return new MockResponse().setBody(TRUSTED_SCORING_SIGNALS.toString()); 4616 } 4617 4618 // Add seller trusted scoring uri path with data version header 4619 if (request.getPath() 4620 .startsWith( 4621 SELLER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION 4622 + SELLER_TRUSTED_SIGNAL_PARAMS)) { 4623 return new MockResponse() 4624 .setBody(TRUSTED_SCORING_SIGNALS.toString()) 4625 .addHeader(DATA_VERSION_HEADER_SCORING_KEY, DATA_VERSION_2); 4626 } 4627 4628 if (request.getPath().startsWith(BUYER_TRUSTED_SIGNAL_URI_PATH)) { 4629 return new MockResponse().setBody(TRUSTED_BIDDING_SIGNALS.toString()); 4630 } 4631 4632 // Add seller trusted scoring uri path with data version header 4633 if (request.getPath() 4634 .startsWith(BUYER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION)) { 4635 return new MockResponse() 4636 .setBody(TRUSTED_BIDDING_SIGNALS.toString()) 4637 .addHeader(DATA_VERSION_HEADER_BIDDING_KEY, DATA_VERSION_1); 4638 } 4639 return new MockResponse().setResponseCode(404); 4640 }); 4641 } 4642 reportInteractionAndAssertSuccess(AdSelectionTestCallback resultsCallback)4643 private void reportInteractionAndAssertSuccess(AdSelectionTestCallback resultsCallback) 4644 throws Exception { 4645 reportInteractionAndAssertSuccess(resultsCallback, CommonFixture.TEST_PACKAGE_NAME); 4646 } 4647 reportInteractionAndAssertSuccess( AdSelectionTestCallback resultsCallback, String callerAppPackageName)4648 private void reportInteractionAndAssertSuccess( 4649 AdSelectionTestCallback resultsCallback, String callerAppPackageName) throws Exception { 4650 ReportInteractionInput reportInteractionInput = 4651 new ReportInteractionInput.Builder() 4652 .setAdSelectionId(resultsCallback.mAdSelectionResponse.getAdSelectionId()) 4653 .setInteractionKey(CLICK_INTERACTION) 4654 .setInteractionData(INTERACTION_DATA) 4655 .setCallerPackageName(callerAppPackageName) 4656 .setReportingDestinations(BUYER_DESTINATION | SELLER_DESTINATION) 4657 .build(); 4658 4659 ReportInteractionTestCallback reportInteractionTestCallback = 4660 callReportInteraction(mAdSelectionService, reportInteractionInput); 4661 assertTrue(reportInteractionTestCallback.mIsSuccess); 4662 } 4663 reportOnlyBuyerInteractionAndAssertSuccess(AdSelectionTestCallback resultsCallback)4664 private void reportOnlyBuyerInteractionAndAssertSuccess(AdSelectionTestCallback resultsCallback) 4665 throws Exception { 4666 ReportInteractionInput reportInteractionInput = 4667 new ReportInteractionInput.Builder() 4668 .setAdSelectionId(resultsCallback.mAdSelectionResponse.getAdSelectionId()) 4669 .setInteractionKey(CLICK_INTERACTION) 4670 .setInteractionData(INTERACTION_DATA) 4671 .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME) 4672 .setReportingDestinations(BUYER_DESTINATION) 4673 .build(); 4674 4675 ReportInteractionTestCallback reportInteractionTestCallback = 4676 callReportInteraction(mAdSelectionService, reportInteractionInput); 4677 assertTrue(reportInteractionTestCallback.mIsSuccess); 4678 } 4679 reportImpressionAndAssertSuccess(long adSelectionId)4680 private void reportImpressionAndAssertSuccess(long adSelectionId) throws Exception { 4681 reportImpressionAndAssertSuccess(adSelectionId, CommonFixture.TEST_PACKAGE_NAME); 4682 } 4683 reportImpressionAndAssertSuccess(long adSelectionId, String callerAppPackageName)4684 private void reportImpressionAndAssertSuccess(long adSelectionId, String callerAppPackageName) 4685 throws Exception { 4686 ReportImpressionInput input = 4687 new ReportImpressionInput.Builder() 4688 .setAdSelectionConfig(mAdSelectionConfig) 4689 .setAdSelectionId(adSelectionId) 4690 .setCallerPackageName(callerAppPackageName) 4691 .build(); 4692 4693 ReportImpressionTestCallback reportImpressionTestCallback = 4694 callReportImpression(mAdSelectionService, input); 4695 4696 assertTrue(reportImpressionTestCallback.mIsSuccess); 4697 } 4698 setupOverridesAndAssertSuccess( CustomAudience customAudience1, CustomAudience customAudience2, String biddingLogicJs, String decisionLogicJs)4699 private void setupOverridesAndAssertSuccess( 4700 CustomAudience customAudience1, 4701 CustomAudience customAudience2, 4702 String biddingLogicJs, 4703 String decisionLogicJs) 4704 throws Exception { 4705 // Add AdSelection Override 4706 AdSelectionOverrideTestCallback adSelectionOverrideTestCallback = 4707 callAddAdSelectionOverride( 4708 mAdSelectionService, 4709 mAdSelectionConfig, 4710 decisionLogicJs, 4711 TRUSTED_SCORING_SIGNALS, 4712 BUYERS_DECISION_LOGIC); 4713 4714 assertTrue(adSelectionOverrideTestCallback.mIsSuccess); 4715 4716 // Add Custom Audience Overrides 4717 CustomAudienceOverrideTestCallback customAudienceOverrideTestCallback1 = 4718 callAddCustomAudienceOverride( 4719 CommonFixture.TEST_PACKAGE_NAME, 4720 customAudience1.getBuyer(), 4721 customAudience1.getName(), 4722 biddingLogicJs, 4723 null, 4724 TRUSTED_BIDDING_SIGNALS, 4725 mCustomAudienceService); 4726 4727 assertTrue(customAudienceOverrideTestCallback1.mIsSuccess); 4728 4729 CustomAudienceOverrideTestCallback customAudienceOverrideTestCallback2 = 4730 callAddCustomAudienceOverride( 4731 CommonFixture.TEST_PACKAGE_NAME, 4732 customAudience2.getBuyer(), 4733 customAudience2.getName(), 4734 biddingLogicJs, 4735 null, 4736 TRUSTED_BIDDING_SIGNALS, 4737 mCustomAudienceService); 4738 4739 assertTrue(customAudienceOverrideTestCallback2.mIsSuccess); 4740 } 4741 setupAdSelectionConfig()4742 private void setupAdSelectionConfig() { 4743 mAdSelectionConfig = 4744 AdSelectionConfigFixture.anAdSelectionConfigBuilder() 4745 .setCustomAudienceBuyers( 4746 ImmutableList.of( 4747 AdTechIdentifier.fromString( 4748 mLocalhostBuyerDomain.getHost()))) 4749 .setSeller( 4750 AdTechIdentifier.fromString( 4751 mockWebServerRule 4752 .uriForPath(SELLER_DECISION_LOGIC_URI_PATH) 4753 .getHost())) 4754 .setDecisionLogicUri( 4755 mockWebServerRule.uriForPath(SELLER_DECISION_LOGIC_URI_PATH)) 4756 .setTrustedScoringSignalsUri( 4757 mockWebServerRule.uriForPath(SELLER_TRUSTED_SIGNAL_URI_PATH)) 4758 .setPerBuyerSignals( 4759 ImmutableMap.of( 4760 AdTechIdentifier.fromString( 4761 mLocalhostBuyerDomain.getHost()), 4762 AdSelectionSignals.fromString("{\"buyer_signals\":0}"))) 4763 .build(); 4764 } 4765 setupAdSelectionConfigWithDataVersionHeader()4766 private void setupAdSelectionConfigWithDataVersionHeader() { 4767 mAdSelectionConfig = 4768 AdSelectionConfigFixture.anAdSelectionConfigBuilder() 4769 .setCustomAudienceBuyers( 4770 ImmutableList.of( 4771 AdTechIdentifier.fromString( 4772 mLocalhostBuyerDomain.getHost()))) 4773 .setSeller( 4774 AdTechIdentifier.fromString( 4775 mockWebServerRule 4776 .uriForPath(SELLER_DECISION_LOGIC_URI_PATH) 4777 .getHost())) 4778 .setDecisionLogicUri( 4779 mockWebServerRule.uriForPath(SELLER_DECISION_LOGIC_URI_PATH)) 4780 .setTrustedScoringSignalsUri( 4781 mockWebServerRule.uriForPath( 4782 SELLER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION)) 4783 .setPerBuyerSignals( 4784 ImmutableMap.of( 4785 AdTechIdentifier.fromString( 4786 mLocalhostBuyerDomain.getHost()), 4787 AdSelectionSignals.fromString("{\"buyer_signals\":0}"))) 4788 .build(); 4789 } 4790 setupConsentGivenStubs()4791 private void setupConsentGivenStubs() { 4792 doReturn(AdServicesApiConsent.GIVEN) 4793 .when(mConsentManagerMock) 4794 .getConsent(AdServicesApiType.FLEDGE); 4795 doReturn(false).when(mConsentManagerMock).isFledgeConsentRevokedForApp(any()); 4796 doReturn(false) 4797 .when(mConsentManagerMock) 4798 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 4799 } 4800 joinCustomAudienceAndAssertSuccess(CustomAudience ca)4801 private void joinCustomAudienceAndAssertSuccess(CustomAudience ca) { 4802 joinCustomAudienceAndAssertSuccess(ca, CommonFixture.TEST_PACKAGE_NAME); 4803 } 4804 joinCustomAudienceAndAssertSuccess( CustomAudience ca, String callerAppPackageName)4805 private void joinCustomAudienceAndAssertSuccess( 4806 CustomAudience ca, String callerAppPackageName) { 4807 ResultCapturingCallback joinCallback = new ResultCapturingCallback(); 4808 mCustomAudienceService.joinCustomAudience(ca, callerAppPackageName, joinCallback); 4809 assertTrue(joinCallback.isSuccess()); 4810 } 4811 fetchAndJoinCustomAudienceAndAssertSuccess(FetchAndJoinCustomAudienceInput request)4812 private void fetchAndJoinCustomAudienceAndAssertSuccess(FetchAndJoinCustomAudienceInput request) 4813 throws InterruptedException { 4814 CountDownLatch resultLatch = new CountDownLatch(1); 4815 FetchCustomAudienceTestCallback callback = new FetchCustomAudienceTestCallback(resultLatch); 4816 mCustomAudienceService.fetchAndJoinCustomAudience(request, callback); 4817 resultLatch.await(); 4818 assertTrue(callback.isSuccess()); 4819 } 4820 leaveCustomAudienceAndAssertSuccess( String callerAppPackageName, AdTechIdentifier buyer, String name)4821 private void leaveCustomAudienceAndAssertSuccess( 4822 String callerAppPackageName, AdTechIdentifier buyer, String name) { 4823 ResultCapturingCallback leaveCallback = new ResultCapturingCallback(); 4824 mCustomAudienceService.leaveCustomAudience( 4825 callerAppPackageName, buyer, name, leaveCallback); 4826 assertTrue(leaveCallback.isSuccess()); 4827 } 4828 initClients( boolean gaUXEnabled, boolean registerAdBeaconEnabled, boolean cpcBillingEnabled, boolean dataVersionHeaderEnabled, boolean shouldUseUnifiedTables, boolean auctionServerEnabledReportImpression)4829 private void initClients( 4830 boolean gaUXEnabled, 4831 boolean registerAdBeaconEnabled, 4832 boolean cpcBillingEnabled, 4833 boolean dataVersionHeaderEnabled, 4834 boolean shouldUseUnifiedTables, 4835 boolean auctionServerEnabledReportImpression) { 4836 initClients( 4837 gaUXEnabled, 4838 registerAdBeaconEnabled, 4839 true, 4840 true, 4841 true, 4842 cpcBillingEnabled, 4843 false, 4844 dataVersionHeaderEnabled, 4845 false, 4846 false, 4847 shouldUseUnifiedTables, 4848 auctionServerEnabledReportImpression); 4849 } 4850 initClients( boolean gaUXEnabled, boolean registerAdBeaconEnabled, boolean frequencyCapFilteringEnabled, boolean appInstallFilteringEnabled, boolean enrollmentCheckDisabled, boolean cpcBillingEnabled, boolean debugReportingEnabled, boolean dataVersionHeaderEnabled, boolean debugReportSendImmediately, boolean adIdKillSwitch, boolean shouldUseUnifiedTables, boolean auctionServerEnabledReportImpression)4851 private void initClients( 4852 boolean gaUXEnabled, 4853 boolean registerAdBeaconEnabled, 4854 boolean frequencyCapFilteringEnabled, 4855 boolean appInstallFilteringEnabled, 4856 boolean enrollmentCheckDisabled, 4857 boolean cpcBillingEnabled, 4858 boolean debugReportingEnabled, 4859 boolean dataVersionHeaderEnabled, 4860 boolean debugReportSendImmediately, 4861 boolean adIdKillSwitch, 4862 boolean shouldUseUnifiedTables, 4863 boolean auctionServerEnabledReportImpression) { 4864 Flags flags = 4865 new FledgeE2ETestFlags( 4866 gaUXEnabled, 4867 registerAdBeaconEnabled, 4868 frequencyCapFilteringEnabled, 4869 appInstallFilteringEnabled, 4870 enrollmentCheckDisabled, 4871 cpcBillingEnabled, 4872 debugReportingEnabled, 4873 dataVersionHeaderEnabled, 4874 debugReportSendImmediately, 4875 adIdKillSwitch, 4876 shouldUseUnifiedTables, 4877 false); 4878 4879 mCustomAudienceService = 4880 new CustomAudienceServiceImpl( 4881 mSpyContext, 4882 new CustomAudienceImpl( 4883 mCustomAudienceDao, 4884 new CustomAudienceQuantityChecker(mCustomAudienceDao, flags), 4885 new CustomAudienceValidator( 4886 CommonFixture.FIXED_CLOCK_TRUNCATED_TO_MILLI, 4887 flags, 4888 flags.getFledgeFrequencyCapFilteringEnabled() 4889 ? new FrequencyCapAdDataValidatorImpl() 4890 : new FrequencyCapAdDataValidatorNoOpImpl(), 4891 AdRenderIdValidator.createInstance(flags)), 4892 CommonFixture.FIXED_CLOCK_TRUNCATED_TO_MILLI, 4893 flags), 4894 mFledgeAuthorizationFilterMock, 4895 mConsentManagerMock, 4896 mDevContextFilterMock, 4897 MoreExecutors.newDirectExecutorService(), 4898 mAdServicesLoggerMock, 4899 mAppImportanceFilterMock, 4900 flags, 4901 CallingAppUidSupplierProcessImpl.create(), 4902 new CustomAudienceServiceFilter( 4903 mSpyContext, 4904 mFledgeConsentFilterMock, 4905 flags, 4906 mAppImportanceFilterMock, 4907 mFledgeAuthorizationFilterMock, 4908 mFledgeAllowListsFilterSpy, 4909 mFledgeApiThrottleFilterMock), 4910 new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDao, flags)); 4911 4912 when(mDevContextFilterMock.createDevContext()) 4913 .thenReturn(DevContext.createForDevOptionsDisabled()); 4914 mAdFilteringFeatureFactory = 4915 new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDao, flags); 4916 mAdIdFetcher = 4917 new AdIdFetcher( 4918 mSpyContext, 4919 mMockAdIdWorker, 4920 mLightweightExecutorService, 4921 mScheduledExecutor); 4922 // Create an instance of AdSelection Service with real dependencies 4923 mAdSelectionService = 4924 new AdSelectionServiceImpl( 4925 mAdSelectionEntryDao, 4926 mAppInstallDao, 4927 mCustomAudienceDao, 4928 mEncodedPayloadDao, 4929 mFrequencyCapDao, 4930 mEncryptionKeyDao, 4931 mEnrollmentDao, 4932 mAdServicesHttpsClient, 4933 mDevContextFilterMock, 4934 mLightweightExecutorService, 4935 mBackgroundExecutorService, 4936 mScheduledExecutor, 4937 mSpyContext, 4938 mAdServicesLoggerMock, 4939 flags, 4940 CallingAppUidSupplierProcessImpl.create(), 4941 mFledgeAuthorizationFilterMock, 4942 mAdSelectionServiceFilterMock, 4943 mAdFilteringFeatureFactory, 4944 mConsentManagerMock, 4945 mMultiCloudSupportStrategy, 4946 mAdSelectionDebugReportDao, 4947 mAdIdFetcher, 4948 mUnusedKAnonSignJoinFactory, 4949 false, 4950 mRetryStrategyFactory, 4951 mConsentedDebugConfigurationGeneratorFactory, 4952 mEgressConfigurationGenerator, 4953 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 4954 } 4955 invokeRunAdSelection( AdSelectionServiceImpl adSelectionService, AdSelectionConfig adSelectionConfig, String callerPackageName)4956 private AdSelectionTestCallback invokeRunAdSelection( 4957 AdSelectionServiceImpl adSelectionService, 4958 AdSelectionConfig adSelectionConfig, 4959 String callerPackageName) 4960 throws InterruptedException { 4961 4962 CountDownLatch countdownLatch = new CountDownLatch(1); 4963 AdSelectionTestCallback adSelectionTestCallback = 4964 new AdSelectionTestCallback(countdownLatch); 4965 4966 AdSelectionInput input = 4967 new AdSelectionInput.Builder() 4968 .setAdSelectionConfig(adSelectionConfig) 4969 .setCallerPackageName(callerPackageName) 4970 .build(); 4971 CallerMetadata callerMetadata = 4972 new CallerMetadata.Builder() 4973 .setBinderElapsedTimestamp(BINDER_ELAPSED_TIMESTAMP) 4974 .build(); 4975 adSelectionService.selectAds(input, callerMetadata, adSelectionTestCallback); 4976 adSelectionTestCallback.mCountDownLatch.await(); 4977 return adSelectionTestCallback; 4978 } 4979 invokeRunAdSelectionAndWaitForFullCallback( AdSelectionServiceImpl adSelectionService, AdSelectionConfig adSelectionConfig, String callerPackageName)4980 private AdSelectionTestCallback invokeRunAdSelectionAndWaitForFullCallback( 4981 AdSelectionServiceImpl adSelectionService, 4982 AdSelectionConfig adSelectionConfig, 4983 String callerPackageName) 4984 throws InterruptedException { 4985 4986 CountDownLatch countdownLatch = new CountDownLatch(1); 4987 AdSelectionTestCallback adSelectionTestCallback = 4988 new AdSelectionTestCallback(countdownLatch); 4989 CountDownLatch countdownLatchForFullCallback = new CountDownLatch(1); 4990 AdSelectionTestCallback adSelectionTestFullCallback = 4991 new AdSelectionTestCallback(countdownLatchForFullCallback); 4992 4993 AdSelectionInput input = 4994 new AdSelectionInput.Builder() 4995 .setAdSelectionConfig(adSelectionConfig) 4996 .setCallerPackageName(callerPackageName) 4997 .build(); 4998 CallerMetadata callerMetadata = 4999 new CallerMetadata.Builder() 5000 .setBinderElapsedTimestamp(BINDER_ELAPSED_TIMESTAMP) 5001 .build(); 5002 adSelectionService.selectAds( 5003 input, callerMetadata, adSelectionTestCallback, adSelectionTestFullCallback); 5004 adSelectionTestCallback.mCountDownLatch.await(); 5005 adSelectionTestFullCallback.mCountDownLatch.await(); 5006 return adSelectionTestCallback; 5007 } 5008 callAddAdSelectionOverride( AdSelectionServiceImpl adSelectionService, AdSelectionConfig adSelectionConfig, String decisionLogicJS, AdSelectionSignals trustedScoringSignals, PerBuyerDecisionLogic buyerDecisionLogicMap)5009 private AdSelectionOverrideTestCallback callAddAdSelectionOverride( 5010 AdSelectionServiceImpl adSelectionService, 5011 AdSelectionConfig adSelectionConfig, 5012 String decisionLogicJS, 5013 AdSelectionSignals trustedScoringSignals, 5014 PerBuyerDecisionLogic buyerDecisionLogicMap) 5015 throws Exception { 5016 // Counted down in 1) callback 5017 CountDownLatch resultLatch = new CountDownLatch(1); 5018 AdSelectionOverrideTestCallback callback = new AdSelectionOverrideTestCallback(resultLatch); 5019 5020 adSelectionService.overrideAdSelectionConfigRemoteInfo( 5021 adSelectionConfig, 5022 decisionLogicJS, 5023 trustedScoringSignals, 5024 buyerDecisionLogicMap, 5025 callback); 5026 resultLatch.await(); 5027 return callback; 5028 } 5029 callAddCustomAudienceOverride( String owner, AdTechIdentifier buyer, String name, String biddingLogicJs, Long biddingLogicJsVersion, AdSelectionSignals trustedBiddingData, CustomAudienceServiceImpl customAudienceService)5030 private CustomAudienceOverrideTestCallback callAddCustomAudienceOverride( 5031 String owner, 5032 AdTechIdentifier buyer, 5033 String name, 5034 String biddingLogicJs, 5035 Long biddingLogicJsVersion, 5036 AdSelectionSignals trustedBiddingData, 5037 CustomAudienceServiceImpl customAudienceService) 5038 throws Exception { 5039 CountDownLatch resultLatch = new CountDownLatch(1); 5040 CustomAudienceOverrideTestCallback callback = 5041 new CustomAudienceOverrideTestCallback(resultLatch); 5042 5043 customAudienceService.overrideCustomAudienceRemoteInfo( 5044 owner, 5045 buyer, 5046 name, 5047 biddingLogicJs, 5048 Optional.ofNullable(biddingLogicJsVersion).orElse(0L), 5049 trustedBiddingData, 5050 callback); 5051 resultLatch.await(); 5052 return callback; 5053 } 5054 callReportImpression( AdSelectionServiceImpl adSelectionService, ReportImpressionInput requestParams)5055 private ReportImpressionTestCallback callReportImpression( 5056 AdSelectionServiceImpl adSelectionService, ReportImpressionInput requestParams) 5057 throws Exception { 5058 // Counted down in 1) callback 5059 CountDownLatch resultLatch = new CountDownLatch(1); 5060 ReportImpressionTestCallback callback = new ReportImpressionTestCallback(resultLatch); 5061 5062 adSelectionService.reportImpression(requestParams, callback); 5063 resultLatch.await(); 5064 return callback; 5065 } 5066 callReportInteraction( AdSelectionServiceImpl adSelectionService, ReportInteractionInput inputParams)5067 private ReportInteractionTestCallback callReportInteraction( 5068 AdSelectionServiceImpl adSelectionService, ReportInteractionInput inputParams) 5069 throws Exception { 5070 // Counted down in 1) callback 5071 CountDownLatch resultLatch = new CountDownLatch(1); 5072 ReportInteractionTestCallback callback = new ReportInteractionTestCallback(resultLatch); 5073 5074 adSelectionService.reportInteraction(inputParams, callback); 5075 resultLatch.await(); 5076 return callback; 5077 } 5078 5079 /** See {@link #createCustomAudience(Uri, String, List)}. */ createCustomAudience(final Uri buyerDomain, List<Double> bids)5080 private CustomAudience createCustomAudience(final Uri buyerDomain, List<Double> bids) { 5081 return createCustomAudience(buyerDomain, "", bids); 5082 } 5083 createCustomAudience( final Uri buyerDomain, final String customAudienceSeq, List<Double> bids)5084 private CustomAudience createCustomAudience( 5085 final Uri buyerDomain, final String customAudienceSeq, List<Double> bids) { 5086 return createCustomAudience(buyerDomain, customAudienceSeq, bids, null, null, false); 5087 } 5088 createCustomAudienceWithDataVersion( final Uri buyerDomain, final String customAudienceSeq, List<Double> bids)5089 private CustomAudience createCustomAudienceWithDataVersion( 5090 final Uri buyerDomain, final String customAudienceSeq, List<Double> bids) { 5091 return createCustomAudience(buyerDomain, customAudienceSeq, bids, null, null, true); 5092 } 5093 createCustomAudienceWithAdCost( final Uri buyerDomain, final String customAudienceSeq, List<Double> bids, double adCost)5094 private CustomAudience createCustomAudienceWithAdCost( 5095 final Uri buyerDomain, 5096 final String customAudienceSeq, 5097 List<Double> bids, 5098 double adCost) { 5099 return createCustomAudienceWithAdCost( 5100 buyerDomain, customAudienceSeq, bids, null, null, adCost); 5101 } 5102 5103 /** 5104 * @param buyerDomain The name of the buyer for this Custom Audience 5105 * @param customAudienceSeq optional numbering for ca name. Should start with slash. 5106 * @param bids these bids, are added to its metadata. Our JS logic then picks this value and 5107 * creates ad with the provided value as bid 5108 * @param filtersForBids A parallel list to bids with the filter that should be added to each 5109 * Ad. Can be left null. 5110 * @param adCounterKeysForBids A parallel list to bids with the adCounterKeys that should be 5111 * added to each Ad. Can be left null. 5112 * @param withDataVersion Whether or not to fetch data version in trusted bidding signals 5113 * @return a real Custom Audience object that can be persisted and used in bidding and scoring 5114 */ createCustomAudience( final Uri buyerDomain, final String customAudienceSeq, List<Double> bids, List<Set<Integer>> adCounterKeysForBids, List<AdFilters> filtersForBids, boolean withDataVersion)5115 private CustomAudience createCustomAudience( 5116 final Uri buyerDomain, 5117 final String customAudienceSeq, 5118 List<Double> bids, 5119 List<Set<Integer>> adCounterKeysForBids, 5120 List<AdFilters> filtersForBids, 5121 boolean withDataVersion) { 5122 5123 // Generate ads for with bids provided 5124 List<AdData> ads = new ArrayList<>(); 5125 5126 // Create ads with the buyer name and bid number as the ad URI 5127 // Add the bid value to the metadata 5128 for (int i = 0; i < bids.size(); i++) { 5129 AdData.Builder builder = 5130 new AdData.Builder() 5131 .setRenderUri( 5132 CommonFixture.getUri( 5133 buyerDomain.getAuthority(), 5134 AD_URI_PREFIX + customAudienceSeq + "/ad" + (i + 1))) 5135 .setMetadata("{\"result\":" + bids.get(i) + "}"); 5136 if (adCounterKeysForBids != null && adCounterKeysForBids.get(i) != null) { 5137 builder.setAdCounterKeys(adCounterKeysForBids.get(i)); 5138 } 5139 if (filtersForBids != null) { 5140 builder.setAdFilters(filtersForBids.get(i)); 5141 } 5142 ads.add(builder.build()); 5143 } 5144 5145 String trustedBiddingUriPath; 5146 if (withDataVersion) { 5147 trustedBiddingUriPath = BUYER_TRUSTED_SIGNAL_URI_PATH_WITH_DATA_VERSION; 5148 } else { 5149 trustedBiddingUriPath = BUYER_TRUSTED_SIGNAL_URI_PATH; 5150 } 5151 5152 return new CustomAudience.Builder() 5153 .setBuyer(AdTechIdentifier.fromString(buyerDomain.getHost())) 5154 .setName( 5155 buyerDomain.getHost() 5156 + customAudienceSeq 5157 + CustomAudienceFixture.VALID_NAME) 5158 .setActivationTime(CustomAudienceFixture.VALID_ACTIVATION_TIME) 5159 .setExpirationTime(CustomAudienceFixture.VALID_EXPIRATION_TIME) 5160 .setDailyUpdateUri( 5161 CustomAudienceFixture.getValidDailyUpdateUriByBuyer( 5162 AdTechIdentifier.fromString(buyerDomain.getAuthority()))) 5163 .setUserBiddingSignals(CustomAudienceFixture.VALID_USER_BIDDING_SIGNALS) 5164 .setTrustedBiddingData( 5165 new TrustedBiddingData.Builder() 5166 .setTrustedBiddingUri( 5167 CommonFixture.getUri( 5168 buyerDomain.getAuthority(), trustedBiddingUriPath)) 5169 .setTrustedBiddingKeys( 5170 TrustedBiddingDataFixture.getValidTrustedBiddingKeys()) 5171 .build()) 5172 .setBiddingLogicUri( 5173 CommonFixture.getUri( 5174 buyerDomain.getAuthority(), 5175 BUYER_BIDDING_LOGIC_URI_PATH + customAudienceSeq)) 5176 .setAds(ads) 5177 .build(); 5178 } 5179 5180 /** 5181 * @param buyerDomain The name of the buyer for this Custom Audience 5182 * @param customAudienceSeq optional numbering for ca name. Should start with slash. 5183 * @param bids these bids, are added to its metadata. Our JS logic then picks this value and 5184 * creates ad with the provided value as bid 5185 * @param filtersForBids A parallel list to bids with the filter that should be added to each 5186 * Ad. Can be left null. 5187 * @param adCounterKeysForBids A parallel list to bids with the adCounterKeys that should be 5188 * added to each Ad. Can be left null. 5189 * @param adCost The cost to click on an ad 5190 * @return a real Custom Audience object that can be persisted and used in bidding and scoring 5191 */ createCustomAudienceWithAdCost( final Uri buyerDomain, final String customAudienceSeq, List<Double> bids, List<Set<Integer>> adCounterKeysForBids, List<AdFilters> filtersForBids, double adCost)5192 private CustomAudience createCustomAudienceWithAdCost( 5193 final Uri buyerDomain, 5194 final String customAudienceSeq, 5195 List<Double> bids, 5196 List<Set<Integer>> adCounterKeysForBids, 5197 List<AdFilters> filtersForBids, 5198 double adCost) { 5199 5200 // Generate ads for with bids provided 5201 List<AdData> ads = new ArrayList<>(); 5202 5203 // Create ads with the buyer name and bid number as the ad URI 5204 // Add the bid value to the metadata 5205 for (int i = 0; i < bids.size(); i++) { 5206 AdData.Builder builder = 5207 new AdData.Builder() 5208 .setRenderUri( 5209 CommonFixture.getUri( 5210 buyerDomain.getAuthority(), 5211 AD_URI_PREFIX + customAudienceSeq + "/ad" + (i + 1))) 5212 .setMetadata( 5213 "{\"result\":" + bids.get(i) + ",\"adCost\":" + adCost + "}"); 5214 if (adCounterKeysForBids != null && adCounterKeysForBids.get(i) != null) { 5215 builder.setAdCounterKeys(adCounterKeysForBids.get(i)); 5216 } 5217 if (filtersForBids != null) { 5218 builder.setAdFilters(filtersForBids.get(i)); 5219 } 5220 ads.add(builder.build()); 5221 } 5222 5223 return new CustomAudience.Builder() 5224 .setBuyer(AdTechIdentifier.fromString(buyerDomain.getHost())) 5225 .setName( 5226 buyerDomain.getHost() 5227 + customAudienceSeq 5228 + CustomAudienceFixture.VALID_NAME) 5229 .setActivationTime(CustomAudienceFixture.VALID_ACTIVATION_TIME) 5230 .setExpirationTime(CustomAudienceFixture.VALID_EXPIRATION_TIME) 5231 .setDailyUpdateUri( 5232 CustomAudienceFixture.getValidDailyUpdateUriByBuyer( 5233 AdTechIdentifier.fromString(buyerDomain.getAuthority()))) 5234 .setUserBiddingSignals(CustomAudienceFixture.VALID_USER_BIDDING_SIGNALS) 5235 .setTrustedBiddingData( 5236 new TrustedBiddingData.Builder() 5237 .setTrustedBiddingUri( 5238 CommonFixture.getUri( 5239 buyerDomain.getAuthority(), 5240 BUYER_TRUSTED_SIGNAL_URI_PATH)) 5241 .setTrustedBiddingKeys( 5242 TrustedBiddingDataFixture.getValidTrustedBiddingKeys()) 5243 .build()) 5244 .setBiddingLogicUri( 5245 CommonFixture.getUri( 5246 buyerDomain.getAuthority(), 5247 BUYER_BIDDING_LOGIC_URI_PATH + customAudienceSeq)) 5248 .setAds(ads) 5249 .build(); 5250 } 5251 testFledgeFlowSuccessAllFilters( boolean shouldUseUnifiedTables, boolean auctionServerEnabledReportImpression)5252 private void testFledgeFlowSuccessAllFilters( 5253 boolean shouldUseUnifiedTables, boolean auctionServerEnabledReportImpression) 5254 throws Exception { 5255 initClients( 5256 true, 5257 true, 5258 false, 5259 false, 5260 shouldUseUnifiedTables, 5261 auctionServerEnabledReportImpression); 5262 doReturn(AdServicesApiConsent.GIVEN) 5263 .when(mConsentManagerMock) 5264 .getConsent(AdServicesApiType.FLEDGE); 5265 doReturn(false) 5266 .when(mConsentManagerMock) 5267 .isFledgeConsentRevokedForAppAfterSettingFledgeUse(any()); 5268 5269 setupAdSelectionConfig(); 5270 CustomAudience customAudience1 = 5271 createCustomAudience( 5272 mLocalhostBuyerDomain, CUSTOM_AUDIENCE_SEQ_1, BIDS_FOR_BUYER_1); 5273 5274 // Using the same generic key across all ads in the CA 5275 List<Set<Integer>> adCounterKeysForCa2 = 5276 Arrays.asList( 5277 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 5278 Collections.singleton(KeyedFrequencyCapFixture.KEY1), 5279 Collections.singleton(KeyedFrequencyCapFixture.KEY1)); 5280 /* The final ad with the highest bid has both fcap and app install filters, the second ad 5281 * with the middle bid has only an app install filter and the first ad with the lowest bid 5282 * in this ca has only a fcap filter. 5283 */ 5284 List<AdFilters> adFiltersForCa2 = 5285 Arrays.asList( 5286 new AdFilters.Builder() 5287 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 5288 .build(), 5289 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build(), 5290 new AdFilters.Builder() 5291 .setAppInstallFilters(CURRENT_APP_FILTER) 5292 .setFrequencyCapFilters(CLICK_ONCE_PER_DAY_KEY1) 5293 .build()); 5294 CustomAudience customAudience2 = 5295 createCustomAudience( 5296 mLocalhostBuyerDomain, 5297 CUSTOM_AUDIENCE_SEQ_2, 5298 BIDS_FOR_BUYER_2, 5299 adCounterKeysForCa2, 5300 adFiltersForCa2, 5301 false); 5302 5303 // We add permits to the semaphores when the MWS is called and remove them in the asserts 5304 Semaphore impressionReportingSemaphore = new Semaphore(0); 5305 Semaphore interactionReportingSemaphore = new Semaphore(0); 5306 5307 MockWebServer server = 5308 getMockWebServer( 5309 getDecisionLogicWithBeacons(), 5310 getV3BiddingLogicJs(), 5311 impressionReportingSemaphore, 5312 interactionReportingSemaphore, 5313 true); 5314 5315 joinCustomAudienceAndAssertSuccess(customAudience1); 5316 joinCustomAudienceAndAssertSuccess(customAudience2); 5317 5318 verifyBackgroundFetchJobInvocation(/* invocationTimes= */ 2); 5319 5320 // Run Ad Selection no filters active 5321 selectAdsAndReport( 5322 CommonFixture.getUri( 5323 mLocalhostBuyerDomain.getAuthority(), 5324 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad3"), 5325 impressionReportingSemaphore, 5326 interactionReportingSemaphore); 5327 5328 // Run Ad Selection with app install filtering 5329 registerForAppInstallFiltering(); 5330 long adSelectionId = 5331 selectAdsAndReport( 5332 CommonFixture.getUri( 5333 mLocalhostBuyerDomain.getAuthority(), 5334 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad1"), 5335 impressionReportingSemaphore, 5336 interactionReportingSemaphore); 5337 5338 // Run Ad Selection with both filters 5339 updateHistogramAndAssertSuccess(adSelectionId, FrequencyCapFilters.AD_EVENT_TYPE_CLICK); 5340 selectAdsAndReport( 5341 CommonFixture.getUri( 5342 mLocalhostBuyerDomain.getAuthority(), 5343 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_1 + "/ad2"), 5344 impressionReportingSemaphore, 5345 interactionReportingSemaphore); 5346 5347 // Run Ad Selection with just fcap filtering 5348 deregisterForAppInstallFiltering(); 5349 selectAdsAndReport( 5350 CommonFixture.getUri( 5351 mLocalhostBuyerDomain.getAuthority(), 5352 AD_URI_PREFIX + CUSTOM_AUDIENCE_SEQ_2 + "/ad2"), 5353 impressionReportingSemaphore, 5354 interactionReportingSemaphore); 5355 5356 // 30 requests for the 3 auctions with both CAs and 9 requests for the auctions with one CA 5357 mockWebServerRule.verifyMockServerRequests( 5358 server, 5359 39, 5360 ImmutableList.of( 5361 SELLER_DECISION_LOGIC_URI_PATH, 5362 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_1, 5363 BUYER_BIDDING_LOGIC_URI_PATH + CUSTOM_AUDIENCE_SEQ_2, 5364 BUYER_TRUSTED_SIGNAL_URI_PATH, 5365 SELLER_TRUSTED_SIGNAL_URI_PATH + SELLER_TRUSTED_SIGNAL_PARAMS), 5366 mRequestMatcherPrefixMatch); 5367 } 5368 5369 private static class ResultCapturingCallback implements ICustomAudienceCallback { 5370 private boolean mIsSuccess; 5371 private Exception mException; 5372 isSuccess()5373 public boolean isSuccess() { 5374 return mIsSuccess; 5375 } 5376 getException()5377 public Exception getException() { 5378 return mException; 5379 } 5380 5381 @Override onSuccess()5382 public void onSuccess() throws RemoteException { 5383 mIsSuccess = true; 5384 } 5385 5386 @Override onFailure(FledgeErrorResponse responseParcel)5387 public void onFailure(FledgeErrorResponse responseParcel) throws RemoteException { 5388 mIsSuccess = false; 5389 mException = AdServicesStatusUtils.asException(responseParcel); 5390 } 5391 5392 @Override asBinder()5393 public IBinder asBinder() { 5394 throw new RuntimeException("Should not be called."); 5395 } 5396 } 5397 5398 private static class AppInstallResultCapturingCallback 5399 implements SetAppInstallAdvertisersCallback { 5400 private boolean mIsSuccess; 5401 private Exception mException; 5402 private final CountDownLatch mCountDownLatch; 5403 isSuccess()5404 public boolean isSuccess() { 5405 return mIsSuccess; 5406 } 5407 getException()5408 public Exception getException() { 5409 return mException; 5410 } 5411 AppInstallResultCapturingCallback(CountDownLatch countDownLatch)5412 AppInstallResultCapturingCallback(CountDownLatch countDownLatch) { 5413 mCountDownLatch = countDownLatch; 5414 } 5415 5416 @Override onSuccess()5417 public void onSuccess() throws RemoteException { 5418 mIsSuccess = true; 5419 mCountDownLatch.countDown(); 5420 } 5421 5422 @Override onFailure(FledgeErrorResponse responseParcel)5423 public void onFailure(FledgeErrorResponse responseParcel) throws RemoteException { 5424 mIsSuccess = false; 5425 mException = AdServicesStatusUtils.asException(responseParcel); 5426 mCountDownLatch.countDown(); 5427 } 5428 5429 @Override asBinder()5430 public IBinder asBinder() { 5431 throw new RuntimeException("Should not be called."); 5432 } 5433 } 5434 5435 static class AdSelectionTestCallback extends AdSelectionCallback.Stub { 5436 5437 final CountDownLatch mCountDownLatch; 5438 boolean mIsSuccess = false; 5439 AdSelectionResponse mAdSelectionResponse; 5440 FledgeErrorResponse mFledgeErrorResponse; 5441 AdSelectionTestCallback(CountDownLatch countDownLatch)5442 AdSelectionTestCallback(CountDownLatch countDownLatch) { 5443 mCountDownLatch = countDownLatch; 5444 mAdSelectionResponse = null; 5445 mFledgeErrorResponse = null; 5446 } 5447 5448 @Override onSuccess(AdSelectionResponse adSelectionResponse)5449 public void onSuccess(AdSelectionResponse adSelectionResponse) throws RemoteException { 5450 mIsSuccess = true; 5451 mAdSelectionResponse = adSelectionResponse; 5452 mCountDownLatch.countDown(); 5453 } 5454 5455 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)5456 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 5457 mIsSuccess = false; 5458 mFledgeErrorResponse = fledgeErrorResponse; 5459 mCountDownLatch.countDown(); 5460 } 5461 } 5462 5463 public static class AdSelectionOverrideTestCallback extends AdSelectionOverrideCallback.Stub { 5464 private final CountDownLatch mCountDownLatch; 5465 boolean mIsSuccess = false; 5466 FledgeErrorResponse mFledgeErrorResponse; 5467 AdSelectionOverrideTestCallback(CountDownLatch countDownLatch)5468 public AdSelectionOverrideTestCallback(CountDownLatch countDownLatch) { 5469 mCountDownLatch = countDownLatch; 5470 } 5471 5472 @Override onSuccess()5473 public void onSuccess() throws RemoteException { 5474 mIsSuccess = true; 5475 mCountDownLatch.countDown(); 5476 } 5477 5478 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)5479 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 5480 mFledgeErrorResponse = fledgeErrorResponse; 5481 mCountDownLatch.countDown(); 5482 } 5483 } 5484 5485 public static class CustomAudienceOverrideTestCallback 5486 extends CustomAudienceOverrideCallback.Stub { 5487 private final CountDownLatch mCountDownLatch; 5488 boolean mIsSuccess = false; 5489 FledgeErrorResponse mFledgeErrorResponse; 5490 CustomAudienceOverrideTestCallback(CountDownLatch countDownLatch)5491 public CustomAudienceOverrideTestCallback(CountDownLatch countDownLatch) { 5492 mCountDownLatch = countDownLatch; 5493 } 5494 5495 @Override onSuccess()5496 public void onSuccess() throws RemoteException { 5497 mIsSuccess = true; 5498 mCountDownLatch.countDown(); 5499 } 5500 5501 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)5502 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 5503 mFledgeErrorResponse = fledgeErrorResponse; 5504 mCountDownLatch.countDown(); 5505 } 5506 } 5507 5508 public static class ReportImpressionTestCallback extends ReportImpressionCallback.Stub { 5509 private final CountDownLatch mCountDownLatch; 5510 boolean mIsSuccess = false; 5511 FledgeErrorResponse mFledgeErrorResponse; 5512 ReportImpressionTestCallback(CountDownLatch countDownLatch)5513 public ReportImpressionTestCallback(CountDownLatch countDownLatch) { 5514 mCountDownLatch = countDownLatch; 5515 } 5516 5517 @Override onSuccess()5518 public void onSuccess() throws RemoteException { 5519 mIsSuccess = true; 5520 mCountDownLatch.countDown(); 5521 } 5522 5523 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)5524 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 5525 mFledgeErrorResponse = fledgeErrorResponse; 5526 mCountDownLatch.countDown(); 5527 } 5528 } 5529 5530 static class ReportInteractionTestCallback extends ReportInteractionCallback.Stub { 5531 private final CountDownLatch mCountDownLatch; 5532 boolean mIsSuccess = false; 5533 FledgeErrorResponse mFledgeErrorResponse; 5534 ReportInteractionTestCallback(CountDownLatch countDownLatch)5535 ReportInteractionTestCallback(CountDownLatch countDownLatch) { 5536 mCountDownLatch = countDownLatch; 5537 } 5538 5539 @Override onSuccess()5540 public void onSuccess() throws RemoteException { 5541 mIsSuccess = true; 5542 mCountDownLatch.countDown(); 5543 } 5544 5545 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)5546 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 5547 mFledgeErrorResponse = fledgeErrorResponse; 5548 mCountDownLatch.countDown(); 5549 } 5550 } 5551 createContextualAds()5552 private Map<AdTechIdentifier, SignedContextualAds> createContextualAds() { 5553 Map<AdTechIdentifier, SignedContextualAds> buyerContextualAds = new HashMap<>(); 5554 5555 // In order to meet ETLd+1 requirements creating Contextual ads with MockWebserver's host 5556 AdTechIdentifier buyer = 5557 AdTechIdentifier.fromString( 5558 mockWebServerRule.uriForPath(BUYER_BIDDING_LOGIC_URI_PATH).getHost()); 5559 SignedContextualAds contextualAds = 5560 SignedContextualAdsFixture.signContextualAds( 5561 SignedContextualAdsFixture.aContextualAdsWithEmptySignatureBuilder( 5562 buyer, ImmutableList.of(100.0, 200.0, 300.0, 400.0, 500.0)) 5563 .setDecisionLogicUri( 5564 mockWebServerRule.uriForPath( 5565 BUYER_BIDDING_LOGIC_URI_PATH))); 5566 buyerContextualAds.put(buyer, contextualAds); 5567 return buyerContextualAds; 5568 } 5569 verifyBackgroundFetchJobInvocation(int invocationTimes)5570 private void verifyBackgroundFetchJobInvocation(int invocationTimes) { 5571 verify(() -> BackgroundFetchJob.schedule(any()), times(invocationTimes)); 5572 } 5573 5574 private static class FledgeE2ETestFlags implements Flags { 5575 private final boolean mIsGaUxEnabled; 5576 private final boolean mRegisterAdBeaconEnabled; 5577 private final boolean mFrequencyCapFilteringEnabled; 5578 private final boolean mAppInstallFilteringEnabled; 5579 private final boolean mEnrollmentCheckDisabled; 5580 private final boolean mCpcBillingEnabled; 5581 private final boolean mDebugReportingEnabled; 5582 private final boolean mDataVersionHeaderEnabled; 5583 private final boolean mDebugReportsSendImmediately; 5584 private final boolean mAdIdKillSwitch; 5585 private final boolean mShouldUseUnifiedTables; 5586 private final boolean mAuctionServerEnabledReportImpression; 5587 FledgeE2ETestFlags( boolean isGaUxEnabled, boolean registerAdBeaconEnabled, boolean frequencyCapFilteringEnabled, boolean appInstallEnabled, boolean enrollmentCheckDisabled, boolean cpcBillingEnabled, boolean debugReportingEnabled, boolean dataVersionHeaderEnabled, boolean debugReportsSendImmediately, boolean adIdKillSwitch, boolean shouldUseUnifiedTables, boolean auctionServerEnabledReportImpression)5588 FledgeE2ETestFlags( 5589 boolean isGaUxEnabled, 5590 boolean registerAdBeaconEnabled, 5591 boolean frequencyCapFilteringEnabled, 5592 boolean appInstallEnabled, 5593 boolean enrollmentCheckDisabled, 5594 boolean cpcBillingEnabled, 5595 boolean debugReportingEnabled, 5596 boolean dataVersionHeaderEnabled, 5597 boolean debugReportsSendImmediately, 5598 boolean adIdKillSwitch, 5599 boolean shouldUseUnifiedTables, 5600 boolean auctionServerEnabledReportImpression) { 5601 mIsGaUxEnabled = isGaUxEnabled; 5602 mRegisterAdBeaconEnabled = registerAdBeaconEnabled; 5603 mFrequencyCapFilteringEnabled = frequencyCapFilteringEnabled; 5604 mAppInstallFilteringEnabled = appInstallEnabled; 5605 mEnrollmentCheckDisabled = enrollmentCheckDisabled; 5606 mCpcBillingEnabled = cpcBillingEnabled; 5607 mDebugReportingEnabled = debugReportingEnabled; 5608 mDataVersionHeaderEnabled = dataVersionHeaderEnabled; 5609 mDebugReportsSendImmediately = debugReportsSendImmediately; 5610 mAdIdKillSwitch = adIdKillSwitch; 5611 mShouldUseUnifiedTables = shouldUseUnifiedTables; 5612 mAuctionServerEnabledReportImpression = auctionServerEnabledReportImpression; 5613 } 5614 5615 @Override getAdSelectionBiddingTimeoutPerCaMs()5616 public long getAdSelectionBiddingTimeoutPerCaMs() { 5617 return 10000; 5618 } 5619 5620 @Override getAdSelectionScoringTimeoutMs()5621 public long getAdSelectionScoringTimeoutMs() { 5622 return 10000; 5623 } 5624 5625 @Override getAdSelectionOverallTimeoutMs()5626 public long getAdSelectionOverallTimeoutMs() { 5627 return 300000; 5628 } 5629 5630 @Override getEnforceIsolateMaxHeapSize()5631 public boolean getEnforceIsolateMaxHeapSize() { 5632 return false; 5633 } 5634 5635 @Override getGaUxFeatureEnabled()5636 public boolean getGaUxFeatureEnabled() { 5637 return mIsGaUxEnabled; 5638 } 5639 5640 @Override getSdkRequestPermitsPerSecond()5641 public float getSdkRequestPermitsPerSecond() { 5642 // Unlimited rate for unit tests to avoid flake in tests due to rate limiting 5643 return -1; 5644 } 5645 5646 @Override getDisableFledgeEnrollmentCheck()5647 public boolean getDisableFledgeEnrollmentCheck() { 5648 return mEnrollmentCheckDisabled; 5649 } 5650 5651 @Override getFledgeRegisterAdBeaconEnabled()5652 public boolean getFledgeRegisterAdBeaconEnabled() { 5653 return mRegisterAdBeaconEnabled; 5654 } 5655 5656 @Override getFledgeFrequencyCapFilteringEnabled()5657 public boolean getFledgeFrequencyCapFilteringEnabled() { 5658 return mFrequencyCapFilteringEnabled; 5659 } 5660 5661 @Override getFledgeAppInstallFilteringEnabled()5662 public boolean getFledgeAppInstallFilteringEnabled() { 5663 return mAppInstallFilteringEnabled; 5664 } 5665 5666 @Override getFledgeAdSelectionContextualAdsEnabled()5667 public boolean getFledgeAdSelectionContextualAdsEnabled() { 5668 return true; 5669 } 5670 5671 @Override getFledgeAdSelectionBiddingLogicJsVersion()5672 public long getFledgeAdSelectionBiddingLogicJsVersion() { 5673 return JsVersionRegister.BUYER_BIDDING_LOGIC_VERSION_VERSION_3; 5674 } 5675 5676 @Override getFledgeCpcBillingEnabled()5677 public boolean getFledgeCpcBillingEnabled() { 5678 return mCpcBillingEnabled; 5679 } 5680 5681 @Override getFledgeFetchCustomAudienceEnabled()5682 public boolean getFledgeFetchCustomAudienceEnabled() { 5683 return true; 5684 } 5685 5686 @Override getFledgeEventLevelDebugReportingEnabled()5687 public boolean getFledgeEventLevelDebugReportingEnabled() { 5688 return mDebugReportingEnabled; 5689 } 5690 5691 @Override getFledgeDataVersionHeaderEnabled()5692 public boolean getFledgeDataVersionHeaderEnabled() { 5693 return mDataVersionHeaderEnabled; 5694 } 5695 5696 @Override getFledgeOnDeviceAuctionKillSwitch()5697 public boolean getFledgeOnDeviceAuctionKillSwitch() { 5698 return false; 5699 } 5700 5701 @Override getFledgeEventLevelDebugReportSendImmediately()5702 public boolean getFledgeEventLevelDebugReportSendImmediately() { 5703 return mDebugReportsSendImmediately; 5704 } 5705 5706 @Override getAdIdKillSwitch()5707 public boolean getAdIdKillSwitch() { 5708 return mAdIdKillSwitch; 5709 } 5710 5711 @Override getFledgeOnDeviceAuctionShouldUseUnifiedTables()5712 public boolean getFledgeOnDeviceAuctionShouldUseUnifiedTables() { 5713 return mShouldUseUnifiedTables; 5714 } 5715 5716 @Override getFledgeAuctionServerEnabledForReportEvent()5717 public boolean getFledgeAuctionServerEnabledForReportEvent() { 5718 return false; 5719 } 5720 5721 @Override getFledgeAuctionServerEnabledForReportImpression()5722 public boolean getFledgeAuctionServerEnabledForReportImpression() { 5723 return mAuctionServerEnabledReportImpression; 5724 } 5725 } 5726 } 5727