1 /* 2 * Copyright (C) 2023 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.adselection; 18 19 import static android.adservices.common.AdServicesStatusUtils.STATUS_INVALID_ARGUMENT; 20 import static android.adservices.common.AdServicesStatusUtils.STATUS_SUCCESS; 21 import static android.adservices.common.KeyedFrequencyCapFixture.ONE_DAY_DURATION; 22 import static android.adservices.customaudience.CustomAudience.FLAG_AUCTION_SERVER_REQUEST_OMIT_ADS; 23 24 import static com.android.adservices.common.DBAdDataFixture.getValidDbAdDataNoFiltersBuilder; 25 import static com.android.adservices.data.adselection.EncryptionKeyConstants.EncryptionKeyType.ENCRYPTION_KEY_TYPE_AUCTION; 26 import static com.android.adservices.service.adselection.AdSelectionFromOutcomesE2ETest.BID_FLOOR_SELECTION_SIGNAL_TEMPLATE; 27 import static com.android.adservices.service.adselection.AdSelectionFromOutcomesE2ETest.SELECTION_WATERFALL_LOGIC_JS; 28 import static com.android.adservices.service.adselection.AdSelectionFromOutcomesE2ETest.SELECTION_WATERFALL_LOGIC_JS_PATH; 29 import static com.android.adservices.service.adselection.AdSelectionServiceImpl.AUCTION_SERVER_API_IS_NOT_AVAILABLE; 30 import static com.android.adservices.service.adselection.GetAdSelectionDataRunner.REVOKED_CONSENT_RANDOM_DATA_SIZE; 31 import static com.android.adservices.service.stats.AdSelectionExecutionLoggerTest.sCallerMetadata; 32 import static com.android.adservices.service.stats.AdsRelevanceStatusUtils.SERVER_AUCTION_COORDINATOR_SOURCE_DEFAULT; 33 import static com.android.adservices.service.stats.AdsRelevanceStatusUtils.SERVER_AUCTION_COORDINATOR_SOURCE_UNSET; 34 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; 35 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; 36 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyLong; 37 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; 38 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 39 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow; 40 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; 41 42 import static com.google.common.truth.Truth.assertThat; 43 import static com.google.common.util.concurrent.Futures.immediateFuture; 44 45 import static org.junit.Assert.assertTrue; 46 import static org.mockito.ArgumentMatchers.eq; 47 import static org.mockito.Mockito.doAnswer; 48 import static org.mockito.Mockito.never; 49 import static org.mockito.Mockito.reset; 50 import static org.mockito.Mockito.spy; 51 import static org.mockito.Mockito.times; 52 import static org.mockito.Mockito.verify; 53 54 import android.adservices.adid.AdId; 55 import android.adservices.adselection.AdSelectionCallback; 56 import android.adservices.adselection.AdSelectionConfig; 57 import android.adservices.adselection.AdSelectionConfigFixture; 58 import android.adservices.adselection.AdSelectionFromOutcomesConfigFixture; 59 import android.adservices.adselection.AdSelectionFromOutcomesInput; 60 import android.adservices.adselection.AdSelectionResponse; 61 import android.adservices.adselection.AdSelectionService; 62 import android.adservices.adselection.AuctionEncryptionKeyFixture; 63 import android.adservices.adselection.GetAdSelectionDataCallback; 64 import android.adservices.adselection.GetAdSelectionDataInput; 65 import android.adservices.adselection.GetAdSelectionDataResponse; 66 import android.adservices.adselection.ObliviousHttpEncryptorWithSeedImpl; 67 import android.adservices.adselection.PersistAdSelectionResultCallback; 68 import android.adservices.adselection.PersistAdSelectionResultInput; 69 import android.adservices.adselection.PersistAdSelectionResultResponse; 70 import android.adservices.adselection.ReportEventRequest; 71 import android.adservices.adselection.ReportImpressionCallback; 72 import android.adservices.adselection.ReportImpressionInput; 73 import android.adservices.adselection.ReportInteractionCallback; 74 import android.adservices.adselection.ReportInteractionInput; 75 import android.adservices.adselection.SetAppInstallAdvertisersCallback; 76 import android.adservices.adselection.SetAppInstallAdvertisersInput; 77 import android.adservices.adselection.UpdateAdCounterHistogramCallback; 78 import android.adservices.adselection.UpdateAdCounterHistogramInput; 79 import android.adservices.common.AdFilters; 80 import android.adservices.common.AdSelectionSignals; 81 import android.adservices.common.AdServicesStatusUtils; 82 import android.adservices.common.AdTechIdentifier; 83 import android.adservices.common.AppInstallFilters; 84 import android.adservices.common.CallingAppUidSupplierProcessImpl; 85 import android.adservices.common.CommonFixture; 86 import android.adservices.common.FledgeErrorResponse; 87 import android.adservices.common.FrequencyCapFilters; 88 import android.adservices.common.KeyedFrequencyCap; 89 import android.adservices.http.MockWebServerRule; 90 import android.content.Context; 91 import android.net.Uri; 92 import android.os.IBinder; 93 import android.os.Process; 94 import android.os.RemoteException; 95 96 import androidx.room.Room; 97 import androidx.test.core.app.ApplicationProvider; 98 import androidx.test.filters.FlakyTest; 99 100 import com.android.adservices.MockWebServerRuleFactory; 101 import com.android.adservices.common.AdServicesDeviceSupportedRule; 102 import com.android.adservices.common.DBAdDataFixture; 103 import com.android.adservices.common.WebViewSupportUtil; 104 import com.android.adservices.concurrency.AdServicesExecutors; 105 import com.android.adservices.customaudience.DBCustomAudienceFixture; 106 import com.android.adservices.data.adselection.AdSelectionDatabase; 107 import com.android.adservices.data.adselection.AdSelectionDebugReportDao; 108 import com.android.adservices.data.adselection.AdSelectionDebugReportingDatabase; 109 import com.android.adservices.data.adselection.AdSelectionEntryDao; 110 import com.android.adservices.data.adselection.AdSelectionServerDatabase; 111 import com.android.adservices.data.adselection.AppInstallDao; 112 import com.android.adservices.data.adselection.ConsentedDebugConfigurationDao; 113 import com.android.adservices.data.adselection.DBEncryptionKey; 114 import com.android.adservices.data.adselection.DBProtectedServersEncryptionConfig; 115 import com.android.adservices.data.adselection.EncryptionContextDao; 116 import com.android.adservices.data.adselection.EncryptionKeyDao; 117 import com.android.adservices.data.adselection.FrequencyCapDao; 118 import com.android.adservices.data.adselection.ProtectedServersEncryptionConfigDao; 119 import com.android.adservices.data.adselection.SharedStorageDatabase; 120 import com.android.adservices.data.adselection.datahandlers.ReportingData; 121 import com.android.adservices.data.common.DBAdData; 122 import com.android.adservices.data.customaudience.CustomAudienceDao; 123 import com.android.adservices.data.customaudience.CustomAudienceDatabase; 124 import com.android.adservices.data.customaudience.DBCustomAudience; 125 import com.android.adservices.data.enrollment.EnrollmentDao; 126 import com.android.adservices.data.signals.DBEncodedPayload; 127 import com.android.adservices.data.signals.EncodedPayloadDao; 128 import com.android.adservices.data.signals.ProtectedSignalsDatabase; 129 import com.android.adservices.ohttp.ObliviousHttpGateway; 130 import com.android.adservices.ohttp.OhttpGatewayPrivateKey; 131 import com.android.adservices.service.Flags; 132 import com.android.adservices.service.FlagsFactory; 133 import com.android.adservices.service.adid.AdIdCacheManager; 134 import com.android.adservices.service.adselection.debug.ConsentedDebugConfigurationGeneratorFactory; 135 import com.android.adservices.service.adselection.encryption.AdSelectionEncryptionKey; 136 import com.android.adservices.service.adselection.encryption.AdSelectionEncryptionKeyManager; 137 import com.android.adservices.service.adselection.encryption.ObliviousHttpEncryptor; 138 import com.android.adservices.service.adselection.encryption.ObliviousHttpEncryptorImpl; 139 import com.android.adservices.service.adselection.encryption.ProtectedServersEncryptionConfigManager; 140 import com.android.adservices.service.common.AdSelectionServiceFilter; 141 import com.android.adservices.service.common.AppImportanceFilter; 142 import com.android.adservices.service.common.FledgeAuthorizationFilter; 143 import com.android.adservices.service.common.RetryStrategyFactory; 144 import com.android.adservices.service.common.Throttler; 145 import com.android.adservices.service.common.cache.CacheProviderFactory; 146 import com.android.adservices.service.common.httpclient.AdServicesHttpClientResponse; 147 import com.android.adservices.service.common.httpclient.AdServicesHttpsClient; 148 import com.android.adservices.service.consent.ConsentManager; 149 import com.android.adservices.service.devapi.DevContext; 150 import com.android.adservices.service.devapi.DevContextFilter; 151 import com.android.adservices.service.exception.FilterException; 152 import com.android.adservices.service.js.JSScriptEngine; 153 import com.android.adservices.service.kanon.KAnonSignJoinFactory; 154 import com.android.adservices.service.proto.bidding_auction_servers.BiddingAuctionServers.AuctionResult; 155 import com.android.adservices.service.proto.bidding_auction_servers.BiddingAuctionServers.BuyerInput; 156 import com.android.adservices.service.proto.bidding_auction_servers.BiddingAuctionServers.ProtectedAppSignals; 157 import com.android.adservices.service.proto.bidding_auction_servers.BiddingAuctionServers.ProtectedAuctionInput; 158 import com.android.adservices.service.proto.bidding_auction_servers.BiddingAuctionServers.WinReportingUrls; 159 import com.android.adservices.service.proto.bidding_auction_servers.BiddingAuctionServers.WinReportingUrls.ReportingUrls; 160 import com.android.adservices.service.signals.EgressConfigurationGenerator; 161 import com.android.adservices.service.stats.AdServicesLogger; 162 import com.android.adservices.service.stats.AdServicesLoggerImpl; 163 import com.android.adservices.service.stats.AdServicesStatsLog; 164 import com.android.adservices.service.stats.FetchProcessLogger; 165 import com.android.adservices.service.stats.GetAdSelectionDataApiCalledStats; 166 import com.android.adservices.service.stats.GetAdSelectionDataBuyerInputGeneratedStats; 167 import com.android.adservices.shared.testing.SdkLevelSupportRule; 168 import com.android.dx.mockito.inline.extended.ExtendedMockito; 169 170 import com.google.common.collect.ImmutableList; 171 import com.google.common.collect.ImmutableSet; 172 import com.google.common.io.BaseEncoding; 173 import com.google.common.util.concurrent.FluentFuture; 174 import com.google.common.util.concurrent.Futures; 175 import com.google.common.util.concurrent.ListenableFuture; 176 import com.google.mockwebserver.Dispatcher; 177 import com.google.mockwebserver.MockResponse; 178 import com.google.mockwebserver.RecordedRequest; 179 import com.google.protobuf.ByteString; 180 import com.google.protobuf.InvalidProtocolBufferException; 181 182 import org.junit.After; 183 import org.junit.Assert; 184 import org.junit.Assume; 185 import org.junit.Before; 186 import org.junit.Rule; 187 import org.junit.Test; 188 import org.junit.function.ThrowingRunnable; 189 import org.mockito.ArgumentCaptor; 190 import org.mockito.Mock; 191 import org.mockito.MockitoSession; 192 import org.mockito.quality.Strictness; 193 import org.mockito.stubbing.Answer; 194 195 import java.io.UncheckedIOException; 196 import java.nio.charset.StandardCharsets; 197 import java.time.Instant; 198 import java.util.Arrays; 199 import java.util.Collections; 200 import java.util.HashMap; 201 import java.util.HashSet; 202 import java.util.List; 203 import java.util.Map; 204 import java.util.Optional; 205 import java.util.Set; 206 import java.util.concurrent.CountDownLatch; 207 import java.util.concurrent.ExecutorService; 208 import java.util.concurrent.ScheduledThreadPoolExecutor; 209 import java.util.concurrent.TimeUnit; 210 import java.util.function.Function; 211 import java.util.stream.Collectors; 212 213 public class AuctionServerE2ETest { 214 private static final int COUNTDOWN_LATCH_LIMIT_SECONDS = 10; 215 private static final int CALLER_UID = Process.myUid(); 216 private static final String CALLER_PACKAGE_NAME = CommonFixture.TEST_PACKAGE_NAME; 217 private static final AdTechIdentifier SELLER = AdSelectionConfigFixture.SELLER; 218 private static final AdTechIdentifier WINNER_BUYER = AdSelectionConfigFixture.BUYER; 219 private static final AdTechIdentifier DIFFERENT_BUYER = AdSelectionConfigFixture.BUYER_2; 220 private static final DBAdData WINNER_AD = 221 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId(WINNER_BUYER).get(0); 222 private static final Uri WINNER_AD_RENDER_URI = WINNER_AD.getRenderUri(); 223 private static final Set<Integer> WINNER_AD_COUNTERS = WINNER_AD.getAdCounterKeys(); 224 private static final String BUYER_REPORTING_URI = 225 CommonFixture.getUri(WINNER_BUYER, "/reporting").toString(); 226 private static final String SELLER_REPORTING_URI = 227 CommonFixture.getUri(SELLER, "/reporting").toString(); 228 private static final String BUYER_INTERACTION_KEY = "buyer-interaction-key"; 229 private static final String BUYER_INTERACTION_URI = 230 CommonFixture.getUri(WINNER_BUYER, "/interaction").toString(); 231 private static final String SELLER_INTERACTION_KEY = "seller-interaction-key"; 232 private static final String SELLER_INTERACTION_URI = 233 CommonFixture.getUri(SELLER, "/interaction").toString(); 234 235 public static final AppInstallFilters CURRENT_APP_FILTER = 236 new AppInstallFilters.Builder() 237 .setPackageNames(new HashSet<>(Arrays.asList(CommonFixture.TEST_PACKAGE_NAME))) 238 .build(); 239 240 private static final String COORDINATOR_URL = "https://example.com/keys"; 241 private static final String COORDINATOR_HOST = "https://example.com"; 242 private static final String DEFAULT_FETCH_URI = "https://default-example.com/keys"; 243 private static final String DEFAULT_FETCH_HOST = "https://default-example.com"; 244 245 private static final String COORDINATOR_ALLOWLIST = COORDINATOR_URL + "," + DEFAULT_FETCH_URI; 246 247 private static final WinReportingUrls WIN_REPORTING_URLS = 248 WinReportingUrls.newBuilder() 249 .setBuyerReportingUrls( 250 ReportingUrls.newBuilder() 251 .setReportingUrl(BUYER_REPORTING_URI) 252 .putInteractionReportingUrls( 253 BUYER_INTERACTION_KEY, BUYER_INTERACTION_URI) 254 .build()) 255 .setTopLevelSellerReportingUrls( 256 ReportingUrls.newBuilder() 257 .setReportingUrl(SELLER_REPORTING_URI) 258 .putInteractionReportingUrls( 259 SELLER_INTERACTION_KEY, SELLER_INTERACTION_URI) 260 .build()) 261 .build(); 262 private static final String WINNING_CUSTOM_AUDIENCE_NAME = "test-name"; 263 private static final String WINNING_CUSTOM_AUDIENCE_OWNER = "test-owner"; 264 private static final float BID = 5; 265 private static final float SCORE = 5; 266 private static final AuctionResult AUCTION_RESULT = 267 AuctionResult.newBuilder() 268 .setAdType(AuctionResult.AdType.REMARKETING_AD) 269 .setAdRenderUrl(WINNER_AD_RENDER_URI.toString()) 270 .setCustomAudienceName(WINNING_CUSTOM_AUDIENCE_NAME) 271 .setCustomAudienceOwner(WINNING_CUSTOM_AUDIENCE_OWNER) 272 .setBuyer(WINNER_BUYER.toString()) 273 .setBid(BID) 274 .setScore(SCORE) 275 .setIsChaff(false) 276 .setWinReportingUrls(WIN_REPORTING_URLS) 277 .build(); 278 279 private static final AuctionResult AUCTION_RESULT_PAS = 280 AuctionResult.newBuilder() 281 .setAdType(AuctionResult.AdType.APP_INSTALL_AD) 282 .setAdRenderUrl(WINNER_AD_RENDER_URI.toString()) 283 .setCustomAudienceOwner(WINNING_CUSTOM_AUDIENCE_OWNER) 284 .setBuyer(WINNER_BUYER.toString()) 285 .setBid(BID) 286 .setScore(SCORE) 287 .setIsChaff(false) 288 .setWinReportingUrls(WIN_REPORTING_URLS) 289 .build(); 290 private static final int NUM_BUYERS = 2; 291 292 private static final long AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS = 20; 293 private static final boolean CONSOLE_MESSAGE_IN_LOGS_ENABLED = true; 294 private ExecutorService mLightweightExecutorService; 295 private ExecutorService mBackgroundExecutorService; 296 private ScheduledThreadPoolExecutor mScheduledExecutor; 297 private AdServicesHttpsClient mAdServicesHttpsClientSpy; 298 private AdServicesLogger mAdServicesLoggerMock; 299 300 @Rule(order = 0) 301 public final SdkLevelSupportRule sdkLevel = SdkLevelSupportRule.forAtLeastS(); 302 303 @Rule(order = 1) 304 public final AdServicesDeviceSupportedRule deviceSupportRule = 305 new AdServicesDeviceSupportedRule(); 306 307 @Rule(order = 2) 308 public final MockWebServerRule mockWebServerRule = MockWebServerRuleFactory.createForHttps(); 309 310 // This object access some system APIs 311 @Mock public DevContextFilter mDevContextFilterMock; 312 @Mock public AppImportanceFilter mAppImportanceFilterMock; 313 private Context mContext; 314 private Flags mFlags; 315 @Mock private FledgeAuthorizationFilter mFledgeAuthorizationFilterMock; 316 private AdFilteringFeatureFactory mAdFilteringFeatureFactory; 317 private MockitoSession mStaticMockSession = null; 318 @Mock private ConsentManager mConsentManagerMock; 319 private CustomAudienceDao mCustomAudienceDaoSpy; 320 private EncodedPayloadDao mEncodedPayloadDaoSpy; 321 private AdSelectionEntryDao mAdSelectionEntryDao; 322 private AppInstallDao mAppInstallDao; 323 private FrequencyCapDao mFrequencyCapDaoSpy; 324 private com.android.adservices.data.encryptionkey.EncryptionKeyDao mEncryptionKeyDao; 325 private EncryptionKeyDao mAuctionServerEncryptionKeyDao; 326 private ProtectedServersEncryptionConfigDao mProtectedServersEncryptionConfigDao; 327 private EnrollmentDao mEnrollmentDao; 328 private EncryptionContextDao mEncryptionContextDao; 329 @Mock private ObliviousHttpEncryptor mObliviousHttpEncryptorMock; 330 @Mock private AdSelectionServiceFilter mAdSelectionServiceFilterMock; 331 private AdSelectionService mAdSelectionService; 332 private AuctionServerPayloadFormatter mPayloadFormatter; 333 private AuctionServerPayloadExtractor mPayloadExtractor; 334 private AuctionServerDataCompressor mDataCompressor; 335 private AdSelectionDebugReportDao mAdSelectionDebugReportDaoSpy; 336 private AdIdFetcher mAdIdFetcher; 337 private MockAdIdWorker mMockAdIdWorker; 338 private MultiCloudSupportStrategy mMultiCloudSupportStrategy; 339 @Mock private KAnonSignJoinFactory mUnusedKAnonSignJoinFactory; 340 @Mock private AdServicesHttpsClient mMockHttpClient; 341 private RetryStrategyFactory mRetryStrategyFactory; 342 private ConsentedDebugConfigurationDao mConsentedDebugConfigurationDao; 343 private ConsentedDebugConfigurationGeneratorFactory 344 mConsentedDebugConfigurationGeneratorFactory; 345 private EgressConfigurationGenerator mEgressConfigurationGenerator; 346 347 @Before setUp()348 public void setUp() { 349 mLightweightExecutorService = AdServicesExecutors.getLightWeightExecutor(); 350 mBackgroundExecutorService = AdServicesExecutors.getBackgroundExecutor(); 351 mScheduledExecutor = AdServicesExecutors.getScheduler(); 352 mContext = ApplicationProvider.getApplicationContext(); 353 mFlags = new AuctionServerE2ETestFlags(); 354 mStaticMockSession = 355 ExtendedMockito.mockitoSession() 356 .spyStatic(JSScriptEngine.class) 357 .strictness(Strictness.LENIENT) 358 .initMocks(this) 359 .mockStatic(ConsentManager.class) 360 .mockStatic(AppImportanceFilter.class) 361 .mockStatic(FlagsFactory.class) 362 .startMocking(); 363 mAdServicesLoggerMock = ExtendedMockito.mock(AdServicesLoggerImpl.class); 364 mCustomAudienceDaoSpy = 365 spy( 366 Room.inMemoryDatabaseBuilder(mContext, CustomAudienceDatabase.class) 367 .addTypeConverter(new DBCustomAudience.Converters(true, true, true)) 368 .build() 369 .customAudienceDao()); 370 mEncodedPayloadDaoSpy = 371 spy( 372 Room.inMemoryDatabaseBuilder(mContext, ProtectedSignalsDatabase.class) 373 .build() 374 .getEncodedPayloadDao()); 375 mAdSelectionEntryDao = 376 Room.inMemoryDatabaseBuilder(mContext, AdSelectionDatabase.class) 377 .build() 378 .adSelectionEntryDao(); 379 SharedStorageDatabase sharedDb = 380 Room.inMemoryDatabaseBuilder(mContext, SharedStorageDatabase.class).build(); 381 382 doReturn(mFlags).when(FlagsFactory::getFlags); 383 mAppInstallDao = sharedDb.appInstallDao(); 384 mFrequencyCapDaoSpy = spy(sharedDb.frequencyCapDao()); 385 AdSelectionServerDatabase serverDb = 386 Room.inMemoryDatabaseBuilder(mContext, AdSelectionServerDatabase.class).build(); 387 mEncryptionKeyDao = 388 com.android.adservices.data.encryptionkey.EncryptionKeyDao.getInstance(); 389 mEnrollmentDao = EnrollmentDao.getInstance(); 390 mAuctionServerEncryptionKeyDao = serverDb.encryptionKeyDao(); 391 mProtectedServersEncryptionConfigDao = serverDb.protectedServersEncryptionConfigDao(); 392 mEncryptionContextDao = serverDb.encryptionContextDao(); 393 mAdFilteringFeatureFactory = 394 new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDaoSpy, mFlags); 395 when(ConsentManager.getInstance()).thenReturn(mConsentManagerMock); 396 when(AppImportanceFilter.create(any(), anyInt(), any())) 397 .thenReturn(mAppImportanceFilterMock); 398 doNothing() 399 .when(mAppImportanceFilterMock) 400 .assertCallerIsInForeground(anyInt(), anyInt(), any()); 401 mAdServicesHttpsClientSpy = 402 spy( 403 new AdServicesHttpsClient( 404 AdServicesExecutors.getBlockingExecutor(), 405 CacheProviderFactory.createNoOpCache())); 406 AdSelectionDebugReportingDatabase adSelectionDebugReportingDatabase = 407 Room.inMemoryDatabaseBuilder(mContext, AdSelectionDebugReportingDatabase.class) 408 .build(); 409 mAdSelectionDebugReportDaoSpy = 410 spy(adSelectionDebugReportingDatabase.getAdSelectionDebugReportDao()); 411 mMockAdIdWorker = new MockAdIdWorker(new AdIdCacheManager(mContext)); 412 mAdIdFetcher = 413 new AdIdFetcher( 414 mContext, mMockAdIdWorker, mLightweightExecutorService, mScheduledExecutor); 415 mMultiCloudSupportStrategy = 416 MultiCloudTestStrategyFactory.getDisabledTestStrategy(mObliviousHttpEncryptorMock); 417 mRetryStrategyFactory = RetryStrategyFactory.createInstanceForTesting(); 418 mConsentedDebugConfigurationDao = 419 Room.inMemoryDatabaseBuilder(mContext, AdSelectionDatabase.class) 420 .build() 421 .consentedDebugConfigurationDao(); 422 mConsentedDebugConfigurationGeneratorFactory = 423 new ConsentedDebugConfigurationGeneratorFactory( 424 false, mConsentedDebugConfigurationDao); 425 mEgressConfigurationGenerator = 426 EgressConfigurationGenerator.createInstance( 427 true, 428 mAdIdFetcher, 429 Flags.DEFAULT_AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 430 mLightweightExecutorService); 431 432 mAdSelectionService = createAdSelectionService(); 433 434 mPayloadFormatter = 435 AuctionServerPayloadFormatterFactory.createPayloadFormatter( 436 mFlags.getFledgeAuctionServerPayloadFormatVersion(), 437 mFlags.getFledgeAuctionServerPayloadBucketSizes()); 438 mPayloadExtractor = 439 AuctionServerPayloadFormatterFactory.createPayloadExtractor( 440 mFlags.getFledgeAuctionServerPayloadFormatVersion(), mAdServicesLoggerMock); 441 442 mDataCompressor = 443 AuctionServerDataCompressorFactory.getDataCompressor( 444 mFlags.getFledgeAuctionServerCompressionAlgorithmVersion()); 445 446 doReturn(DevContext.createForDevOptionsDisabled()) 447 .when(mDevContextFilterMock) 448 .createDevContext(); 449 mMockAdIdWorker.setResult(AdId.ZERO_OUT, true); 450 } 451 452 @After tearDown()453 public void tearDown() { 454 if (mStaticMockSession != null) { 455 mStaticMockSession.finishMocking(); 456 } 457 if (mAdServicesHttpsClientSpy != null) { 458 reset(mAdServicesHttpsClientSpy); 459 } 460 } 461 462 @Test testAuctionServer_killSwitchDisabled_throwsException()463 public void testAuctionServer_killSwitchDisabled_throwsException() { 464 mFlags = 465 new AuctionServerE2ETestFlags( 466 true, false, AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, false); 467 mAdSelectionService = createAdSelectionService(); // create the service again with new flags 468 469 GetAdSelectionDataInput getAdSelectionDataInput = 470 new GetAdSelectionDataInput.Builder() 471 .setSeller(SELLER) 472 .setCallerPackageName(CALLER_PACKAGE_NAME) 473 .build(); 474 475 ThrowingRunnable getAdSelectionDataRunnable = 476 () -> invokeGetAdSelectionData(mAdSelectionService, getAdSelectionDataInput); 477 478 PersistAdSelectionResultInput persistAdSelectionResultInput = 479 new PersistAdSelectionResultInput.Builder() 480 .setAdSelectionId(123456L) 481 .setSeller(SELLER) 482 .setAdSelectionResult(new byte[42]) 483 .setCallerPackageName(CALLER_PACKAGE_NAME) 484 .build(); 485 ThrowingRunnable persistAdSelectionResultRunnable = 486 () -> 487 invokePersistAdSelectionResult( 488 mAdSelectionService, persistAdSelectionResultInput); 489 490 Assert.assertThrows( 491 AUCTION_SERVER_API_IS_NOT_AVAILABLE, 492 IllegalStateException.class, 493 getAdSelectionDataRunnable); 494 Assert.assertThrows( 495 AUCTION_SERVER_API_IS_NOT_AVAILABLE, 496 IllegalStateException.class, 497 persistAdSelectionResultRunnable); 498 } 499 500 @Test testAuctionServer_consentDisabled_throwsException()501 public void testAuctionServer_consentDisabled_throwsException() 502 throws RemoteException, InterruptedException { 503 doThrow(new FilterException(new ConsentManager.RevokedConsentException())) 504 .when(mAdSelectionServiceFilterMock) 505 .filterRequest( 506 eq(SELLER), 507 eq(CALLER_PACKAGE_NAME), 508 eq(false), 509 eq(true), 510 eq(CALLER_UID), 511 eq(AdServicesStatsLog 512 .AD_SERVICES_API_CALLED__API_NAME__GET_AD_SELECTION_DATA), 513 eq(Throttler.ApiKey.FLEDGE_API_GET_AD_SELECTION_DATA), 514 eq(DevContext.createForDevOptionsDisabled())); 515 doThrow(new FilterException(new ConsentManager.RevokedConsentException())) 516 .when(mAdSelectionServiceFilterMock) 517 .filterRequest( 518 eq(SELLER), 519 eq(CALLER_PACKAGE_NAME), 520 eq(false), 521 eq(true), 522 eq(CALLER_UID), 523 eq(AdServicesStatsLog 524 .AD_SERVICES_API_CALLED__API_NAME__PERSIST_AD_SELECTION_RESULT), 525 eq(Throttler.ApiKey.FLEDGE_API_PERSIST_AD_SELECTION_RESULT), 526 eq(DevContext.createForDevOptionsDisabled())); 527 528 mAdSelectionService = createAdSelectionService(); // create the service again with new flags 529 530 GetAdSelectionDataInput getAdSelectionDataInput = 531 new GetAdSelectionDataInput.Builder() 532 .setSeller(SELLER) 533 .setCallerPackageName(CALLER_PACKAGE_NAME) 534 .build(); 535 536 GetAdSelectionDataTestCallback callback1 = 537 invokeGetAdSelectionData(mAdSelectionService, getAdSelectionDataInput); 538 long adSelectionId = callback1.mGetAdSelectionDataResponse.getAdSelectionId(); 539 540 assertTrue(callback1.mIsSuccess); 541 Assert.assertNotNull(callback1.mGetAdSelectionDataResponse.getAdSelectionData()); 542 Assert.assertEquals( 543 REVOKED_CONSENT_RANDOM_DATA_SIZE, 544 callback1.mGetAdSelectionDataResponse.getAdSelectionData().length); 545 546 PersistAdSelectionResultInput persistAdSelectionResultInput = 547 new PersistAdSelectionResultInput.Builder() 548 .setAdSelectionId(adSelectionId) 549 .setSeller(SELLER) 550 .setAdSelectionResult(new byte[42]) 551 .setCallerPackageName(CALLER_PACKAGE_NAME) 552 .build(); 553 PersistAdSelectionResultTestCallback callback2 = 554 invokePersistAdSelectionResult(mAdSelectionService, persistAdSelectionResultInput); 555 assertTrue(callback2.mIsSuccess); 556 Assert.assertEquals( 557 adSelectionId, callback2.mPersistAdSelectionResultResponse.getAdSelectionId()); 558 Assert.assertNotNull(callback2.mPersistAdSelectionResultResponse.getAdRenderUri()); 559 Assert.assertEquals( 560 Uri.EMPTY, callback2.mPersistAdSelectionResultResponse.getAdRenderUri()); 561 } 562 563 @Test testGetAdSelectionData_withoutEncrypt_validRequest_success()564 public void testGetAdSelectionData_withoutEncrypt_validRequest_success() throws Exception { 565 doReturn(mFlags).when(FlagsFactory::getFlags); 566 567 Map<String, AdTechIdentifier> nameAndBuyersMap = 568 Map.of( 569 "Shoes CA of Buyer 1", WINNER_BUYER, 570 "Shirts CA of Buyer 1", WINNER_BUYER, 571 "Shoes CA Of Buyer 2", DIFFERENT_BUYER); 572 Set<AdTechIdentifier> buyers = new HashSet<>(nameAndBuyersMap.values()); 573 Map<String, DBCustomAudience> namesAndCustomAudiences = 574 createAndPersistDBCustomAudiences(nameAndBuyersMap); 575 576 when(mObliviousHttpEncryptorMock.encryptBytes( 577 any(byte[].class), anyLong(), anyLong(), any(), any())) 578 .thenAnswer( 579 invocation -> 580 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 581 582 GetAdSelectionDataInput input = 583 new GetAdSelectionDataInput.Builder() 584 .setSeller(SELLER) 585 .setCallerPackageName(CALLER_PACKAGE_NAME) 586 .build(); 587 588 GetAdSelectionDataTestCallback callback = 589 invokeGetAdSelectionData(mAdSelectionService, input); 590 591 assertTrue(callback.mIsSuccess); 592 Assert.assertNotNull(callback.mGetAdSelectionDataResponse); 593 Assert.assertNotNull(callback.mGetAdSelectionDataResponse.getAdSelectionData()); 594 595 byte[] encryptedBytes = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 596 // Since encryption is mocked to do nothing then just passing encrypted byte[] 597 Map<AdTechIdentifier, BuyerInput> buyerInputMap = 598 getBuyerInputMapFromDecryptedBytes(encryptedBytes); 599 Assert.assertEquals(buyers, buyerInputMap.keySet()); 600 for (AdTechIdentifier buyer : buyerInputMap.keySet()) { 601 BuyerInput buyerInput = buyerInputMap.get(buyer); 602 for (BuyerInput.CustomAudience buyerInputsCA : buyerInput.getCustomAudiencesList()) { 603 String buyerInputsCAName = buyerInputsCA.getName(); 604 assertTrue(namesAndCustomAudiences.containsKey(buyerInputsCAName)); 605 DBCustomAudience deviceCA = namesAndCustomAudiences.get(buyerInputsCAName); 606 Assert.assertEquals(deviceCA.getName(), buyerInputsCAName); 607 Assert.assertEquals(deviceCA.getBuyer(), buyer); 608 assertCasEquals(buyerInputsCA, deviceCA); 609 } 610 } 611 } 612 613 @Test testAuctionServerFlow_withoutEncrypt_validRequest_BothFiltersEnabled()614 public void testAuctionServerFlow_withoutEncrypt_validRequest_BothFiltersEnabled() 615 throws RemoteException, InterruptedException { 616 Flags flags = 617 new AuctionServerE2ETestFlags() { 618 @Override 619 public boolean getFledgeFrequencyCapFilteringEnabled() { 620 return true; 621 } 622 623 @Override 624 public boolean getFledgeAppInstallFilteringEnabled() { 625 return true; 626 } 627 }; 628 AdFilteringFeatureFactory adFilteringFeatureFactory = 629 new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDaoSpy, flags); 630 doReturn(flags).when(FlagsFactory::getFlags); 631 AdSelectionService adSelectionService = 632 createAdSelectionService( 633 flags, 634 adFilteringFeatureFactory); // create the service again with new flags and 635 // new feature factory 636 637 when(mObliviousHttpEncryptorMock.encryptBytes( 638 any(byte[].class), anyLong(), anyLong(), any(), any())) 639 .thenAnswer( 640 invocation -> 641 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 642 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 643 .thenAnswer(invocation -> invocation.getArgument(0)); 644 645 int sequenceNumber1 = 1; 646 int sequenceNumber2 = 2; 647 int sequenceNumber3 = 3; 648 int filterMaxCount = 1; 649 List<DBAdData> ads = 650 List.of( 651 getFilterableAndServerEligibleFCapAd(sequenceNumber1, filterMaxCount), 652 getFilterableAndServerEligibleAppInstallAd(sequenceNumber2), 653 DBAdDataFixture.getValidDbAdDataNoFiltersBuilder( 654 WINNER_BUYER, sequenceNumber3) 655 .setAdRenderId(Integer.toString(sequenceNumber3)) 656 .build()); 657 658 DBCustomAudience winningCustomAudience = 659 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 660 WINNER_BUYER, 661 WINNING_CUSTOM_AUDIENCE_NAME, 662 WINNING_CUSTOM_AUDIENCE_OWNER) 663 .setAds(ads) 664 .build(); 665 Assert.assertNotNull(winningCustomAudience.getAds()); 666 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 667 winningCustomAudience, Uri.EMPTY, false); 668 669 GetAdSelectionDataInput input = 670 new GetAdSelectionDataInput.Builder() 671 .setSeller(SELLER) 672 .setCallerPackageName(CALLER_PACKAGE_NAME) 673 .build(); 674 675 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 676 invokeGetAdSelectionData(adSelectionService, input); 677 long adSelectionId = 678 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 679 assertTrue(getAdSelectionDataTestCallback.mIsSuccess); 680 681 // Since encryption is mocked to do nothing then just passing encrypted byte[] 682 List<String> adRenderIdsFromBuyerInput = 683 extractCAAdRenderIdListFromBuyerInput( 684 getAdSelectionDataTestCallback, 685 winningCustomAudience.getBuyer(), 686 winningCustomAudience.getName(), 687 winningCustomAudience.getOwner()); 688 689 // Expect no ads are filtered 690 assertThat(adRenderIdsFromBuyerInput.size()).isEqualTo(ads.size()); 691 692 PersistAdSelectionResultInput persistAdSelectionResultInput = 693 new PersistAdSelectionResultInput.Builder() 694 .setAdSelectionId(adSelectionId) 695 .setSeller(SELLER) 696 .setAdSelectionResult(prepareAuctionResultBytes()) 697 .setCallerPackageName(CALLER_PACKAGE_NAME) 698 .build(); 699 700 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 701 invokePersistAdSelectionResult(adSelectionService, persistAdSelectionResultInput); 702 703 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 704 705 // FCap non-win histogram update 706 UpdateAdCounterHistogramInput updateHistogramInput = 707 new UpdateAdCounterHistogramInput.Builder( 708 adSelectionId, 709 FrequencyCapFilters.AD_EVENT_TYPE_CLICK, 710 SELLER, 711 CALLER_PACKAGE_NAME) 712 .build(); 713 UpdateAdCounterHistogramTestCallback updateHistogramCallback = 714 invokeUpdateAdCounterHistogram(adSelectionService, updateHistogramInput); 715 assertTrue(updateHistogramCallback.mIsSuccess); 716 717 // Call set app install advertisers 718 setAppInstallAdvertisers(ImmutableSet.of(WINNER_BUYER), adSelectionService); 719 720 // Collect device data again and expect to see both filter ads out 721 GetAdSelectionDataInput input2 = 722 new GetAdSelectionDataInput.Builder() 723 .setSeller(SELLER) 724 .setCallerPackageName(CALLER_PACKAGE_NAME) 725 .build(); 726 727 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback2 = 728 invokeGetAdSelectionData(adSelectionService, input2); 729 730 // Since encryption is mocked to do nothing then just passing encrypted byte[] 731 List<String> adRenderIdsFromBuyerInput2 = 732 extractCAAdRenderIdListFromBuyerInput( 733 getAdSelectionDataTestCallback2, 734 winningCustomAudience.getBuyer(), 735 winningCustomAudience.getName(), 736 winningCustomAudience.getOwner()); 737 // Both ads with filters are filtered out 738 assertThat(ads.size() - 2).isEqualTo(adRenderIdsFromBuyerInput2.size()); 739 740 // Assert that only ad remaining is the non filter one 741 assertThat(adRenderIdsFromBuyerInput2.get(0)).isEqualTo(Integer.toString(sequenceNumber3)); 742 } 743 744 @Test testAuctionServerFlow_withoutEncrypt_validRequest_AppInstallDisabled()745 public void testAuctionServerFlow_withoutEncrypt_validRequest_AppInstallDisabled() 746 throws RemoteException, InterruptedException { 747 // Enabling both filters to start so setAppInstallAdvertisers and updateAdCounterHistogram 748 // can be called as part of test setup 749 Flags flagsWithBothFiltersEnabled = 750 new AuctionServerE2ETestFlags() { 751 @Override 752 public boolean getFledgeFrequencyCapFilteringEnabled() { 753 return true; 754 } 755 756 @Override 757 public boolean getFledgeAppInstallFilteringEnabled() { 758 return true; 759 } 760 }; 761 AdFilteringFeatureFactory adFilteringFeatureFactory = 762 new AdFilteringFeatureFactory( 763 mAppInstallDao, mFrequencyCapDaoSpy, flagsWithBothFiltersEnabled); 764 doReturn(flagsWithBothFiltersEnabled).when(FlagsFactory::getFlags); 765 AdSelectionService adSelectionService = 766 createAdSelectionService( 767 flagsWithBothFiltersEnabled, 768 adFilteringFeatureFactory); // create the service again with new flags and 769 // new feature factory 770 771 when(mObliviousHttpEncryptorMock.encryptBytes( 772 any(byte[].class), anyLong(), anyLong(), any(), any())) 773 .thenAnswer( 774 invocation -> 775 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 776 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 777 .thenAnswer(invocation -> invocation.getArgument(0)); 778 779 int sequenceNumber1 = 1; 780 int sequenceNumber2 = 2; 781 int filterMaxCount = 1; 782 List<DBAdData> ads = 783 List.of( 784 getFilterableAndServerEligibleFCapAd(sequenceNumber1, filterMaxCount), 785 getFilterableAndServerEligibleAppInstallAd(sequenceNumber2)); 786 787 DBCustomAudience winningCustomAudience = 788 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 789 WINNER_BUYER, 790 WINNING_CUSTOM_AUDIENCE_NAME, 791 WINNING_CUSTOM_AUDIENCE_OWNER) 792 .setAds(ads) 793 .build(); 794 Assert.assertNotNull(winningCustomAudience.getAds()); 795 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 796 winningCustomAudience, Uri.EMPTY, false); 797 798 GetAdSelectionDataInput input = 799 new GetAdSelectionDataInput.Builder() 800 .setSeller(SELLER) 801 .setCallerPackageName(CALLER_PACKAGE_NAME) 802 .build(); 803 804 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 805 invokeGetAdSelectionData(adSelectionService, input); 806 long adSelectionId = 807 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 808 assertTrue(getAdSelectionDataTestCallback.mIsSuccess); 809 810 // Since encryption is mocked to do nothing then just passing encrypted byte[] 811 List<String> adRenderIdsFromBuyerInput = 812 extractCAAdRenderIdListFromBuyerInput( 813 getAdSelectionDataTestCallback, 814 winningCustomAudience.getBuyer(), 815 winningCustomAudience.getName(), 816 winningCustomAudience.getOwner()); 817 // Expect no ads are filtered 818 assertThat(adRenderIdsFromBuyerInput.size()).isEqualTo(ads.size()); 819 820 PersistAdSelectionResultInput persistAdSelectionResultInput = 821 new PersistAdSelectionResultInput.Builder() 822 .setAdSelectionId(adSelectionId) 823 .setSeller(SELLER) 824 .setAdSelectionResult(prepareAuctionResultBytes()) 825 .setCallerPackageName(CALLER_PACKAGE_NAME) 826 .build(); 827 828 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 829 invokePersistAdSelectionResult(adSelectionService, persistAdSelectionResultInput); 830 831 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 832 833 // FCap non-win histogram update 834 UpdateAdCounterHistogramInput updateHistogramInput = 835 new UpdateAdCounterHistogramInput.Builder( 836 adSelectionId, 837 FrequencyCapFilters.AD_EVENT_TYPE_CLICK, 838 SELLER, 839 CALLER_PACKAGE_NAME) 840 .build(); 841 UpdateAdCounterHistogramTestCallback updateHistogramCallback = 842 invokeUpdateAdCounterHistogram(adSelectionService, updateHistogramInput); 843 assertTrue(updateHistogramCallback.mIsSuccess); 844 845 // Call set app install advertisers 846 setAppInstallAdvertisers(ImmutableSet.of(WINNER_BUYER), adSelectionService); 847 848 Flags flagsWithAppInstallDisabled = 849 new AuctionServerE2ETestFlags() { 850 @Override 851 public boolean getFledgeFrequencyCapFilteringEnabled() { 852 return true; 853 } 854 855 @Override 856 public boolean getFledgeAppInstallFilteringEnabled() { 857 return false; 858 } 859 }; 860 adFilteringFeatureFactory = 861 new AdFilteringFeatureFactory( 862 mAppInstallDao, mFrequencyCapDaoSpy, flagsWithAppInstallDisabled); 863 doReturn(flagsWithAppInstallDisabled).when(FlagsFactory::getFlags); 864 adSelectionService = 865 createAdSelectionService( 866 flagsWithAppInstallDisabled, 867 adFilteringFeatureFactory); // create the service again with new flags and 868 // new feature factory 869 870 // Collect device data again and expect one less ads due to FCap filter 871 GetAdSelectionDataInput input2 = 872 new GetAdSelectionDataInput.Builder() 873 .setSeller(SELLER) 874 .setCallerPackageName(CALLER_PACKAGE_NAME) 875 .build(); 876 877 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback2 = 878 invokeGetAdSelectionData(adSelectionService, input2); 879 880 // Since encryption is mocked to do nothing then just passing encrypted byte[] 881 List<String> adRenderIdsFromBuyerInput2 = 882 extractCAAdRenderIdListFromBuyerInput( 883 getAdSelectionDataTestCallback2, 884 winningCustomAudience.getBuyer(), 885 winningCustomAudience.getName(), 886 winningCustomAudience.getOwner()); 887 // Only fcap ad is filtered out since app install is disabled 888 Assert.assertEquals(1, adRenderIdsFromBuyerInput2.size()); 889 890 // Assert that only ad remaining is the app install ad 891 assertThat(adRenderIdsFromBuyerInput2.get(0)).isEqualTo(Integer.toString(sequenceNumber2)); 892 } 893 894 @Test testAuctionServerFlow_withoutEncrypt_validRequest_FrequencyCapDisabled()895 public void testAuctionServerFlow_withoutEncrypt_validRequest_FrequencyCapDisabled() 896 throws RemoteException, InterruptedException { 897 // Enabling both filters to start so setAppInstallAdvertisers and updateAdCounterHistogram 898 // can be called as part of test setup 899 Flags flagsWithBothFiltersEnabled = 900 new AuctionServerE2ETestFlags() { 901 @Override 902 public boolean getFledgeFrequencyCapFilteringEnabled() { 903 return true; 904 } 905 906 @Override 907 public boolean getFledgeAppInstallFilteringEnabled() { 908 return true; 909 } 910 }; 911 AdFilteringFeatureFactory adFilteringFeatureFactory = 912 new AdFilteringFeatureFactory( 913 mAppInstallDao, mFrequencyCapDaoSpy, flagsWithBothFiltersEnabled); 914 doReturn(flagsWithBothFiltersEnabled).when(FlagsFactory::getFlags); 915 AdSelectionService adSelectionService = 916 createAdSelectionService( 917 flagsWithBothFiltersEnabled, 918 adFilteringFeatureFactory); // create the service again with new flags and 919 // new feature factory 920 921 when(mObliviousHttpEncryptorMock.encryptBytes( 922 any(byte[].class), anyLong(), anyLong(), any(), any())) 923 .thenAnswer( 924 invocation -> 925 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 926 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 927 .thenAnswer(invocation -> invocation.getArgument(0)); 928 929 int sequenceNumber1 = 1; 930 int sequenceNumber2 = 2; 931 int filterMaxCount = 1; 932 List<DBAdData> ads = 933 List.of( 934 getFilterableAndServerEligibleFCapAd(sequenceNumber1, filterMaxCount), 935 getFilterableAndServerEligibleAppInstallAd(sequenceNumber2)); 936 937 DBCustomAudience winningCustomAudience = 938 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 939 WINNER_BUYER, 940 WINNING_CUSTOM_AUDIENCE_NAME, 941 WINNING_CUSTOM_AUDIENCE_OWNER) 942 .setAds(ads) 943 .build(); 944 Assert.assertNotNull(winningCustomAudience.getAds()); 945 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 946 winningCustomAudience, Uri.EMPTY, false); 947 948 GetAdSelectionDataInput input = 949 new GetAdSelectionDataInput.Builder() 950 .setSeller(SELLER) 951 .setCallerPackageName(CALLER_PACKAGE_NAME) 952 .build(); 953 954 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 955 invokeGetAdSelectionData(adSelectionService, input); 956 long adSelectionId = 957 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 958 assertTrue(getAdSelectionDataTestCallback.mIsSuccess); 959 960 // Since encryption is mocked to do nothing then just passing encrypted byte[] 961 List<String> adRenderIdsFromBuyerInput = 962 extractCAAdRenderIdListFromBuyerInput( 963 getAdSelectionDataTestCallback, 964 winningCustomAudience.getBuyer(), 965 winningCustomAudience.getName(), 966 winningCustomAudience.getOwner()); 967 // Expect no ads are filtered 968 assertThat(adRenderIdsFromBuyerInput.size()).isEqualTo(ads.size()); 969 970 PersistAdSelectionResultInput persistAdSelectionResultInput = 971 new PersistAdSelectionResultInput.Builder() 972 .setAdSelectionId(adSelectionId) 973 .setSeller(SELLER) 974 .setAdSelectionResult(prepareAuctionResultBytes()) 975 .setCallerPackageName(CALLER_PACKAGE_NAME) 976 .build(); 977 978 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 979 invokePersistAdSelectionResult(adSelectionService, persistAdSelectionResultInput); 980 981 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 982 983 // FCap FCap non-win histogram updat 984 UpdateAdCounterHistogramInput updateHistogramInput = 985 new UpdateAdCounterHistogramInput.Builder( 986 adSelectionId, 987 FrequencyCapFilters.AD_EVENT_TYPE_CLICK, 988 SELLER, 989 CALLER_PACKAGE_NAME) 990 .build(); 991 UpdateAdCounterHistogramTestCallback updateHistogramCallback = 992 invokeUpdateAdCounterHistogram(adSelectionService, updateHistogramInput); 993 assertTrue(updateHistogramCallback.mIsSuccess); 994 995 // Call set app install advertisers 996 setAppInstallAdvertisers(ImmutableSet.of(WINNER_BUYER), adSelectionService); 997 998 Flags flagsWithFCapDisabled = 999 new AuctionServerE2ETestFlags() { 1000 @Override 1001 public boolean getFledgeFrequencyCapFilteringEnabled() { 1002 return false; 1003 } 1004 1005 @Override 1006 public boolean getFledgeAppInstallFilteringEnabled() { 1007 return true; 1008 } 1009 }; 1010 adFilteringFeatureFactory = 1011 new AdFilteringFeatureFactory( 1012 mAppInstallDao, mFrequencyCapDaoSpy, flagsWithFCapDisabled); 1013 doReturn(flagsWithFCapDisabled).when(FlagsFactory::getFlags); 1014 adSelectionService = 1015 createAdSelectionService( 1016 flagsWithFCapDisabled, 1017 adFilteringFeatureFactory); // create the service again with new flags and 1018 // new feature factory 1019 1020 // Collect device data again and expect one less ads due to app install filter 1021 GetAdSelectionDataInput input2 = 1022 new GetAdSelectionDataInput.Builder() 1023 .setSeller(SELLER) 1024 .setCallerPackageName(CALLER_PACKAGE_NAME) 1025 .build(); 1026 1027 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback2 = 1028 invokeGetAdSelectionData(adSelectionService, input2); 1029 1030 // Since encryption is mocked to do nothing then just passing encrypted byte[] 1031 List<String> adRenderIdsFromBuyerInput2 = 1032 extractCAAdRenderIdListFromBuyerInput( 1033 getAdSelectionDataTestCallback2, 1034 winningCustomAudience.getBuyer(), 1035 winningCustomAudience.getName(), 1036 winningCustomAudience.getOwner()); 1037 // Only app install ad is filtered out since f cap is disabled 1038 Assert.assertEquals(1, adRenderIdsFromBuyerInput2.size()); 1039 1040 // Assert that only ad remaining is the fcap ad 1041 assertThat(adRenderIdsFromBuyerInput2.get(0)).isEqualTo(Integer.toString(sequenceNumber1)); 1042 } 1043 1044 @Test testGetAdSelectionData_withoutEncrypt_validRequest_successPayloadMetricsEnabled()1045 public void testGetAdSelectionData_withoutEncrypt_validRequest_successPayloadMetricsEnabled() 1046 throws Exception { 1047 ArgumentCaptor<GetAdSelectionDataApiCalledStats> argumentCaptorApiCalledStats = 1048 ArgumentCaptor.forClass(GetAdSelectionDataApiCalledStats.class); 1049 1050 ArgumentCaptor<GetAdSelectionDataBuyerInputGeneratedStats> argumentCaptorBuyerInputStats = 1051 ArgumentCaptor.forClass(GetAdSelectionDataBuyerInputGeneratedStats.class); 1052 1053 mFlags = 1054 new AuctionServerE2ETestFlags() { 1055 @Override 1056 public boolean getFledgeAuctionServerGetAdSelectionDataPayloadMetricsEnabled() { 1057 return true; 1058 } 1059 }; 1060 1061 doReturn(mFlags).when(FlagsFactory::getFlags); 1062 // Create a logging latch with count of 3, 2 for buyer input logs and 1 for api logs 1063 CountDownLatch loggingLatch = new CountDownLatch(3); 1064 Answer<Void> countDownAnswer = 1065 unused -> { 1066 loggingLatch.countDown(); 1067 return null; 1068 }; 1069 ExtendedMockito.doAnswer(countDownAnswer) 1070 .when(mAdServicesLoggerMock) 1071 .logGetAdSelectionDataApiCalledStats(any()); 1072 ExtendedMockito.doAnswer(countDownAnswer) 1073 .when(mAdServicesLoggerMock) 1074 .logGetAdSelectionDataBuyerInputGeneratedStats(any()); 1075 1076 mAdSelectionService = createAdSelectionService(); // create the service again with new flags 1077 1078 Map<String, AdTechIdentifier> nameAndBuyersMap = 1079 Map.of( 1080 "Shoes CA of Buyer 1", WINNER_BUYER, 1081 "Shirts CA of Buyer 1", WINNER_BUYER, 1082 "Shoes CA Of Buyer 2", DIFFERENT_BUYER); 1083 Set<AdTechIdentifier> buyers = new HashSet<>(nameAndBuyersMap.values()); 1084 Map<String, DBCustomAudience> namesAndCustomAudiences = 1085 createAndPersistDBCustomAudiences(nameAndBuyersMap); 1086 1087 when(mObliviousHttpEncryptorMock.encryptBytes( 1088 any(byte[].class), anyLong(), anyLong(), any(), any())) 1089 .thenAnswer( 1090 invocation -> 1091 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 1092 1093 GetAdSelectionDataInput input = 1094 new GetAdSelectionDataInput.Builder() 1095 .setSeller(SELLER) 1096 .setCallerPackageName(CALLER_PACKAGE_NAME) 1097 .build(); 1098 1099 GetAdSelectionDataTestCallback callback = 1100 invokeGetAdSelectionData(mAdSelectionService, input); 1101 1102 assertTrue(callback.mIsSuccess); 1103 Assert.assertNotNull(callback.mGetAdSelectionDataResponse); 1104 Assert.assertNotNull(callback.mGetAdSelectionDataResponse.getAdSelectionData()); 1105 1106 byte[] encryptedBytes = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 1107 // Since encryption is mocked to do nothing then just passing encrypted byte[] 1108 Map<AdTechIdentifier, BuyerInput> buyerInputMap = 1109 getBuyerInputMapFromDecryptedBytes(encryptedBytes); 1110 Assert.assertEquals(buyers, buyerInputMap.keySet()); 1111 for (AdTechIdentifier buyer : buyerInputMap.keySet()) { 1112 BuyerInput buyerInput = buyerInputMap.get(buyer); 1113 for (BuyerInput.CustomAudience buyerInputsCA : buyerInput.getCustomAudiencesList()) { 1114 String buyerInputsCAName = buyerInputsCA.getName(); 1115 assertTrue(namesAndCustomAudiences.containsKey(buyerInputsCAName)); 1116 DBCustomAudience deviceCA = namesAndCustomAudiences.get(buyerInputsCAName); 1117 Assert.assertEquals(deviceCA.getName(), buyerInputsCAName); 1118 Assert.assertEquals(deviceCA.getBuyer(), buyer); 1119 assertCasEquals(buyerInputsCA, deviceCA); 1120 } 1121 } 1122 1123 loggingLatch.await(); 1124 // Verify GetAdSelectionDataBuyerInputGeneratedStats metrics 1125 verify(mAdServicesLoggerMock, times(2)) 1126 .logGetAdSelectionDataBuyerInputGeneratedStats( 1127 argumentCaptorBuyerInputStats.capture()); 1128 List<GetAdSelectionDataBuyerInputGeneratedStats> stats = 1129 argumentCaptorBuyerInputStats.getAllValues(); 1130 1131 GetAdSelectionDataBuyerInputGeneratedStats stats1 = stats.get(0); 1132 assertThat(stats1.getNumCustomAudiences()).isEqualTo(1); 1133 assertThat(stats1.getNumCustomAudiencesOmitAds()).isEqualTo(0); 1134 1135 GetAdSelectionDataBuyerInputGeneratedStats stats2 = stats.get(1); 1136 assertThat(stats2.getNumCustomAudiences()).isEqualTo(2); 1137 assertThat(stats2.getNumCustomAudiencesOmitAds()).isEqualTo(0); 1138 1139 // Verify GetAdSelectionDataApiCalledStats metrics 1140 verify(mAdServicesLoggerMock, times(1)) 1141 .logGetAdSelectionDataApiCalledStats(argumentCaptorApiCalledStats.capture()); 1142 assertThat(argumentCaptorApiCalledStats.getValue().getStatusCode()) 1143 .isEqualTo(STATUS_SUCCESS); 1144 assertThat(argumentCaptorApiCalledStats.getValue().getPayloadSizeKb()) 1145 .isEqualTo(encryptedBytes.length / 1000); 1146 assertThat(argumentCaptorApiCalledStats.getValue().getNumBuyers()).isEqualTo(NUM_BUYERS); 1147 assertThat(argumentCaptorApiCalledStats.getValue().getServerAuctionCoordinatorSource()) 1148 .isEqualTo(SERVER_AUCTION_COORDINATOR_SOURCE_UNSET); 1149 } 1150 1151 @Test 1152 public void testGetAdSelectionData_validRequest_successPayloadMetricsEnabled_withSourceCoordinator()1153 testGetAdSelectionData_validRequest_successPayloadMetricsEnabled_withSourceCoordinator() 1154 throws Exception { 1155 ArgumentCaptor<GetAdSelectionDataApiCalledStats> argumentCaptorApiCalledStats = 1156 ArgumentCaptor.forClass(GetAdSelectionDataApiCalledStats.class); 1157 1158 ArgumentCaptor<GetAdSelectionDataBuyerInputGeneratedStats> argumentCaptorBuyerInputStats = 1159 ArgumentCaptor.forClass(GetAdSelectionDataBuyerInputGeneratedStats.class); 1160 1161 mFlags = 1162 new AuctionServerE2ETestFlags() { 1163 @Override 1164 public boolean getFledgeAuctionServerGetAdSelectionDataPayloadMetricsEnabled() { 1165 return true; 1166 } 1167 1168 @Override 1169 public boolean getFledgeAuctionServerKeyFetchMetricsEnabled() { 1170 return true; 1171 } 1172 }; 1173 1174 doReturn(mFlags).when(FlagsFactory::getFlags); 1175 // Create a logging latch with count of 3, 2 for buyer input logs and 1 for api logs 1176 CountDownLatch loggingLatch = new CountDownLatch(3); 1177 Answer<Void> countDownAnswer = 1178 unused -> { 1179 loggingLatch.countDown(); 1180 return null; 1181 }; 1182 ExtendedMockito.doAnswer(countDownAnswer) 1183 .when(mAdServicesLoggerMock) 1184 .logGetAdSelectionDataApiCalledStats(any()); 1185 ExtendedMockito.doAnswer(countDownAnswer) 1186 .when(mAdServicesLoggerMock) 1187 .logGetAdSelectionDataBuyerInputGeneratedStats(any()); 1188 1189 mAdSelectionService = createAdSelectionService(); // create the service again with new flags 1190 1191 Map<String, AdTechIdentifier> nameAndBuyersMap = 1192 Map.of( 1193 "Shoes CA of Buyer 1", WINNER_BUYER, 1194 "Shirts CA of Buyer 1", WINNER_BUYER, 1195 "Shoes CA Of Buyer 2", DIFFERENT_BUYER); 1196 Set<AdTechIdentifier> buyers = new HashSet<>(nameAndBuyersMap.values()); 1197 Map<String, DBCustomAudience> namesAndCustomAudiences = 1198 createAndPersistDBCustomAudiences(nameAndBuyersMap); 1199 1200 when(mObliviousHttpEncryptorMock.encryptBytes( 1201 any(byte[].class), anyLong(), anyLong(), any(), any())) 1202 .thenAnswer( 1203 invocation -> 1204 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 1205 1206 GetAdSelectionDataInput input = 1207 new GetAdSelectionDataInput.Builder() 1208 .setSeller(SELLER) 1209 .setCallerPackageName(CALLER_PACKAGE_NAME) 1210 .build(); 1211 1212 GetAdSelectionDataTestCallback callback = 1213 invokeGetAdSelectionData(mAdSelectionService, input); 1214 1215 assertTrue(callback.mIsSuccess); 1216 Assert.assertNotNull(callback.mGetAdSelectionDataResponse); 1217 Assert.assertNotNull(callback.mGetAdSelectionDataResponse.getAdSelectionData()); 1218 1219 byte[] encryptedBytes = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 1220 // Since encryption is mocked to do nothing then just passing encrypted byte[] 1221 Map<AdTechIdentifier, BuyerInput> buyerInputMap = 1222 getBuyerInputMapFromDecryptedBytes(encryptedBytes); 1223 Assert.assertEquals(buyers, buyerInputMap.keySet()); 1224 for (AdTechIdentifier buyer : buyerInputMap.keySet()) { 1225 BuyerInput buyerInput = buyerInputMap.get(buyer); 1226 for (BuyerInput.CustomAudience buyerInputsCA : buyerInput.getCustomAudiencesList()) { 1227 String buyerInputsCAName = buyerInputsCA.getName(); 1228 assertTrue(namesAndCustomAudiences.containsKey(buyerInputsCAName)); 1229 DBCustomAudience deviceCA = namesAndCustomAudiences.get(buyerInputsCAName); 1230 Assert.assertEquals(deviceCA.getName(), buyerInputsCAName); 1231 Assert.assertEquals(deviceCA.getBuyer(), buyer); 1232 assertCasEquals(buyerInputsCA, deviceCA); 1233 } 1234 } 1235 1236 loggingLatch.await(); 1237 // Verify GetAdSelectionDataBuyerInputGeneratedStats metrics 1238 verify(mAdServicesLoggerMock, times(2)) 1239 .logGetAdSelectionDataBuyerInputGeneratedStats( 1240 argumentCaptorBuyerInputStats.capture()); 1241 List<GetAdSelectionDataBuyerInputGeneratedStats> stats = 1242 argumentCaptorBuyerInputStats.getAllValues(); 1243 1244 GetAdSelectionDataBuyerInputGeneratedStats stats1 = stats.get(0); 1245 assertThat(stats1.getNumCustomAudiences()).isEqualTo(1); 1246 assertThat(stats1.getNumCustomAudiencesOmitAds()).isEqualTo(0); 1247 1248 GetAdSelectionDataBuyerInputGeneratedStats stats2 = stats.get(1); 1249 assertThat(stats2.getNumCustomAudiences()).isEqualTo(2); 1250 assertThat(stats2.getNumCustomAudiencesOmitAds()).isEqualTo(0); 1251 1252 // Verify GetAdSelectionDataApiCalledStats metrics 1253 verify(mAdServicesLoggerMock, times(1)) 1254 .logGetAdSelectionDataApiCalledStats(argumentCaptorApiCalledStats.capture()); 1255 assertThat(argumentCaptorApiCalledStats.getValue().getStatusCode()) 1256 .isEqualTo(STATUS_SUCCESS); 1257 assertThat(argumentCaptorApiCalledStats.getValue().getPayloadSizeKb()) 1258 .isEqualTo(encryptedBytes.length / 1000); 1259 assertThat(argumentCaptorApiCalledStats.getValue().getNumBuyers()).isEqualTo(NUM_BUYERS); 1260 assertThat(argumentCaptorApiCalledStats.getValue().getServerAuctionCoordinatorSource()) 1261 .isEqualTo(SERVER_AUCTION_COORDINATOR_SOURCE_DEFAULT); 1262 } 1263 1264 @Test testGetAdSelectionData_withoutEncrypt_validRequest_successPayloadMetricsDisabled()1265 public void testGetAdSelectionData_withoutEncrypt_validRequest_successPayloadMetricsDisabled() 1266 throws Exception { 1267 mFlags = 1268 new AuctionServerE2ETestFlags() { 1269 @Override 1270 public boolean getFledgeAuctionServerGetAdSelectionDataPayloadMetricsEnabled() { 1271 return false; 1272 } 1273 }; 1274 1275 doReturn(mFlags).when(FlagsFactory::getFlags); 1276 1277 mAdSelectionService = createAdSelectionService(); // create the service again with new flags 1278 1279 Map<String, AdTechIdentifier> nameAndBuyersMap = 1280 Map.of( 1281 "Shoes CA of Buyer 1", WINNER_BUYER, 1282 "Shirts CA of Buyer 1", WINNER_BUYER, 1283 "Shoes CA Of Buyer 2", DIFFERENT_BUYER); 1284 Set<AdTechIdentifier> buyers = new HashSet<>(nameAndBuyersMap.values()); 1285 Map<String, DBCustomAudience> namesAndCustomAudiences = 1286 createAndPersistDBCustomAudiences(nameAndBuyersMap); 1287 1288 when(mObliviousHttpEncryptorMock.encryptBytes( 1289 any(byte[].class), anyLong(), anyLong(), any(), any())) 1290 .thenAnswer( 1291 invocation -> 1292 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 1293 1294 GetAdSelectionDataInput input = 1295 new GetAdSelectionDataInput.Builder() 1296 .setSeller(SELLER) 1297 .setCallerPackageName(CALLER_PACKAGE_NAME) 1298 .build(); 1299 1300 GetAdSelectionDataTestCallback callback = 1301 invokeGetAdSelectionData(mAdSelectionService, input); 1302 1303 assertTrue(callback.mIsSuccess); 1304 Assert.assertNotNull(callback.mGetAdSelectionDataResponse); 1305 Assert.assertNotNull(callback.mGetAdSelectionDataResponse.getAdSelectionData()); 1306 1307 byte[] encryptedBytes = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 1308 // Since encryption is mocked to do nothing then just passing encrypted byte[] 1309 Map<AdTechIdentifier, BuyerInput> buyerInputMap = 1310 getBuyerInputMapFromDecryptedBytes(encryptedBytes); 1311 Assert.assertEquals(buyers, buyerInputMap.keySet()); 1312 for (AdTechIdentifier buyer : buyerInputMap.keySet()) { 1313 BuyerInput buyerInput = buyerInputMap.get(buyer); 1314 for (BuyerInput.CustomAudience buyerInputsCA : buyerInput.getCustomAudiencesList()) { 1315 String buyerInputsCAName = buyerInputsCA.getName(); 1316 assertTrue(namesAndCustomAudiences.containsKey(buyerInputsCAName)); 1317 DBCustomAudience deviceCA = namesAndCustomAudiences.get(buyerInputsCAName); 1318 Assert.assertEquals(deviceCA.getName(), buyerInputsCAName); 1319 Assert.assertEquals(deviceCA.getBuyer(), buyer); 1320 assertCasEquals(buyerInputsCA, deviceCA); 1321 } 1322 } 1323 1324 verify(mAdServicesLoggerMock, never()).logGetAdSelectionDataApiCalledStats(any()); 1325 verify(mAdServicesLoggerMock, never()).logGetAdSelectionDataBuyerInputGeneratedStats(any()); 1326 } 1327 1328 @Test testGetAdSelectionData_withoutEncrypt_validRequestWithOmitAdsInOneCA_success()1329 public void testGetAdSelectionData_withoutEncrypt_validRequestWithOmitAdsInOneCA_success() 1330 throws Exception { 1331 mFlags = 1332 new AuctionServerE2ETestFlags( 1333 /* omitAdsEnabled = */ true); // create flags with omit ads enabled 1334 doReturn(mFlags).when(FlagsFactory::getFlags); 1335 1336 mAdSelectionService = createAdSelectionService(); // create the service again with new flags 1337 1338 Map<String, AdTechIdentifier> nameAndBuyersMap = 1339 Map.of( 1340 "Shoes CA of Buyer 1", WINNER_BUYER, 1341 "Shirts CA of Buyer 1", WINNER_BUYER, 1342 "Shoes CA Of Buyer 2", DIFFERENT_BUYER); 1343 Set<AdTechIdentifier> buyers = new HashSet<>(nameAndBuyersMap.values()); 1344 Map<String, DBCustomAudience> namesAndCustomAudiences = 1345 createAndPersistDBCustomAudiences(nameAndBuyersMap); 1346 1347 String buyer2ShirtsName = "Shirts CA of Buyer 2"; 1348 // Insert a CA with omit ads enabled 1349 DBCustomAudience dbCustomAudienceOmitAdsEnabled = 1350 createAndPersistDBCustomAudienceWithOmitAdsEnabled( 1351 buyer2ShirtsName, DIFFERENT_BUYER); 1352 namesAndCustomAudiences.put(buyer2ShirtsName, dbCustomAudienceOmitAdsEnabled); 1353 1354 when(mObliviousHttpEncryptorMock.encryptBytes( 1355 any(byte[].class), anyLong(), anyLong(), any(), any())) 1356 .thenAnswer( 1357 invocation -> 1358 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 1359 1360 GetAdSelectionDataInput input = 1361 new GetAdSelectionDataInput.Builder() 1362 .setSeller(SELLER) 1363 .setCallerPackageName(CALLER_PACKAGE_NAME) 1364 .build(); 1365 1366 GetAdSelectionDataTestCallback callback = 1367 invokeGetAdSelectionData(mAdSelectionService, input); 1368 1369 assertTrue(callback.mIsSuccess); 1370 Assert.assertNotNull(callback.mGetAdSelectionDataResponse); 1371 Assert.assertNotNull(callback.mGetAdSelectionDataResponse.getAdSelectionData()); 1372 1373 byte[] encryptedBytes = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 1374 // Since encryption is mocked to do nothing then just passing encrypted byte[] 1375 Map<AdTechIdentifier, BuyerInput> buyerInputMap = 1376 getBuyerInputMapFromDecryptedBytes(encryptedBytes); 1377 Assert.assertEquals(buyers, buyerInputMap.keySet()); 1378 for (AdTechIdentifier buyer : buyerInputMap.keySet()) { 1379 BuyerInput buyerInput = buyerInputMap.get(buyer); 1380 for (BuyerInput.CustomAudience buyerInputsCA : buyerInput.getCustomAudiencesList()) { 1381 String buyerInputsCAName = buyerInputsCA.getName(); 1382 assertTrue(namesAndCustomAudiences.containsKey(buyerInputsCAName)); 1383 DBCustomAudience deviceCA = namesAndCustomAudiences.get(buyerInputsCAName); 1384 Assert.assertEquals(deviceCA.getName(), buyerInputsCAName); 1385 Assert.assertEquals(deviceCA.getBuyer(), buyer); 1386 assertCasEquals(buyerInputsCA, deviceCA); 1387 1388 // Buyer 2 shirts ca should not have ad render ids list 1389 if (deviceCA.getBuyer().equals(DIFFERENT_BUYER) 1390 && deviceCA.getName().equals(buyer2ShirtsName)) { 1391 assertThat(buyerInputsCA.getAdRenderIdsList()).isEmpty(); 1392 } else { 1393 // All other cas should have ads 1394 assertThat(buyerInputsCA.getAdRenderIdsList()).isNotEmpty(); 1395 } 1396 } 1397 } 1398 } 1399 1400 @Test testGetAdSelectionData_fCap_success()1401 public void testGetAdSelectionData_fCap_success() throws Exception { 1402 doReturn(mFlags).when(FlagsFactory::getFlags); 1403 1404 when(mObliviousHttpEncryptorMock.encryptBytes( 1405 any(byte[].class), anyLong(), anyLong(), any(), any())) 1406 .thenAnswer( 1407 invocation -> 1408 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 1409 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 1410 .thenAnswer(invocation -> invocation.getArgument(0)); 1411 1412 int sequenceNumber1 = 1; 1413 int sequenceNumber2 = 2; 1414 int filterMaxCount = 1; 1415 List<DBAdData> filterableAds = 1416 List.of( 1417 getFilterableAndServerEligibleFCapAd(sequenceNumber1, filterMaxCount), 1418 getFilterableAndServerEligibleFCapAd(sequenceNumber2, filterMaxCount)); 1419 1420 DBCustomAudience winningCustomAudience = 1421 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 1422 WINNER_BUYER, 1423 WINNING_CUSTOM_AUDIENCE_NAME, 1424 WINNING_CUSTOM_AUDIENCE_OWNER) 1425 .setAds(filterableAds) 1426 .build(); 1427 Assert.assertNotNull(winningCustomAudience.getAds()); 1428 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 1429 winningCustomAudience, Uri.EMPTY, false); 1430 1431 GetAdSelectionDataInput input = 1432 new GetAdSelectionDataInput.Builder() 1433 .setSeller(SELLER) 1434 .setCallerPackageName(CALLER_PACKAGE_NAME) 1435 .build(); 1436 1437 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 1438 invokeGetAdSelectionData(mAdSelectionService, input); 1439 long adSelectionId = 1440 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 1441 assertTrue(getAdSelectionDataTestCallback.mIsSuccess); 1442 1443 // Since encryption is mocked to do nothing then just passing encrypted byte[] 1444 List<String> adRenderIdsFromBuyerInput = 1445 extractCAAdRenderIdListFromBuyerInput( 1446 getAdSelectionDataTestCallback, 1447 winningCustomAudience.getBuyer(), 1448 winningCustomAudience.getName(), 1449 winningCustomAudience.getOwner()); 1450 Assert.assertEquals(filterableAds.size(), adRenderIdsFromBuyerInput.size()); 1451 1452 PersistAdSelectionResultInput persistAdSelectionResultInput = 1453 new PersistAdSelectionResultInput.Builder() 1454 .setAdSelectionId(adSelectionId) 1455 .setSeller(SELLER) 1456 .setAdSelectionResult(prepareAuctionResultBytes()) 1457 .setCallerPackageName(CALLER_PACKAGE_NAME) 1458 .build(); 1459 1460 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 1461 invokePersistAdSelectionResult(mAdSelectionService, persistAdSelectionResultInput); 1462 1463 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 1464 1465 // FCap non-win reporting 1466 UpdateAdCounterHistogramInput updateHistogramInput = 1467 new UpdateAdCounterHistogramInput.Builder( 1468 adSelectionId, 1469 FrequencyCapFilters.AD_EVENT_TYPE_CLICK, 1470 SELLER, 1471 CALLER_PACKAGE_NAME) 1472 .build(); 1473 UpdateAdCounterHistogramTestCallback updateHistogramCallback = 1474 invokeUpdateAdCounterHistogram(mAdSelectionService, updateHistogramInput); 1475 assertTrue(updateHistogramCallback.mIsSuccess); 1476 1477 // Collect device data again and expect one less ads due to FCap filter 1478 GetAdSelectionDataInput input2 = 1479 new GetAdSelectionDataInput.Builder() 1480 .setSeller(SELLER) 1481 .setCallerPackageName(CALLER_PACKAGE_NAME) 1482 .build(); 1483 1484 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback2 = 1485 invokeGetAdSelectionData(mAdSelectionService, input2); 1486 1487 // Since encryption is mocked to do nothing then just passing encrypted byte[] 1488 List<String> adRenderIdsFromBuyerInput2 = 1489 extractCAAdRenderIdListFromBuyerInput( 1490 getAdSelectionDataTestCallback2, 1491 winningCustomAudience.getBuyer(), 1492 winningCustomAudience.getName(), 1493 winningCustomAudience.getOwner()); 1494 // No ads collected for the same CA bc they are filtered out 1495 Assert.assertEquals(filterableAds.size() - 1, adRenderIdsFromBuyerInput2.size()); 1496 } 1497 1498 @Test testGetAdSelectionData_withEncrypt_validRequest_success()1499 public void testGetAdSelectionData_withEncrypt_validRequest_success() throws Exception { 1500 testGetAdSelectionData_withEncryptHelper(mFlags); 1501 } 1502 1503 @Test testGetAdSelectionData_withEncrypt_validRequest_DebugReportingFlagEnabled()1504 public void testGetAdSelectionData_withEncrypt_validRequest_DebugReportingFlagEnabled() 1505 throws Exception { 1506 Flags flags = 1507 new AuctionServerE2ETestFlags( 1508 false, true, AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, false); 1509 1510 testGetAdSelectionData_withEncryptHelper(flags); 1511 } 1512 1513 @Test testGetAdSelectionData_withEncrypt_validRequest_LatDisabled()1514 public void testGetAdSelectionData_withEncrypt_validRequest_LatDisabled() throws Exception { 1515 Flags flags = 1516 new AuctionServerE2ETestFlags( 1517 false, true, AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, false); 1518 mMockAdIdWorker.setResult(MockAdIdWorker.MOCK_AD_ID, false); 1519 1520 testGetAdSelectionData_withEncryptHelper(flags); 1521 } 1522 1523 @Test testGetAdSelectionData_withEncrypt_validRequest_GetAdIdTimeoutException()1524 public void testGetAdSelectionData_withEncrypt_validRequest_GetAdIdTimeoutException() 1525 throws Exception { 1526 Flags flags = 1527 new AuctionServerE2ETestFlags( 1528 false, true, AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, false); 1529 mMockAdIdWorker.setResult(MockAdIdWorker.MOCK_AD_ID, false); 1530 mMockAdIdWorker.setDelay(AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS * 2); 1531 1532 testGetAdSelectionData_withEncryptHelper(flags); 1533 } 1534 1535 @Test testPersistAdSelectionResult_withoutDecrypt_validRequest_success()1536 public void testPersistAdSelectionResult_withoutDecrypt_validRequest_success() 1537 throws Exception { 1538 doReturn(mFlags).when(FlagsFactory::getFlags); 1539 1540 when(mObliviousHttpEncryptorMock.encryptBytes( 1541 any(byte[].class), anyLong(), anyLong(), any(), any())) 1542 .thenAnswer( 1543 invocation -> 1544 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 1545 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 1546 .thenAnswer(invocation -> invocation.getArgument(0)); 1547 1548 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 1549 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 1550 WINNER_BUYER, 1551 WINNING_CUSTOM_AUDIENCE_NAME, 1552 WINNING_CUSTOM_AUDIENCE_OWNER) 1553 .setAds( 1554 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 1555 WINNER_BUYER)) 1556 .build(), 1557 Uri.EMPTY, 1558 false); 1559 1560 GetAdSelectionDataInput input = 1561 new GetAdSelectionDataInput.Builder() 1562 .setSeller(SELLER) 1563 .setCallerPackageName(CALLER_PACKAGE_NAME) 1564 .build(); 1565 1566 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 1567 invokeGetAdSelectionData(mAdSelectionService, input); 1568 long adSelectionId = 1569 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 1570 1571 PersistAdSelectionResultInput persistAdSelectionResultInput = 1572 new PersistAdSelectionResultInput.Builder() 1573 .setAdSelectionId(adSelectionId) 1574 .setSeller(SELLER) 1575 .setAdSelectionResult(prepareAuctionResultBytes()) 1576 .setCallerPackageName(CALLER_PACKAGE_NAME) 1577 .build(); 1578 1579 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 1580 invokePersistAdSelectionResult(mAdSelectionService, persistAdSelectionResultInput); 1581 1582 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 1583 Assert.assertEquals( 1584 WINNER_AD_RENDER_URI, 1585 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 1586 .getAdRenderUri()); 1587 Assert.assertEquals( 1588 adSelectionId, 1589 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 1590 .getAdSelectionId()); 1591 ReportingData reportingData = 1592 mAdSelectionEntryDao.getReportingDataForId(adSelectionId, false); 1593 Assert.assertEquals( 1594 BUYER_REPORTING_URI, reportingData.getBuyerWinReportingUri().toString()); 1595 Assert.assertEquals( 1596 SELLER_REPORTING_URI, reportingData.getSellerWinReportingUri().toString()); 1597 } 1598 1599 @Test testPersistAdSelectionResult_withoutDecrypt_validRequest_successOmitAdsEnabled()1600 public void testPersistAdSelectionResult_withoutDecrypt_validRequest_successOmitAdsEnabled() 1601 throws Exception { 1602 Flags flagWithOmitAdsEnabled = 1603 new AuctionServerE2ETestFlags( 1604 /* omitAdsEnabled = */ true); // create flags with omit ads enabled 1605 doReturn(flagWithOmitAdsEnabled).when(FlagsFactory::getFlags); 1606 1607 when(mObliviousHttpEncryptorMock.encryptBytes( 1608 any(byte[].class), anyLong(), anyLong(), any(), any())) 1609 .thenAnswer( 1610 invocation -> 1611 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 1612 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 1613 .thenAnswer(invocation -> invocation.getArgument(0)); 1614 1615 AdSelectionService adSelectionService = 1616 new AdSelectionServiceImpl( 1617 mAdSelectionEntryDao, 1618 mAppInstallDao, 1619 mCustomAudienceDaoSpy, 1620 mEncodedPayloadDaoSpy, 1621 mFrequencyCapDaoSpy, 1622 mEncryptionKeyDao, 1623 mEnrollmentDao, 1624 mAdServicesHttpsClientSpy, 1625 mDevContextFilterMock, 1626 mLightweightExecutorService, 1627 mBackgroundExecutorService, 1628 mScheduledExecutor, 1629 mContext, 1630 mAdServicesLoggerMock, 1631 flagWithOmitAdsEnabled, 1632 CallingAppUidSupplierProcessImpl.create(), 1633 mFledgeAuthorizationFilterMock, 1634 mAdSelectionServiceFilterMock, 1635 mAdFilteringFeatureFactory, 1636 mConsentManagerMock, 1637 mMultiCloudSupportStrategy, 1638 mAdSelectionDebugReportDaoSpy, 1639 mAdIdFetcher, 1640 mUnusedKAnonSignJoinFactory, 1641 false, 1642 mRetryStrategyFactory, 1643 mConsentedDebugConfigurationGeneratorFactory, 1644 mEgressConfigurationGenerator, 1645 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 1646 1647 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 1648 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 1649 WINNER_BUYER, 1650 WINNING_CUSTOM_AUDIENCE_NAME, 1651 WINNING_CUSTOM_AUDIENCE_OWNER) 1652 .setAds( 1653 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 1654 WINNER_BUYER)) 1655 .setAuctionServerRequestFlags(FLAG_AUCTION_SERVER_REQUEST_OMIT_ADS) 1656 .build(), 1657 Uri.EMPTY, 1658 false); 1659 1660 GetAdSelectionDataInput input = 1661 new GetAdSelectionDataInput.Builder() 1662 .setSeller(SELLER) 1663 .setCallerPackageName(CALLER_PACKAGE_NAME) 1664 .build(); 1665 1666 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 1667 invokeGetAdSelectionData(adSelectionService, input); 1668 1669 byte[] encryptedBytes = 1670 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionData(); 1671 1672 // Since encryption is mocked to do nothing then just passing encrypted byte[] 1673 Map<AdTechIdentifier, BuyerInput> buyerInputMap = 1674 getBuyerInputMapFromDecryptedBytes(encryptedBytes); 1675 1676 // Assert that ads were omitted in buyer input 1677 BuyerInput buyerInput = buyerInputMap.get(WINNER_BUYER); 1678 assertThat(buyerInput.getCustomAudiences(0).getAdRenderIdsCount()).isEqualTo(0); 1679 1680 long adSelectionId = 1681 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 1682 1683 PersistAdSelectionResultInput persistAdSelectionResultInput = 1684 new PersistAdSelectionResultInput.Builder() 1685 .setAdSelectionId(adSelectionId) 1686 .setSeller(SELLER) 1687 .setAdSelectionResult(prepareAuctionResultBytes()) 1688 .setCallerPackageName(CALLER_PACKAGE_NAME) 1689 .build(); 1690 1691 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 1692 invokePersistAdSelectionResult(adSelectionService, persistAdSelectionResultInput); 1693 1694 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 1695 Assert.assertEquals( 1696 WINNER_AD_RENDER_URI, 1697 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 1698 .getAdRenderUri()); 1699 Assert.assertEquals( 1700 adSelectionId, 1701 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 1702 .getAdSelectionId()); 1703 ReportingData reportingData = 1704 mAdSelectionEntryDao.getReportingDataForId(adSelectionId, false); 1705 Assert.assertEquals( 1706 BUYER_REPORTING_URI, reportingData.getBuyerWinReportingUri().toString()); 1707 Assert.assertEquals( 1708 SELLER_REPORTING_URI, reportingData.getSellerWinReportingUri().toString()); 1709 } 1710 1711 @Test 1712 @FlakyTest(bugId = 303119299) testAuctionServerResult_usedInWaterfallMediation_success()1713 public void testAuctionServerResult_usedInWaterfallMediation_success() throws Exception { 1714 Assume.assumeTrue(WebViewSupportUtil.isJSSandboxAvailable(mContext)); 1715 doReturn(mFlags).when(FlagsFactory::getFlags); 1716 1717 Dispatcher dispatcher = 1718 new Dispatcher() { 1719 @Override 1720 public MockResponse dispatch(RecordedRequest request) { 1721 if (request.getPath().equals(SELECTION_WATERFALL_LOGIC_JS_PATH)) { 1722 return new MockResponse().setBody(SELECTION_WATERFALL_LOGIC_JS); 1723 } 1724 return new MockResponse().setResponseCode(404); 1725 } 1726 }; 1727 mockWebServerRule.startMockWebServer(dispatcher); 1728 final String selectionLogicPath = SELECTION_WATERFALL_LOGIC_JS_PATH; 1729 1730 when(mObliviousHttpEncryptorMock.encryptBytes( 1731 any(byte[].class), anyLong(), anyLong(), any(), any())) 1732 .thenAnswer( 1733 invocation -> 1734 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 1735 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 1736 .thenAnswer(invocation -> invocation.getArgument(0)); 1737 1738 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 1739 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 1740 WINNER_BUYER, 1741 WINNING_CUSTOM_AUDIENCE_NAME, 1742 WINNING_CUSTOM_AUDIENCE_OWNER) 1743 .setAds( 1744 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 1745 WINNER_BUYER)) 1746 .build(), 1747 Uri.EMPTY, 1748 false); 1749 1750 GetAdSelectionDataInput input = 1751 new GetAdSelectionDataInput.Builder() 1752 .setSeller(SELLER) 1753 .setCallerPackageName(CALLER_PACKAGE_NAME) 1754 .build(); 1755 1756 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 1757 invokeGetAdSelectionData(mAdSelectionService, input); 1758 long adSelectionId = 1759 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 1760 1761 PersistAdSelectionResultInput persistAdSelectionResultInput = 1762 new PersistAdSelectionResultInput.Builder() 1763 .setAdSelectionId(adSelectionId) 1764 .setSeller(SELLER) 1765 .setAdSelectionResult(prepareAuctionResultBytes()) 1766 .setCallerPackageName(CALLER_PACKAGE_NAME) 1767 .build(); 1768 1769 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 1770 invokePersistAdSelectionResult(mAdSelectionService, persistAdSelectionResultInput); 1771 1772 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 1773 Assert.assertEquals( 1774 WINNER_AD_RENDER_URI, 1775 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 1776 .getAdRenderUri()); 1777 Assert.assertEquals( 1778 adSelectionId, 1779 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 1780 .getAdSelectionId()); 1781 1782 AdSelectionSignals bidFloorSignalsBelowBid = 1783 AdSelectionSignals.fromString( 1784 String.format(BID_FLOOR_SELECTION_SIGNAL_TEMPLATE, BID - 1)); 1785 AdSelectionFromOutcomesInput waterfallReturnsAdSelectionIdInput = 1786 new AdSelectionFromOutcomesInput.Builder() 1787 .setAdSelectionFromOutcomesConfig( 1788 AdSelectionFromOutcomesConfigFixture 1789 .anAdSelectionFromOutcomesConfig( 1790 Collections.singletonList(adSelectionId), 1791 bidFloorSignalsBelowBid, 1792 mockWebServerRule.uriForPath(selectionLogicPath))) 1793 .setCallerPackageName(CALLER_PACKAGE_NAME) 1794 .build(); 1795 AdSelectionFromOutcomesTestCallback waterfallReturnsAdSelectionIdCallback = 1796 invokeAdSelectionFromOutcomes( 1797 mAdSelectionService, waterfallReturnsAdSelectionIdInput); 1798 assertTrue(waterfallReturnsAdSelectionIdCallback.mIsSuccess); 1799 Assert.assertNotNull(waterfallReturnsAdSelectionIdCallback.mAdSelectionResponse); 1800 Assert.assertEquals( 1801 adSelectionId, 1802 waterfallReturnsAdSelectionIdCallback.mAdSelectionResponse.getAdSelectionId()); 1803 1804 AdSelectionSignals bidFloorSignalsAboveBid = 1805 AdSelectionSignals.fromString( 1806 String.format(BID_FLOOR_SELECTION_SIGNAL_TEMPLATE, BID + 1)); 1807 AdSelectionFromOutcomesInput waterfallInputReturnNull = 1808 new AdSelectionFromOutcomesInput.Builder() 1809 .setAdSelectionFromOutcomesConfig( 1810 AdSelectionFromOutcomesConfigFixture 1811 .anAdSelectionFromOutcomesConfig( 1812 Collections.singletonList(adSelectionId), 1813 bidFloorSignalsAboveBid, 1814 mockWebServerRule.uriForPath(selectionLogicPath))) 1815 .setCallerPackageName(CALLER_PACKAGE_NAME) 1816 .build(); 1817 AdSelectionFromOutcomesTestCallback waterfallReturnsNullCallback = 1818 invokeAdSelectionFromOutcomes(mAdSelectionService, waterfallInputReturnNull); 1819 assertTrue(waterfallReturnsNullCallback.mIsSuccess); 1820 Assert.assertNull(waterfallReturnsNullCallback.mAdSelectionResponse); 1821 } 1822 1823 @Test testPersistAdSelectionResult_withDecrypt_validRequest_successEmptyUri()1824 public void testPersistAdSelectionResult_withDecrypt_validRequest_successEmptyUri() 1825 throws Exception { 1826 doReturn(mFlags).when(FlagsFactory::getFlags); 1827 1828 DBEncryptionKey dbEncryptionKey = 1829 DBEncryptionKey.builder() 1830 .setPublicKey("bSHP4J++pRIvnrwusqafzE8GQIzVSqyTTwEudvzc72I=") 1831 .setKeyIdentifier("050bed24-c62f-46e0-a1ad-211361ad771a") 1832 .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION) 1833 .setExpiryTtlSeconds(TimeUnit.DAYS.toSeconds(7)) 1834 .build(); 1835 mAuctionServerEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey)); 1836 String seed = "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"; 1837 byte[] seedBytes = seed.getBytes(StandardCharsets.US_ASCII); 1838 1839 AdSelectionService service = 1840 new AdSelectionServiceImpl( 1841 mAdSelectionEntryDao, 1842 mAppInstallDao, 1843 mCustomAudienceDaoSpy, 1844 mEncodedPayloadDaoSpy, 1845 mFrequencyCapDaoSpy, 1846 mEncryptionKeyDao, 1847 mEnrollmentDao, 1848 mAdServicesHttpsClientSpy, 1849 mDevContextFilterMock, 1850 mLightweightExecutorService, 1851 mBackgroundExecutorService, 1852 mScheduledExecutor, 1853 mContext, 1854 mAdServicesLoggerMock, 1855 mFlags, 1856 CallingAppUidSupplierProcessImpl.create(), 1857 mFledgeAuthorizationFilterMock, 1858 mAdSelectionServiceFilterMock, 1859 mAdFilteringFeatureFactory, 1860 mConsentManagerMock, 1861 MultiCloudTestStrategyFactory.getDisabledTestStrategy( 1862 new ObliviousHttpEncryptorWithSeedImpl( 1863 new AdSelectionEncryptionKeyManager( 1864 mAuctionServerEncryptionKeyDao, 1865 mFlags, 1866 mAdServicesHttpsClientSpy, 1867 mLightweightExecutorService, 1868 mAdServicesLoggerMock), 1869 mEncryptionContextDao, 1870 seedBytes, 1871 mLightweightExecutorService)), 1872 mAdSelectionDebugReportDaoSpy, 1873 mAdIdFetcher, 1874 mUnusedKAnonSignJoinFactory, 1875 false, 1876 mRetryStrategyFactory, 1877 mConsentedDebugConfigurationGeneratorFactory, 1878 mEgressConfigurationGenerator, 1879 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 1880 1881 GetAdSelectionDataInput input = 1882 new GetAdSelectionDataInput.Builder() 1883 .setSeller(SELLER) 1884 .setCallerPackageName(CALLER_PACKAGE_NAME) 1885 .build(); 1886 1887 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 1888 invokeGetAdSelectionData(service, input); 1889 1890 long adSelectionId = 1891 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 1892 byte[] encryptedBytes = 1893 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionData(); 1894 1895 Assert.assertNotNull(encryptedBytes); 1896 Assert.assertNotNull( 1897 mEncryptionContextDao.getEncryptionContext( 1898 adSelectionId, ENCRYPTION_KEY_TYPE_AUCTION)); 1899 1900 String cipherText = 1901 "Lu9TKo4rvstPJt98F1IrLiVUeczFzKuBEJ8jFe1BNXfNImu/lQR0CB8/B1Kur0n1Fxcz" 1902 + "ZQs28dZO2b3jwOaKk5qJgIlcY8Zd1n0Tb/M9vQXcs+d2QbeykmoffEb9kf76zebKDd1" 1903 + "Slb0psgEFtATuqaxaPd9ErumVWXdvD9QuvB6p+URWN+uIv2VhFwmjtf+QE/HZBD6EE+" 1904 + "Ft8ipPiNkNysa7TyL3FLgXO3HGZ2FlQX4GvE5R3br3hPkceY+cplv7ZZDSmc/vfO+7N" 1905 + "4S1XkZ/y0KYuQHXF24ejJ4xmwrJ5L22V3LhTm5euppXerNtUkIqaaYRE3lQ+Glh1rph" 1906 + "dFYZqyoXLhFp6ABzk72lnjMzqdL2hYAVc7agowS29jz6Wo6Tw/pglfls8l1yLntocNE" 1907 + "hEUUvCDl+MQJqrY9gwmbEzrvhwgfl3MbEcShXib3qny+b8/cGEJdQ8sDft1xglbe0a1" 1908 + "rGHZbNgLiprEtVYKyD4dGMcNT7L/RqmygoLRgYzmCBBD7dLgEdYMpRrYh5kmopx4lZJ" 1909 + "6HkltqP0f+OzDLzgA7JCiPsCgiZG7Sx4iRR8p2iwfhKBVZPX1fPORdkRhzjIbhdWxCA" 1910 + "2+GuafjfdY5FBX2F719z0SbkJeaxxrrjKMmpXLzgVT12vVMsDbuFDFhi4i4buI3gMns" 1911 + "g0r4+eeQ+KX1UOMaM6OsGkdt5/aTSsBYTTv8Ikp2ufUEFDnAK4nuoTJlp+gEN3l0K07" 1912 + "/U3b7R4TI="; 1913 1914 byte[] responseBytes = BaseEncoding.base64().decode(cipherText); 1915 1916 PersistAdSelectionResultInput persistAdSelectionResultInput = 1917 new PersistAdSelectionResultInput.Builder() 1918 .setSeller(SELLER) 1919 .setAdSelectionId(adSelectionId) 1920 .setAdSelectionResult(responseBytes) 1921 .setCallerPackageName(CALLER_PACKAGE_NAME) 1922 .build(); 1923 1924 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 1925 invokePersistAdSelectionResult(service, persistAdSelectionResultInput); 1926 1927 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 1928 Assert.assertEquals( 1929 Uri.EMPTY, 1930 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 1931 .getAdRenderUri()); 1932 } 1933 1934 @Test 1935 public void testReportImpression_serverAuction_impressionAndInteractionReportingUnifiedTablesDisabled()1936 testReportImpression_serverAuction_impressionAndInteractionReportingUnifiedTablesDisabled() 1937 throws Exception { 1938 Flags flagsWithUnifiedTablesDisabled = 1939 new AuctionServerE2ETestFlags() { 1940 @Override 1941 public boolean getFledgeOnDeviceAuctionShouldUseUnifiedTables() { 1942 return false; 1943 } 1944 }; 1945 1946 // Re init service with new flags 1947 AdSelectionServiceImpl adSelectionService = 1948 new AdSelectionServiceImpl( 1949 mAdSelectionEntryDao, 1950 mAppInstallDao, 1951 mCustomAudienceDaoSpy, 1952 mEncodedPayloadDaoSpy, 1953 mFrequencyCapDaoSpy, 1954 mEncryptionKeyDao, 1955 mEnrollmentDao, 1956 mAdServicesHttpsClientSpy, 1957 mDevContextFilterMock, 1958 mLightweightExecutorService, 1959 mBackgroundExecutorService, 1960 mScheduledExecutor, 1961 mContext, 1962 mAdServicesLoggerMock, 1963 flagsWithUnifiedTablesDisabled, 1964 CallingAppUidSupplierProcessImpl.create(), 1965 mFledgeAuthorizationFilterMock, 1966 mAdSelectionServiceFilterMock, 1967 mAdFilteringFeatureFactory, 1968 mConsentManagerMock, 1969 mMultiCloudSupportStrategy, 1970 mAdSelectionDebugReportDaoSpy, 1971 mAdIdFetcher, 1972 mUnusedKAnonSignJoinFactory, 1973 /* shouldUseUnifiedTables= */ false, 1974 mRetryStrategyFactory, 1975 mConsentedDebugConfigurationGeneratorFactory, 1976 mEgressConfigurationGenerator, 1977 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 1978 1979 Assume.assumeTrue(WebViewSupportUtil.isJSSandboxAvailable(mContext)); 1980 doReturn(mFlags).when(FlagsFactory::getFlags); 1981 1982 CountDownLatch reportImpressionCountDownLatch = new CountDownLatch(4); 1983 Answer<ListenableFuture<Void>> successReportImpressionGetAnswer = 1984 invocation -> { 1985 reportImpressionCountDownLatch.countDown(); 1986 return Futures.immediateFuture(null); 1987 }; 1988 doAnswer(successReportImpressionGetAnswer) 1989 .when(mAdServicesHttpsClientSpy) 1990 .getAndReadNothing(any(Uri.class), any(DevContext.class)); 1991 doAnswer(successReportImpressionGetAnswer) 1992 .when(mAdServicesHttpsClientSpy) 1993 .postPlainText(any(Uri.class), any(String.class), any(DevContext.class)); 1994 1995 when(mObliviousHttpEncryptorMock.encryptBytes( 1996 any(byte[].class), anyLong(), anyLong(), any(), any())) 1997 .thenAnswer( 1998 invocation -> 1999 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 2000 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 2001 .thenAnswer(invocation -> invocation.getArgument(0)); 2002 2003 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 2004 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 2005 WINNER_BUYER, 2006 WINNING_CUSTOM_AUDIENCE_NAME, 2007 WINNING_CUSTOM_AUDIENCE_OWNER) 2008 .setAds( 2009 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 2010 WINNER_BUYER)) 2011 .build(), 2012 Uri.EMPTY, 2013 false); 2014 2015 GetAdSelectionDataInput input = 2016 new GetAdSelectionDataInput.Builder() 2017 .setSeller(SELLER) 2018 .setCallerPackageName(CALLER_PACKAGE_NAME) 2019 .build(); 2020 2021 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 2022 invokeGetAdSelectionData(adSelectionService, input); 2023 long adSelectionId = 2024 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 2025 2026 PersistAdSelectionResultInput persistAdSelectionResultInput = 2027 new PersistAdSelectionResultInput.Builder() 2028 .setAdSelectionId(adSelectionId) 2029 .setSeller(SELLER) 2030 .setAdSelectionResult(prepareAuctionResultBytes()) 2031 .setCallerPackageName(CALLER_PACKAGE_NAME) 2032 .build(); 2033 2034 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 2035 invokePersistAdSelectionResult(adSelectionService, persistAdSelectionResultInput); 2036 Uri adRenderUriFromPersistAdSelectionResult = 2037 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 2038 .getAdRenderUri(); 2039 Assert.assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 2040 Assert.assertEquals(WINNER_AD_RENDER_URI, adRenderUriFromPersistAdSelectionResult); 2041 Assert.assertEquals( 2042 adSelectionId, 2043 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 2044 .getAdSelectionId()); 2045 Assert.assertEquals( 2046 BUYER_REPORTING_URI, 2047 mAdSelectionEntryDao 2048 .getReportingUris(adSelectionId) 2049 .getBuyerWinReportingUri() 2050 .toString()); 2051 Assert.assertEquals( 2052 SELLER_REPORTING_URI, 2053 mAdSelectionEntryDao 2054 .getReportingUris(adSelectionId) 2055 .getSellerWinReportingUri() 2056 .toString()); 2057 2058 // Invoke report impression 2059 ReportImpressionInput reportImpressionInput = 2060 new ReportImpressionInput.Builder() 2061 .setAdSelectionId(adSelectionId) 2062 .setAdSelectionConfig(AdSelectionConfig.EMPTY) 2063 .setCallerPackageName(CALLER_PACKAGE_NAME) 2064 .build(); 2065 ReportImpressionTestCallback reportImpressionCallback = 2066 invokeReportImpression(adSelectionService, reportImpressionInput); 2067 2068 // Invoke report interaction for buyer 2069 String buyerInteractionData = "buyer-interaction-data"; 2070 ReportInteractionInput reportBuyerInteractionInput = 2071 new ReportInteractionInput.Builder() 2072 .setAdSelectionId(adSelectionId) 2073 .setInteractionKey(BUYER_INTERACTION_KEY) 2074 .setInteractionData(buyerInteractionData) 2075 .setCallerPackageName(CALLER_PACKAGE_NAME) 2076 .setReportingDestinations( 2077 ReportEventRequest.FLAG_REPORTING_DESTINATION_BUYER) 2078 .build(); 2079 ReportInteractionsTestCallback reportBuyerInteractionsCallback = 2080 invokeReportInteractions(adSelectionService, reportBuyerInteractionInput); 2081 2082 // Invoke report interaction for seller 2083 String sellerInteractionData = "seller-interaction-data"; 2084 ReportInteractionInput reportSellerInteractionInput = 2085 new ReportInteractionInput.Builder() 2086 .setAdSelectionId(adSelectionId) 2087 .setInteractionKey(SELLER_INTERACTION_KEY) 2088 .setInteractionData(sellerInteractionData) 2089 .setCallerPackageName(CALLER_PACKAGE_NAME) 2090 .setReportingDestinations( 2091 ReportEventRequest.FLAG_REPORTING_DESTINATION_SELLER) 2092 .build(); 2093 ReportInteractionsTestCallback reportSellerInteractionsCallback = 2094 invokeReportInteractions(adSelectionService, reportSellerInteractionInput); 2095 2096 // Wait for countdown latch 2097 boolean isCountdownDone = 2098 reportImpressionCountDownLatch.await( 2099 COUNTDOWN_LATCH_LIMIT_SECONDS, TimeUnit.SECONDS); 2100 Assert.assertTrue(isCountdownDone); 2101 2102 // Assert report impression 2103 Assert.assertTrue(reportImpressionCallback.mIsSuccess); 2104 verify(mAdServicesHttpsClientSpy, times(1)) 2105 .getAndReadNothing(eq(Uri.parse(SELLER_REPORTING_URI)), any()); 2106 verify(mAdServicesHttpsClientSpy, times(1)) 2107 .getAndReadNothing(eq(Uri.parse(BUYER_REPORTING_URI)), any()); 2108 2109 // Assert report interaction for buyer 2110 Assert.assertTrue(reportBuyerInteractionsCallback.mIsSuccess); 2111 verify(mAdServicesHttpsClientSpy, times(1)) 2112 .postPlainText( 2113 eq(Uri.parse(BUYER_INTERACTION_URI)), eq(buyerInteractionData), any()); 2114 2115 // Assert report interaction for seller 2116 Assert.assertTrue(reportSellerInteractionsCallback.mIsSuccess); 2117 verify(mAdServicesHttpsClientSpy, times(1)) 2118 .postPlainText( 2119 eq(Uri.parse(SELLER_INTERACTION_URI)), eq(sellerInteractionData), any()); 2120 } 2121 2122 @Test 2123 public void testReportImpression_serverAuction_impressionAndInteractionReportingUnifiedTablesEnabled()2124 testReportImpression_serverAuction_impressionAndInteractionReportingUnifiedTablesEnabled() 2125 throws Exception { 2126 Flags flagsWithUnifiedTablesEnabled = 2127 new AuctionServerE2ETestFlags() { 2128 @Override 2129 public boolean getFledgeOnDeviceAuctionShouldUseUnifiedTables() { 2130 return true; 2131 } 2132 }; 2133 2134 // Re init service with new flags 2135 AdSelectionServiceImpl adSelectionService = 2136 new AdSelectionServiceImpl( 2137 mAdSelectionEntryDao, 2138 mAppInstallDao, 2139 mCustomAudienceDaoSpy, 2140 mEncodedPayloadDaoSpy, 2141 mFrequencyCapDaoSpy, 2142 mEncryptionKeyDao, 2143 mEnrollmentDao, 2144 mAdServicesHttpsClientSpy, 2145 mDevContextFilterMock, 2146 mLightweightExecutorService, 2147 mBackgroundExecutorService, 2148 mScheduledExecutor, 2149 mContext, 2150 mAdServicesLoggerMock, 2151 flagsWithUnifiedTablesEnabled, 2152 CallingAppUidSupplierProcessImpl.create(), 2153 mFledgeAuthorizationFilterMock, 2154 mAdSelectionServiceFilterMock, 2155 mAdFilteringFeatureFactory, 2156 mConsentManagerMock, 2157 mMultiCloudSupportStrategy, 2158 mAdSelectionDebugReportDaoSpy, 2159 mAdIdFetcher, 2160 mUnusedKAnonSignJoinFactory, 2161 /* shouldUseUnifiedTables= */ true, 2162 mRetryStrategyFactory, 2163 mConsentedDebugConfigurationGeneratorFactory, 2164 mEgressConfigurationGenerator, 2165 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 2166 2167 Assume.assumeTrue(WebViewSupportUtil.isJSSandboxAvailable(mContext)); 2168 doReturn(mFlags).when(FlagsFactory::getFlags); 2169 2170 CountDownLatch reportImpressionCountDownLatch = new CountDownLatch(4); 2171 Answer<ListenableFuture<Void>> successReportImpressionGetAnswer = 2172 invocation -> { 2173 reportImpressionCountDownLatch.countDown(); 2174 return Futures.immediateFuture(null); 2175 }; 2176 doAnswer(successReportImpressionGetAnswer) 2177 .when(mAdServicesHttpsClientSpy) 2178 .getAndReadNothing(any(Uri.class), any(DevContext.class)); 2179 doAnswer(successReportImpressionGetAnswer) 2180 .when(mAdServicesHttpsClientSpy) 2181 .postPlainText(any(Uri.class), any(String.class), any(DevContext.class)); 2182 2183 when(mObliviousHttpEncryptorMock.encryptBytes( 2184 any(byte[].class), anyLong(), anyLong(), any(), any())) 2185 .thenAnswer( 2186 invocation -> 2187 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 2188 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 2189 .thenAnswer(invocation -> invocation.getArgument(0)); 2190 2191 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 2192 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 2193 WINNER_BUYER, 2194 WINNING_CUSTOM_AUDIENCE_NAME, 2195 WINNING_CUSTOM_AUDIENCE_OWNER) 2196 .setAds( 2197 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 2198 WINNER_BUYER)) 2199 .build(), 2200 Uri.EMPTY, 2201 false); 2202 2203 GetAdSelectionDataInput input = 2204 new GetAdSelectionDataInput.Builder() 2205 .setSeller(SELLER) 2206 .setCallerPackageName(CALLER_PACKAGE_NAME) 2207 .build(); 2208 2209 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 2210 invokeGetAdSelectionData(adSelectionService, input); 2211 long adSelectionId = 2212 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 2213 2214 PersistAdSelectionResultInput persistAdSelectionResultInput = 2215 new PersistAdSelectionResultInput.Builder() 2216 .setAdSelectionId(adSelectionId) 2217 .setSeller(SELLER) 2218 .setAdSelectionResult(prepareAuctionResultBytes()) 2219 .setCallerPackageName(CALLER_PACKAGE_NAME) 2220 .build(); 2221 2222 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 2223 invokePersistAdSelectionResult(adSelectionService, persistAdSelectionResultInput); 2224 Uri adRenderUriFromPersistAdSelectionResult = 2225 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 2226 .getAdRenderUri(); 2227 Assert.assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 2228 Assert.assertEquals(WINNER_AD_RENDER_URI, adRenderUriFromPersistAdSelectionResult); 2229 Assert.assertEquals( 2230 adSelectionId, 2231 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 2232 .getAdSelectionId()); 2233 Assert.assertEquals( 2234 BUYER_REPORTING_URI, 2235 mAdSelectionEntryDao 2236 .getReportingUris(adSelectionId) 2237 .getBuyerWinReportingUri() 2238 .toString()); 2239 Assert.assertEquals( 2240 SELLER_REPORTING_URI, 2241 mAdSelectionEntryDao 2242 .getReportingUris(adSelectionId) 2243 .getSellerWinReportingUri() 2244 .toString()); 2245 2246 // Invoke report impression 2247 ReportImpressionInput reportImpressionInput = 2248 new ReportImpressionInput.Builder() 2249 .setAdSelectionId(adSelectionId) 2250 .setAdSelectionConfig(AdSelectionConfig.EMPTY) 2251 .setCallerPackageName(CALLER_PACKAGE_NAME) 2252 .build(); 2253 ReportImpressionTestCallback reportImpressionCallback = 2254 invokeReportImpression(adSelectionService, reportImpressionInput); 2255 2256 // Invoke report interaction for buyer 2257 String buyerInteractionData = "buyer-interaction-data"; 2258 ReportInteractionInput reportBuyerInteractionInput = 2259 new ReportInteractionInput.Builder() 2260 .setAdSelectionId(adSelectionId) 2261 .setInteractionKey(BUYER_INTERACTION_KEY) 2262 .setInteractionData(buyerInteractionData) 2263 .setCallerPackageName(CALLER_PACKAGE_NAME) 2264 .setReportingDestinations( 2265 ReportEventRequest.FLAG_REPORTING_DESTINATION_BUYER) 2266 .build(); 2267 ReportInteractionsTestCallback reportBuyerInteractionsCallback = 2268 invokeReportInteractions(adSelectionService, reportBuyerInteractionInput); 2269 2270 // Invoke report interaction for seller 2271 String sellerInteractionData = "seller-interaction-data"; 2272 ReportInteractionInput reportSellerInteractionInput = 2273 new ReportInteractionInput.Builder() 2274 .setAdSelectionId(adSelectionId) 2275 .setInteractionKey(SELLER_INTERACTION_KEY) 2276 .setInteractionData(sellerInteractionData) 2277 .setCallerPackageName(CALLER_PACKAGE_NAME) 2278 .setReportingDestinations( 2279 ReportEventRequest.FLAG_REPORTING_DESTINATION_SELLER) 2280 .build(); 2281 ReportInteractionsTestCallback reportSellerInteractionsCallback = 2282 invokeReportInteractions(adSelectionService, reportSellerInteractionInput); 2283 2284 // Wait for countdown latch 2285 boolean isCountdownDone = 2286 reportImpressionCountDownLatch.await( 2287 COUNTDOWN_LATCH_LIMIT_SECONDS, TimeUnit.SECONDS); 2288 Assert.assertTrue(isCountdownDone); 2289 2290 // Assert report impression 2291 Assert.assertTrue(reportImpressionCallback.mIsSuccess); 2292 verify(mAdServicesHttpsClientSpy, times(1)) 2293 .getAndReadNothing(eq(Uri.parse(SELLER_REPORTING_URI)), any()); 2294 verify(mAdServicesHttpsClientSpy, times(1)) 2295 .getAndReadNothing(eq(Uri.parse(BUYER_REPORTING_URI)), any()); 2296 2297 // Assert report interaction for buyer 2298 Assert.assertTrue(reportBuyerInteractionsCallback.mIsSuccess); 2299 verify(mAdServicesHttpsClientSpy, times(1)) 2300 .postPlainText( 2301 eq(Uri.parse(BUYER_INTERACTION_URI)), eq(buyerInteractionData), any()); 2302 2303 // Assert report interaction for seller 2304 Assert.assertTrue(reportSellerInteractionsCallback.mIsSuccess); 2305 verify(mAdServicesHttpsClientSpy, times(1)) 2306 .postPlainText( 2307 eq(Uri.parse(SELLER_INTERACTION_URI)), eq(sellerInteractionData), any()); 2308 } 2309 2310 @Test testReportImpression_serverAuction_sellerReportingFailure_noExceptionThrown()2311 public void testReportImpression_serverAuction_sellerReportingFailure_noExceptionThrown() 2312 throws Exception { 2313 Assume.assumeTrue(WebViewSupportUtil.isJSSandboxAvailable(mContext)); 2314 doReturn(mFlags).when(FlagsFactory::getFlags); 2315 2316 CountDownLatch reportImpressionCountDownLatch = new CountDownLatch(2); 2317 Answer<ListenableFuture<Void>> failedReportImpressionGetAnswer = 2318 invocation -> { 2319 reportImpressionCountDownLatch.countDown(); 2320 return Futures.immediateFailedFuture( 2321 new IllegalStateException("Exception for test!")); 2322 }; 2323 Answer<ListenableFuture<Void>> successReportImpressionGetAnswer = 2324 invocation -> { 2325 reportImpressionCountDownLatch.countDown(); 2326 return Futures.immediateFuture(null); 2327 }; 2328 doAnswer(successReportImpressionGetAnswer) 2329 .when(mAdServicesHttpsClientSpy) 2330 .getAndReadNothing(eq(Uri.parse(BUYER_REPORTING_URI)), any(DevContext.class)); 2331 doAnswer(failedReportImpressionGetAnswer) 2332 .when(mAdServicesHttpsClientSpy) 2333 .getAndReadNothing(eq(Uri.parse(SELLER_REPORTING_URI)), any(DevContext.class)); 2334 2335 when(mObliviousHttpEncryptorMock.encryptBytes( 2336 any(byte[].class), anyLong(), anyLong(), any(), any())) 2337 .thenAnswer( 2338 invocation -> 2339 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 2340 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 2341 .thenAnswer(invocation -> invocation.getArgument(0)); 2342 2343 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 2344 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 2345 WINNER_BUYER, 2346 WINNING_CUSTOM_AUDIENCE_NAME, 2347 WINNING_CUSTOM_AUDIENCE_OWNER) 2348 .setAds( 2349 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 2350 WINNER_BUYER)) 2351 .build(), 2352 Uri.EMPTY, 2353 false); 2354 2355 GetAdSelectionDataInput input = 2356 new GetAdSelectionDataInput.Builder() 2357 .setSeller(SELLER) 2358 .setCallerPackageName(CALLER_PACKAGE_NAME) 2359 .build(); 2360 2361 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 2362 invokeGetAdSelectionData(mAdSelectionService, input); 2363 long adSelectionId = 2364 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 2365 2366 PersistAdSelectionResultInput persistAdSelectionResultInput = 2367 new PersistAdSelectionResultInput.Builder() 2368 .setAdSelectionId(adSelectionId) 2369 .setSeller(SELLER) 2370 .setAdSelectionResult(prepareAuctionResultBytes()) 2371 .setCallerPackageName(CALLER_PACKAGE_NAME) 2372 .build(); 2373 2374 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 2375 invokePersistAdSelectionResult(mAdSelectionService, persistAdSelectionResultInput); 2376 2377 Uri adRenderUriFromPersistAdSelectionResult = 2378 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 2379 .getAdRenderUri(); 2380 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 2381 Assert.assertEquals(WINNER_AD_RENDER_URI, adRenderUriFromPersistAdSelectionResult); 2382 Assert.assertEquals( 2383 adSelectionId, 2384 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 2385 .getAdSelectionId()); 2386 Assert.assertEquals( 2387 BUYER_REPORTING_URI, 2388 mAdSelectionEntryDao 2389 .getReportingUris(adSelectionId) 2390 .getBuyerWinReportingUri() 2391 .toString()); 2392 Assert.assertEquals( 2393 SELLER_REPORTING_URI, 2394 mAdSelectionEntryDao 2395 .getReportingUris(adSelectionId) 2396 .getSellerWinReportingUri() 2397 .toString()); 2398 2399 ReportImpressionInput reportImpressionInput = 2400 new ReportImpressionInput.Builder() 2401 .setAdSelectionId(adSelectionId) 2402 .setAdSelectionConfig(AdSelectionConfig.EMPTY) 2403 .setCallerPackageName(CALLER_PACKAGE_NAME) 2404 .build(); 2405 ReportImpressionTestCallback callback = 2406 invokeReportImpression(mAdSelectionService, reportImpressionInput); 2407 boolean isCountdownDone = 2408 reportImpressionCountDownLatch.await( 2409 COUNTDOWN_LATCH_LIMIT_SECONDS, TimeUnit.SECONDS); 2410 assertTrue(isCountdownDone); 2411 assertTrue(callback.mIsSuccess); 2412 verify(mAdServicesHttpsClientSpy, times(1)) 2413 .getAndReadNothing(eq(Uri.parse(SELLER_REPORTING_URI)), any()); 2414 verify(mAdServicesHttpsClientSpy, times(1)) 2415 .getAndReadNothing(eq(Uri.parse(BUYER_REPORTING_URI)), any()); 2416 } 2417 2418 @Test testReportImpression_serverAuction_buyerReportingFailure_noExceptionThrown()2419 public void testReportImpression_serverAuction_buyerReportingFailure_noExceptionThrown() 2420 throws Exception { 2421 Assume.assumeTrue(WebViewSupportUtil.isJSSandboxAvailable(mContext)); 2422 doReturn(mFlags).when(FlagsFactory::getFlags); 2423 2424 CountDownLatch reportImpressionCountDownLatch = new CountDownLatch(2); 2425 Answer<ListenableFuture<Void>> failedReportImpressionGetAnswer = 2426 invocation -> { 2427 reportImpressionCountDownLatch.countDown(); 2428 return Futures.immediateFailedFuture( 2429 new IllegalStateException("Exception for test!")); 2430 }; 2431 Answer<ListenableFuture<Void>> successReportImpressionGetAnswer = 2432 invocation -> { 2433 reportImpressionCountDownLatch.countDown(); 2434 return Futures.immediateFuture(null); 2435 }; 2436 doAnswer(successReportImpressionGetAnswer) 2437 .when(mAdServicesHttpsClientSpy) 2438 .getAndReadNothing(eq(Uri.parse(SELLER_REPORTING_URI)), any(DevContext.class)); 2439 doAnswer(failedReportImpressionGetAnswer) 2440 .when(mAdServicesHttpsClientSpy) 2441 .getAndReadNothing(eq(Uri.parse(BUYER_REPORTING_URI)), any(DevContext.class)); 2442 2443 when(mObliviousHttpEncryptorMock.encryptBytes( 2444 any(byte[].class), anyLong(), anyLong(), any(), any())) 2445 .thenAnswer( 2446 invocation -> 2447 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 2448 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 2449 .thenAnswer(invocation -> invocation.getArgument(0)); 2450 2451 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 2452 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 2453 WINNER_BUYER, 2454 WINNING_CUSTOM_AUDIENCE_NAME, 2455 WINNING_CUSTOM_AUDIENCE_OWNER) 2456 .setAds( 2457 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 2458 WINNER_BUYER)) 2459 .build(), 2460 Uri.EMPTY, 2461 false); 2462 2463 GetAdSelectionDataInput input = 2464 new GetAdSelectionDataInput.Builder() 2465 .setSeller(SELLER) 2466 .setCallerPackageName(CALLER_PACKAGE_NAME) 2467 .build(); 2468 2469 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 2470 invokeGetAdSelectionData(mAdSelectionService, input); 2471 long adSelectionId = 2472 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 2473 2474 PersistAdSelectionResultInput persistAdSelectionResultInput = 2475 new PersistAdSelectionResultInput.Builder() 2476 .setAdSelectionId(adSelectionId) 2477 .setSeller(SELLER) 2478 .setAdSelectionResult(prepareAuctionResultBytes()) 2479 .setCallerPackageName(CALLER_PACKAGE_NAME) 2480 .build(); 2481 2482 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 2483 invokePersistAdSelectionResult(mAdSelectionService, persistAdSelectionResultInput); 2484 2485 Uri adRenderUriFromPersistAdSelectionResult = 2486 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 2487 .getAdRenderUri(); 2488 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 2489 Assert.assertEquals(WINNER_AD_RENDER_URI, adRenderUriFromPersistAdSelectionResult); 2490 Assert.assertEquals( 2491 adSelectionId, 2492 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 2493 .getAdSelectionId()); 2494 Assert.assertEquals( 2495 BUYER_REPORTING_URI, 2496 mAdSelectionEntryDao 2497 .getReportingUris(adSelectionId) 2498 .getBuyerWinReportingUri() 2499 .toString()); 2500 Assert.assertEquals( 2501 SELLER_REPORTING_URI, 2502 mAdSelectionEntryDao 2503 .getReportingUris(adSelectionId) 2504 .getSellerWinReportingUri() 2505 .toString()); 2506 2507 ReportImpressionInput reportImpressionInput = 2508 new ReportImpressionInput.Builder() 2509 .setAdSelectionId(adSelectionId) 2510 .setAdSelectionConfig(AdSelectionConfig.EMPTY) 2511 .setCallerPackageName(CALLER_PACKAGE_NAME) 2512 .build(); 2513 2514 ReportImpressionTestCallback callback = 2515 invokeReportImpression(mAdSelectionService, reportImpressionInput); 2516 assertTrue(callback.mIsSuccess); 2517 boolean isCountdownDone = 2518 reportImpressionCountDownLatch.await( 2519 COUNTDOWN_LATCH_LIMIT_SECONDS, TimeUnit.SECONDS); 2520 assertTrue(isCountdownDone); 2521 verify(mAdServicesHttpsClientSpy, times(1)) 2522 .getAndReadNothing(eq(Uri.parse(SELLER_REPORTING_URI)), any()); 2523 verify(mAdServicesHttpsClientSpy, times(1)) 2524 .getAndReadNothing(eq(Uri.parse(BUYER_REPORTING_URI)), any()); 2525 } 2526 2527 @Test testPersistAdSelectionResult_withoutDecrypt_savesWinEventsSuccess()2528 public void testPersistAdSelectionResult_withoutDecrypt_savesWinEventsSuccess() 2529 throws Exception { 2530 doReturn(mFlags).when(FlagsFactory::getFlags); 2531 2532 mAdFilteringFeatureFactory = 2533 new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDaoSpy, mFlags); 2534 mAdSelectionService = createAdSelectionService(); 2535 2536 when(mObliviousHttpEncryptorMock.encryptBytes( 2537 any(byte[].class), anyLong(), anyLong(), any(), any())) 2538 .thenAnswer( 2539 invocation -> 2540 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 2541 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 2542 .thenAnswer(invocation -> invocation.getArgument(0)); 2543 2544 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 2545 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 2546 WINNER_BUYER, 2547 WINNING_CUSTOM_AUDIENCE_NAME, 2548 WINNING_CUSTOM_AUDIENCE_OWNER) 2549 .setAds( 2550 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 2551 WINNER_BUYER)) 2552 .build(), 2553 Uri.EMPTY, 2554 false); 2555 2556 GetAdSelectionDataInput input = 2557 new GetAdSelectionDataInput.Builder() 2558 .setSeller(SELLER) 2559 .setCallerPackageName(CALLER_PACKAGE_NAME) 2560 .build(); 2561 2562 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 2563 invokeGetAdSelectionData(mAdSelectionService, input); 2564 assertTrue(getAdSelectionDataTestCallback.mIsSuccess); 2565 long adSelectionId = 2566 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 2567 2568 PersistAdSelectionResultInput persistAdSelectionResultInput = 2569 new PersistAdSelectionResultInput.Builder() 2570 .setAdSelectionId(adSelectionId) 2571 .setSeller(SELLER) 2572 .setAdSelectionResult(prepareAuctionResultBytes()) 2573 .setCallerPackageName(CALLER_PACKAGE_NAME) 2574 .build(); 2575 2576 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 2577 invokePersistAdSelectionResult(mAdSelectionService, persistAdSelectionResultInput); 2578 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 2579 2580 // Assert fcap win reporting 2581 ArgumentCaptor<HistogramEvent> histogramEventArgumentCaptor = 2582 ArgumentCaptor.forClass(HistogramEvent.class); 2583 verify(mFrequencyCapDaoSpy, times(WINNER_AD_COUNTERS.size())) 2584 .insertHistogramEvent( 2585 histogramEventArgumentCaptor.capture(), 2586 anyInt(), 2587 anyInt(), 2588 anyInt(), 2589 anyInt()); 2590 List<HistogramEvent> capturedHistogramEventList = 2591 histogramEventArgumentCaptor.getAllValues(); 2592 Assert.assertEquals( 2593 FrequencyCapFilters.AD_EVENT_TYPE_WIN, 2594 capturedHistogramEventList.get(0).getAdEventType()); 2595 Assert.assertEquals( 2596 WINNER_AD_COUNTERS, 2597 capturedHistogramEventList.stream() 2598 .map(HistogramEvent::getAdCounterKey) 2599 .collect(Collectors.toSet())); 2600 } 2601 2602 @Test testPersistAdSelectionResult_withoutDecrypt_savesNonWinEventsSuccess()2603 public void testPersistAdSelectionResult_withoutDecrypt_savesNonWinEventsSuccess() 2604 throws Exception { 2605 doReturn(mFlags).when(FlagsFactory::getFlags); 2606 2607 mAdFilteringFeatureFactory = 2608 new AdFilteringFeatureFactory(mAppInstallDao, mFrequencyCapDaoSpy, mFlags); 2609 mAdSelectionService = createAdSelectionService(); 2610 2611 when(mObliviousHttpEncryptorMock.encryptBytes( 2612 any(byte[].class), anyLong(), anyLong(), any(), any())) 2613 .thenAnswer( 2614 invocation -> 2615 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 2616 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 2617 .thenAnswer(invocation -> invocation.getArgument(0)); 2618 2619 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 2620 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 2621 WINNER_BUYER, 2622 WINNING_CUSTOM_AUDIENCE_NAME, 2623 WINNING_CUSTOM_AUDIENCE_OWNER) 2624 .setAds( 2625 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 2626 WINNER_BUYER)) 2627 .build(), 2628 Uri.EMPTY, 2629 false); 2630 2631 GetAdSelectionDataInput input = 2632 new GetAdSelectionDataInput.Builder() 2633 .setSeller(SELLER) 2634 .setCallerPackageName(CALLER_PACKAGE_NAME) 2635 .build(); 2636 2637 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 2638 invokeGetAdSelectionData(mAdSelectionService, input); 2639 assertTrue(getAdSelectionDataTestCallback.mIsSuccess); 2640 long adSelectionId = 2641 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 2642 2643 PersistAdSelectionResultInput persistAdSelectionResultInput = 2644 new PersistAdSelectionResultInput.Builder() 2645 .setAdSelectionId(adSelectionId) 2646 .setSeller(SELLER) 2647 .setAdSelectionResult(prepareAuctionResultBytes()) 2648 .setCallerPackageName(CALLER_PACKAGE_NAME) 2649 .build(); 2650 2651 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 2652 invokePersistAdSelectionResult(mAdSelectionService, persistAdSelectionResultInput); 2653 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 2654 2655 // Assert fcap non-win reporting 2656 UpdateAdCounterHistogramInput updateHistogramInput = 2657 new UpdateAdCounterHistogramInput.Builder( 2658 adSelectionId, 2659 FrequencyCapFilters.AD_EVENT_TYPE_VIEW, 2660 SELLER, 2661 CALLER_PACKAGE_NAME) 2662 .build(); 2663 UpdateAdCounterHistogramTestCallback updateHistogramCallback = 2664 invokeUpdateAdCounterHistogram(mAdSelectionService, updateHistogramInput); 2665 2666 int numOfKeys = WINNER_AD_COUNTERS.size(); 2667 ArgumentCaptor<HistogramEvent> histogramEventArgumentCaptor = 2668 ArgumentCaptor.forClass(HistogramEvent.class); 2669 assertTrue(updateHistogramCallback.mIsSuccess); 2670 verify( 2671 mFrequencyCapDaoSpy, 2672 // Each key is reported twice; WIN and VIEW events 2673 times(2 * numOfKeys)) 2674 .insertHistogramEvent( 2675 histogramEventArgumentCaptor.capture(), 2676 anyInt(), 2677 anyInt(), 2678 anyInt(), 2679 anyInt()); 2680 List<HistogramEvent> capturedHistogramEventList = 2681 histogramEventArgumentCaptor.getAllValues(); 2682 Assert.assertEquals( 2683 FrequencyCapFilters.AD_EVENT_TYPE_WIN, 2684 capturedHistogramEventList.get(0).getAdEventType()); 2685 Assert.assertEquals( 2686 FrequencyCapFilters.AD_EVENT_TYPE_VIEW, 2687 capturedHistogramEventList.get(numOfKeys).getAdEventType()); 2688 Assert.assertEquals( 2689 WINNER_AD_COUNTERS, 2690 capturedHistogramEventList.subList(numOfKeys, 2 * numOfKeys).stream() 2691 .map(HistogramEvent::getAdCounterKey) 2692 .collect(Collectors.toSet())); 2693 } 2694 2695 @Test testGetAdSelectionData_withOhttpGatewayDecryption()2696 public void testGetAdSelectionData_withOhttpGatewayDecryption() throws Exception { 2697 doReturn(mFlags).when(FlagsFactory::getFlags); 2698 2699 String winnerBuyerCaOneName = "Shoes CA of Buyer 1"; 2700 String winnerBuyerCaTwoName = "Shirts CA of Buyer 1"; 2701 String differentBuyerCaOneName = "Shoes CA Of Buyer 2"; 2702 2703 Map<String, AdTechIdentifier> nameAndBuyersMap = 2704 Map.of( 2705 winnerBuyerCaOneName, WINNER_BUYER, 2706 winnerBuyerCaTwoName, WINNER_BUYER, 2707 differentBuyerCaOneName, DIFFERENT_BUYER); 2708 createAndPersistDBCustomAudiences(nameAndBuyersMap); 2709 2710 String privateKeyHex = "e7b292f49df28b8065992cdeadbc9d032a0e09e8476cb6d8d507212e7be3b9b4"; 2711 OhttpGatewayPrivateKey privKey = 2712 OhttpGatewayPrivateKey.create( 2713 BaseEncoding.base16().lowerCase().decode(privateKeyHex)); 2714 DBEncryptionKey dbEncryptionKey = 2715 DBEncryptionKey.builder() 2716 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 2717 .setKeyIdentifier("400bed24-c62f-46e0-a1ad-211361ad771a") 2718 .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION) 2719 .setExpiryTtlSeconds(TimeUnit.DAYS.toSeconds(7)) 2720 .build(); 2721 mAuctionServerEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey)); 2722 2723 String seed = "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"; 2724 byte[] seedBytes = seed.getBytes(StandardCharsets.US_ASCII); 2725 AdSelectionService service = 2726 new AdSelectionServiceImpl( 2727 mAdSelectionEntryDao, 2728 mAppInstallDao, 2729 mCustomAudienceDaoSpy, 2730 mEncodedPayloadDaoSpy, 2731 mFrequencyCapDaoSpy, 2732 mEncryptionKeyDao, 2733 mEnrollmentDao, 2734 mAdServicesHttpsClientSpy, 2735 mDevContextFilterMock, 2736 mLightweightExecutorService, 2737 mBackgroundExecutorService, 2738 mScheduledExecutor, 2739 mContext, 2740 mAdServicesLoggerMock, 2741 mFlags, 2742 CallingAppUidSupplierProcessImpl.create(), 2743 mFledgeAuthorizationFilterMock, 2744 mAdSelectionServiceFilterMock, 2745 mAdFilteringFeatureFactory, 2746 mConsentManagerMock, 2747 MultiCloudTestStrategyFactory.getDisabledTestStrategy( 2748 new ObliviousHttpEncryptorWithSeedImpl( 2749 new AdSelectionEncryptionKeyManager( 2750 mAuctionServerEncryptionKeyDao, 2751 mFlags, 2752 mAdServicesHttpsClientSpy, 2753 mLightweightExecutorService, 2754 mAdServicesLoggerMock), 2755 mEncryptionContextDao, 2756 seedBytes, 2757 mLightweightExecutorService)), 2758 mAdSelectionDebugReportDaoSpy, 2759 mAdIdFetcher, 2760 mUnusedKAnonSignJoinFactory, 2761 false, 2762 mRetryStrategyFactory, 2763 mConsentedDebugConfigurationGeneratorFactory, 2764 mEgressConfigurationGenerator, 2765 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 2766 2767 GetAdSelectionDataInput input = 2768 new GetAdSelectionDataInput.Builder() 2769 .setSeller(SELLER) 2770 .setCallerPackageName(CALLER_PACKAGE_NAME) 2771 .build(); 2772 2773 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 2774 assertTrue(callback.mIsSuccess); 2775 byte[] adSelectionResponse = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 2776 2777 ProtectedAuctionInput protectedAuctionInput = 2778 getProtectedAuctionInputFromCipherText(adSelectionResponse, privKey); 2779 2780 Map<String, BuyerInput> buyerInputs = getDecompressedBuyerInputs(protectedAuctionInput); 2781 2782 Assert.assertEquals(CALLER_PACKAGE_NAME, protectedAuctionInput.getPublisherName()); 2783 Assert.assertEquals(2, buyerInputs.size()); 2784 assertTrue(buyerInputs.containsKey(DIFFERENT_BUYER.toString())); 2785 assertTrue(buyerInputs.containsKey(WINNER_BUYER.toString())); 2786 Assert.assertEquals( 2787 1, buyerInputs.get(DIFFERENT_BUYER.toString()).getCustomAudiencesList().size()); 2788 Assert.assertEquals( 2789 2, buyerInputs.get(WINNER_BUYER.toString()).getCustomAudiencesList().size()); 2790 2791 List<String> actual = 2792 Arrays.asList( 2793 buyerInputs.get(WINNER_BUYER.toString()).getCustomAudiences(0).getName(), 2794 buyerInputs.get(WINNER_BUYER.toString()).getCustomAudiences(1).getName()); 2795 List<String> expected = Arrays.asList(winnerBuyerCaOneName, winnerBuyerCaTwoName); 2796 assertTrue(expected.containsAll(actual)); 2797 } 2798 2799 @Test 2800 public void testGetAdSelectionData_withOhttpGatewayDecryption_withServerAuctionMediaTypeChanged()2801 testGetAdSelectionData_withOhttpGatewayDecryption_withServerAuctionMediaTypeChanged() 2802 throws Exception { 2803 mFlags = 2804 new AuctionServerE2ETestFlags() { 2805 @Override 2806 public boolean getFledgeAuctionServerMediaTypeChangeEnabled() { 2807 return true; 2808 } 2809 }; 2810 doReturn(mFlags).when(FlagsFactory::getFlags); 2811 2812 String winnerBuyerCaOneName = "Shoes CA of Buyer 1"; 2813 String winnerBuyerCaTwoName = "Shirts CA of Buyer 1"; 2814 String differentBuyerCaOneName = "Shoes CA Of Buyer 2"; 2815 2816 Map<String, AdTechIdentifier> nameAndBuyersMap = 2817 Map.of( 2818 winnerBuyerCaOneName, WINNER_BUYER, 2819 winnerBuyerCaTwoName, WINNER_BUYER, 2820 differentBuyerCaOneName, DIFFERENT_BUYER); 2821 createAndPersistDBCustomAudiences(nameAndBuyersMap); 2822 2823 String privateKeyHex = "e7b292f49df28b8065992cdeadbc9d032a0e09e8476cb6d8d507212e7be3b9b4"; 2824 OhttpGatewayPrivateKey privKey = 2825 OhttpGatewayPrivateKey.create( 2826 BaseEncoding.base16().lowerCase().decode(privateKeyHex)); 2827 DBEncryptionKey dbEncryptionKey = 2828 DBEncryptionKey.builder() 2829 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 2830 .setKeyIdentifier("400bed24-c62f-46e0-a1ad-211361ad771a") 2831 .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION) 2832 .setExpiryTtlSeconds(TimeUnit.DAYS.toSeconds(7)) 2833 .build(); 2834 mAuctionServerEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey)); 2835 2836 AdSelectionService service = 2837 new AdSelectionServiceImpl( 2838 mAdSelectionEntryDao, 2839 mAppInstallDao, 2840 mCustomAudienceDaoSpy, 2841 mEncodedPayloadDaoSpy, 2842 mFrequencyCapDaoSpy, 2843 mEncryptionKeyDao, 2844 mEnrollmentDao, 2845 mAdServicesHttpsClientSpy, 2846 mDevContextFilterMock, 2847 mLightweightExecutorService, 2848 mBackgroundExecutorService, 2849 mScheduledExecutor, 2850 mContext, 2851 mAdServicesLoggerMock, 2852 mFlags, 2853 CallingAppUidSupplierProcessImpl.create(), 2854 mFledgeAuthorizationFilterMock, 2855 mAdSelectionServiceFilterMock, 2856 mAdFilteringFeatureFactory, 2857 mConsentManagerMock, 2858 MultiCloudTestStrategyFactory.getDisabledTestStrategy( 2859 new ObliviousHttpEncryptorImpl( 2860 new AdSelectionEncryptionKeyManager( 2861 mAuctionServerEncryptionKeyDao, 2862 mFlags, 2863 mAdServicesHttpsClientSpy, 2864 mLightweightExecutorService, 2865 mAdServicesLoggerMock), 2866 mEncryptionContextDao, 2867 mLightweightExecutorService)), 2868 mAdSelectionDebugReportDaoSpy, 2869 mAdIdFetcher, 2870 mUnusedKAnonSignJoinFactory, 2871 false, 2872 mRetryStrategyFactory, 2873 mConsentedDebugConfigurationGeneratorFactory, 2874 mEgressConfigurationGenerator, 2875 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 2876 2877 GetAdSelectionDataInput input = 2878 new GetAdSelectionDataInput.Builder() 2879 .setSeller(SELLER) 2880 .setCallerPackageName(CALLER_PACKAGE_NAME) 2881 .build(); 2882 2883 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 2884 assertTrue(callback.mIsSuccess); 2885 byte[] adSelectionResponse = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 2886 2887 ProtectedAuctionInput protectedAuctionInput = 2888 getProtectedAuctionInputFromCipherText(adSelectionResponse, privKey); 2889 2890 Map<String, BuyerInput> buyerInputs = getDecompressedBuyerInputs(protectedAuctionInput); 2891 2892 Assert.assertEquals(CALLER_PACKAGE_NAME, protectedAuctionInput.getPublisherName()); 2893 Assert.assertEquals(2, buyerInputs.size()); 2894 assertTrue(buyerInputs.containsKey(DIFFERENT_BUYER.toString())); 2895 assertTrue(buyerInputs.containsKey(WINNER_BUYER.toString())); 2896 Assert.assertEquals( 2897 1, buyerInputs.get(DIFFERENT_BUYER.toString()).getCustomAudiencesList().size()); 2898 Assert.assertEquals( 2899 2, buyerInputs.get(WINNER_BUYER.toString()).getCustomAudiencesList().size()); 2900 2901 List<String> actual = 2902 Arrays.asList( 2903 buyerInputs.get(WINNER_BUYER.toString()).getCustomAudiences(0).getName(), 2904 buyerInputs.get(WINNER_BUYER.toString()).getCustomAudiences(1).getName()); 2905 List<String> expected = Arrays.asList(winnerBuyerCaOneName, winnerBuyerCaTwoName); 2906 assertTrue(expected.containsAll(actual)); 2907 } 2908 2909 @Test testGetAdSelectionData_multiCloudOn_success()2910 public void testGetAdSelectionData_multiCloudOn_success() throws Exception { 2911 mFlags = 2912 new AuctionServerE2ETestFlags( 2913 false, 2914 false, 2915 AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 2916 true, 2917 COORDINATOR_ALLOWLIST, 2918 false, 2919 true, 2920 false); 2921 doReturn(mFlags).when(FlagsFactory::getFlags); 2922 2923 String privateKeyHex = "e7b292f49df28b8065992cdeadbc9d032a0e09e8476cb6d8d507212e7be3b9b4"; 2924 OhttpGatewayPrivateKey privKey = 2925 OhttpGatewayPrivateKey.create( 2926 BaseEncoding.base16().lowerCase().decode(privateKeyHex)); 2927 AuctionEncryptionKeyFixture.AuctionKey auctionKey = 2928 AuctionEncryptionKeyFixture.AuctionKey.builder() 2929 .setKeyId("400bed24-c62f-46e0-a1ad-211361ad771a") 2930 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 2931 .build(); 2932 2933 AdServicesHttpClientResponse httpClientResponse = 2934 AuctionEncryptionKeyFixture.mockAuctionKeyFetchResponseWithGivenKey(auctionKey); 2935 when(mMockHttpClient.fetchPayloadWithLogging( 2936 eq(Uri.parse(COORDINATOR_URL)), 2937 eq(DevContext.createForDevOptionsDisabled()), 2938 any(FetchProcessLogger.class))) 2939 .thenReturn(Futures.immediateFuture(httpClientResponse)); 2940 2941 doReturn(mFlags).when(FlagsFactory::getFlags); 2942 2943 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 2944 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 2945 WINNER_BUYER, 2946 WINNING_CUSTOM_AUDIENCE_NAME, 2947 WINNING_CUSTOM_AUDIENCE_OWNER) 2948 .setAds( 2949 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 2950 WINNER_BUYER)) 2951 .build(), 2952 Uri.EMPTY, 2953 false); 2954 2955 AdSelectionService service = 2956 getService( 2957 MultiCloudTestStrategyFactory.getEnabledTestStrategy( 2958 new ObliviousHttpEncryptorImpl( 2959 new ProtectedServersEncryptionConfigManager( 2960 mProtectedServersEncryptionConfigDao, 2961 mFlags, 2962 mMockHttpClient, 2963 mLightweightExecutorService, 2964 mAdServicesLoggerMock), 2965 mEncryptionContextDao, 2966 mLightweightExecutorService), 2967 COORDINATOR_ALLOWLIST)); 2968 2969 GetAdSelectionDataInput input = 2970 new GetAdSelectionDataInput.Builder() 2971 .setSeller(SELLER) 2972 .setCallerPackageName(CALLER_PACKAGE_NAME) 2973 .setCoordinatorOriginUri(Uri.parse(COORDINATOR_HOST)) 2974 .build(); 2975 2976 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 2977 2978 assertTrue(callback.mIsSuccess); 2979 long adSelectionId = callback.mGetAdSelectionDataResponse.getAdSelectionId(); 2980 Assert.assertNotNull( 2981 mEncryptionContextDao.getEncryptionContext( 2982 adSelectionId, ENCRYPTION_KEY_TYPE_AUCTION)); 2983 2984 ProtectedAuctionInput protectedAuctionInput = 2985 getProtectedAuctionInputFromCipherText( 2986 callback.mGetAdSelectionDataResponse.getAdSelectionData(), privKey); 2987 2988 Map<String, BuyerInput> buyerInputs = getDecompressedBuyerInputs(protectedAuctionInput); 2989 2990 Assert.assertEquals(CALLER_PACKAGE_NAME, protectedAuctionInput.getPublisherName()); 2991 Assert.assertEquals(1, buyerInputs.size()); 2992 assertTrue(buyerInputs.containsKey(WINNER_BUYER.toString())); 2993 Assert.assertEquals( 2994 1, buyerInputs.get(WINNER_BUYER.toString()).getCustomAudiencesList().size()); 2995 Assert.assertEquals( 2996 WINNING_CUSTOM_AUDIENCE_NAME, 2997 buyerInputs.get(WINNER_BUYER.toString()).getCustomAudiences(0).getName()); 2998 2999 // assert that we can decrypt server's response as well even when using non-default 3000 // coordinator 3001 byte[] encryptedServerResponse = 3002 ObliviousHttpGateway.encrypt( 3003 privKey, 3004 callback.mGetAdSelectionDataResponse.getAdSelectionData(), 3005 prepareAuctionResultBytes()); 3006 PersistAdSelectionResultInput persistAdSelectionResultInput = 3007 new PersistAdSelectionResultInput.Builder() 3008 .setAdSelectionId(adSelectionId) 3009 .setSeller(SELLER) 3010 .setAdSelectionResult(encryptedServerResponse) 3011 .setCallerPackageName(CALLER_PACKAGE_NAME) 3012 .build(); 3013 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 3014 invokePersistAdSelectionResult(service, persistAdSelectionResultInput); 3015 3016 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 3017 Assert.assertEquals( 3018 adSelectionId, 3019 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 3020 .getAdSelectionId()); 3021 Assert.assertEquals( 3022 WINNER_AD_RENDER_URI, 3023 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 3024 .getAdRenderUri()); 3025 } 3026 3027 @Test testGetAdSelectionData_multiCloudOn_refreshFlagOn_fetchesNewKey()3028 public void testGetAdSelectionData_multiCloudOn_refreshFlagOn_fetchesNewKey() throws Exception { 3029 mFlags = 3030 new AuctionServerE2ETestFlags( 3031 false, 3032 false, 3033 AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 3034 true, 3035 COORDINATOR_ALLOWLIST, 3036 false, 3037 true, 3038 true); 3039 doReturn(mFlags).when(FlagsFactory::getFlags); 3040 3041 String liveKeyId = "400bed24-c62f-46e0-a1ad-211361ad771a"; 3042 String privateKeyHex = "e7b292f49df28b8065992cdeadbc9d032a0e09e8476cb6d8d507212e7be3b9b4"; 3043 OhttpGatewayPrivateKey privKey = 3044 OhttpGatewayPrivateKey.create( 3045 BaseEncoding.base16().lowerCase().decode(privateKeyHex)); 3046 AuctionEncryptionKeyFixture.AuctionKey auctionKey = 3047 AuctionEncryptionKeyFixture.AuctionKey.builder() 3048 .setKeyId(liveKeyId) 3049 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3050 .build(); 3051 3052 AdServicesHttpClientResponse httpClientResponse = 3053 AuctionEncryptionKeyFixture.mockAuctionKeyFetchResponseWithGivenKey(auctionKey); 3054 when(mMockHttpClient.fetchPayloadWithLogging( 3055 eq(Uri.parse(COORDINATOR_URL)), 3056 eq(DevContext.createForDevOptionsDisabled()), 3057 any(FetchProcessLogger.class))) 3058 .thenReturn(Futures.immediateFuture(httpClientResponse)); 3059 3060 String expiredKeyId = "000bed24-c62f-46e0-a1ad-211361ad771a"; 3061 DBProtectedServersEncryptionConfig dbEncryptionKey = 3062 DBProtectedServersEncryptionConfig.builder() 3063 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3064 .setKeyIdentifier(expiredKeyId) 3065 .setCoordinatorUrl(COORDINATOR_URL) 3066 .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION) 3067 .setExpiryTtlSeconds(-1L) 3068 .build(); 3069 mProtectedServersEncryptionConfigDao.insertKeys(ImmutableList.of(dbEncryptionKey)); 3070 3071 List<DBProtectedServersEncryptionConfig> protectedServersEncryptionConfigs = 3072 mProtectedServersEncryptionConfigDao.getLatestExpiryNKeys( 3073 AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION, 3074 COORDINATOR_URL, 3075 100); 3076 Assert.assertEquals(1, protectedServersEncryptionConfigs.size()); 3077 Assert.assertEquals( 3078 expiredKeyId, protectedServersEncryptionConfigs.get(0).getKeyIdentifier()); 3079 3080 doReturn(mFlags).when(FlagsFactory::getFlags); 3081 3082 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 3083 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 3084 WINNER_BUYER, 3085 WINNING_CUSTOM_AUDIENCE_NAME, 3086 WINNING_CUSTOM_AUDIENCE_OWNER) 3087 .setAds( 3088 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 3089 WINNER_BUYER)) 3090 .build(), 3091 Uri.EMPTY, 3092 false); 3093 3094 AdSelectionService service = 3095 getService( 3096 MultiCloudTestStrategyFactory.getEnabledTestStrategy( 3097 new ObliviousHttpEncryptorImpl( 3098 new ProtectedServersEncryptionConfigManager( 3099 mProtectedServersEncryptionConfigDao, 3100 mFlags, 3101 mMockHttpClient, 3102 mLightweightExecutorService, 3103 mAdServicesLoggerMock), 3104 mEncryptionContextDao, 3105 mLightweightExecutorService), 3106 COORDINATOR_ALLOWLIST)); 3107 3108 GetAdSelectionDataInput input = 3109 new GetAdSelectionDataInput.Builder() 3110 .setSeller(SELLER) 3111 .setCallerPackageName(CALLER_PACKAGE_NAME) 3112 .setCoordinatorOriginUri(Uri.parse(COORDINATOR_HOST)) 3113 .build(); 3114 3115 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 3116 3117 Assert.assertTrue(callback.mIsSuccess); 3118 3119 protectedServersEncryptionConfigs = 3120 mProtectedServersEncryptionConfigDao.getLatestExpiryNKeys( 3121 AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION, 3122 COORDINATOR_URL, 3123 100); 3124 3125 // assert that the DB now contains the new keys when refresh keys flag is off 3126 Assert.assertEquals(1, protectedServersEncryptionConfigs.size()); 3127 Assert.assertEquals(liveKeyId, protectedServersEncryptionConfigs.get(0).getKeyIdentifier()); 3128 verify(mMockHttpClient) 3129 .fetchPayloadWithLogging( 3130 eq(Uri.parse(COORDINATOR_URL)), 3131 eq(DevContext.createForDevOptionsDisabled()), 3132 any(FetchProcessLogger.class)); 3133 3134 long adSelectionId = callback.mGetAdSelectionDataResponse.getAdSelectionId(); 3135 3136 // assert that we can decrypt server's response as well even when using non-default 3137 // coordinator 3138 byte[] encryptedServerResponse = 3139 ObliviousHttpGateway.encrypt( 3140 privKey, 3141 callback.mGetAdSelectionDataResponse.getAdSelectionData(), 3142 prepareAuctionResultBytes()); 3143 PersistAdSelectionResultInput persistAdSelectionResultInput = 3144 new PersistAdSelectionResultInput.Builder() 3145 .setAdSelectionId(adSelectionId) 3146 .setSeller(SELLER) 3147 .setAdSelectionResult(encryptedServerResponse) 3148 .setCallerPackageName(CALLER_PACKAGE_NAME) 3149 .build(); 3150 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 3151 invokePersistAdSelectionResult(service, persistAdSelectionResultInput); 3152 3153 Assert.assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 3154 Assert.assertEquals( 3155 adSelectionId, 3156 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 3157 .getAdSelectionId()); 3158 Assert.assertEquals( 3159 WINNER_AD_RENDER_URI, 3160 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 3161 .getAdRenderUri()); 3162 } 3163 3164 @Test testGetAdSelectionData_multiCloudOn_refreshFlagOff_noNetworkCall()3165 public void testGetAdSelectionData_multiCloudOn_refreshFlagOff_noNetworkCall() 3166 throws Exception { 3167 mFlags = 3168 new AuctionServerE2ETestFlags( 3169 false, 3170 false, 3171 AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 3172 true, 3173 COORDINATOR_ALLOWLIST, 3174 false, 3175 true, 3176 false); 3177 doReturn(mFlags).when(FlagsFactory::getFlags); 3178 3179 String liveKeyId = "400bed24-c62f-46e0-a1ad-211361ad771a"; 3180 String privateKeyHex = "e7b292f49df28b8065992cdeadbc9d032a0e09e8476cb6d8d507212e7be3b9b4"; 3181 OhttpGatewayPrivateKey privKey = 3182 OhttpGatewayPrivateKey.create( 3183 BaseEncoding.base16().lowerCase().decode(privateKeyHex)); 3184 AuctionEncryptionKeyFixture.AuctionKey auctionKey = 3185 AuctionEncryptionKeyFixture.AuctionKey.builder() 3186 .setKeyId(liveKeyId) 3187 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3188 .build(); 3189 3190 AdServicesHttpClientResponse httpClientResponse = 3191 AuctionEncryptionKeyFixture.mockAuctionKeyFetchResponseWithGivenKey(auctionKey); 3192 when(mMockHttpClient.fetchPayloadWithLogging( 3193 eq(Uri.parse(COORDINATOR_URL)), 3194 eq(DevContext.createForDevOptionsDisabled()), 3195 any(FetchProcessLogger.class))) 3196 .thenReturn(Futures.immediateFuture(httpClientResponse)); 3197 3198 String expiredKeyId = "000bed24-c62f-46e0-a1ad-211361ad771a"; 3199 DBProtectedServersEncryptionConfig dbEncryptionKey = 3200 DBProtectedServersEncryptionConfig.builder() 3201 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3202 .setKeyIdentifier(expiredKeyId) 3203 .setCoordinatorUrl(COORDINATOR_URL) 3204 .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION) 3205 .setExpiryTtlSeconds(-1L) 3206 .build(); 3207 mProtectedServersEncryptionConfigDao.insertKeys(ImmutableList.of(dbEncryptionKey)); 3208 3209 List<DBProtectedServersEncryptionConfig> protectedServersEncryptionConfigs = 3210 mProtectedServersEncryptionConfigDao.getLatestExpiryNKeys( 3211 AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION, 3212 COORDINATOR_URL, 3213 100); 3214 Assert.assertEquals(1, protectedServersEncryptionConfigs.size()); 3215 Assert.assertEquals( 3216 expiredKeyId, protectedServersEncryptionConfigs.get(0).getKeyIdentifier()); 3217 verify(mMockHttpClient, never()) 3218 .fetchPayloadWithLogging( 3219 eq(Uri.parse(COORDINATOR_URL)), 3220 eq(DevContext.createForDevOptionsDisabled()), 3221 any(FetchProcessLogger.class)); 3222 3223 doReturn(mFlags).when(FlagsFactory::getFlags); 3224 3225 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 3226 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 3227 WINNER_BUYER, 3228 WINNING_CUSTOM_AUDIENCE_NAME, 3229 WINNING_CUSTOM_AUDIENCE_OWNER) 3230 .setAds( 3231 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 3232 WINNER_BUYER)) 3233 .build(), 3234 Uri.EMPTY, 3235 false); 3236 3237 AdSelectionService service = 3238 getService( 3239 MultiCloudTestStrategyFactory.getEnabledTestStrategy( 3240 new ObliviousHttpEncryptorImpl( 3241 new ProtectedServersEncryptionConfigManager( 3242 mProtectedServersEncryptionConfigDao, 3243 mFlags, 3244 mMockHttpClient, 3245 mLightweightExecutorService, 3246 mAdServicesLoggerMock), 3247 mEncryptionContextDao, 3248 mLightweightExecutorService), 3249 COORDINATOR_ALLOWLIST)); 3250 3251 GetAdSelectionDataInput input = 3252 new GetAdSelectionDataInput.Builder() 3253 .setSeller(SELLER) 3254 .setCallerPackageName(CALLER_PACKAGE_NAME) 3255 .setCoordinatorOriginUri(Uri.parse(COORDINATOR_HOST)) 3256 .build(); 3257 3258 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 3259 3260 Assert.assertTrue(callback.mIsSuccess); 3261 3262 protectedServersEncryptionConfigs = 3263 mProtectedServersEncryptionConfigDao.getLatestExpiryNKeys( 3264 AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION, 3265 COORDINATOR_URL, 3266 100); 3267 3268 // assert that the DB still contains the expired keys when refresh keys flag is off 3269 Assert.assertEquals(1, protectedServersEncryptionConfigs.size()); 3270 Assert.assertEquals( 3271 expiredKeyId, protectedServersEncryptionConfigs.get(0).getKeyIdentifier()); 3272 3273 long adSelectionId = callback.mGetAdSelectionDataResponse.getAdSelectionId(); 3274 3275 // assert that we can decrypt server's response as well even when using non-default 3276 // coordinator 3277 byte[] encryptedServerResponse = 3278 ObliviousHttpGateway.encrypt( 3279 privKey, 3280 callback.mGetAdSelectionDataResponse.getAdSelectionData(), 3281 prepareAuctionResultBytes()); 3282 PersistAdSelectionResultInput persistAdSelectionResultInput = 3283 new PersistAdSelectionResultInput.Builder() 3284 .setAdSelectionId(adSelectionId) 3285 .setSeller(SELLER) 3286 .setAdSelectionResult(encryptedServerResponse) 3287 .setCallerPackageName(CALLER_PACKAGE_NAME) 3288 .build(); 3289 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 3290 invokePersistAdSelectionResult(service, persistAdSelectionResultInput); 3291 3292 Assert.assertEquals( 3293 WINNER_AD_RENDER_URI, 3294 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 3295 .getAdRenderUri()); 3296 } 3297 3298 @Test testGetAdSelectionData_multiCloudOff_refreshFlagOn_fetchesNewKey()3299 public void testGetAdSelectionData_multiCloudOff_refreshFlagOn_fetchesNewKey() 3300 throws Exception { 3301 mFlags = 3302 new AuctionServerE2ETestFlags( 3303 false, 3304 false, 3305 AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 3306 false, 3307 COORDINATOR_ALLOWLIST, 3308 false, 3309 true, 3310 true); 3311 doReturn(mFlags).when(FlagsFactory::getFlags); 3312 3313 String liveKeyId = "000bed24-c62f-46e0-a1ad-211361ad771a"; 3314 String privateKeyHex = "e7b292f49df28b8065992cdeadbc9d032a0e09e8476cb6d8d507212e7be3b9b4"; 3315 OhttpGatewayPrivateKey privKey = 3316 OhttpGatewayPrivateKey.create( 3317 BaseEncoding.base16().lowerCase().decode(privateKeyHex)); 3318 AuctionEncryptionKeyFixture.AuctionKey auctionKey = 3319 AuctionEncryptionKeyFixture.AuctionKey.builder() 3320 .setKeyId(liveKeyId) 3321 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3322 .build(); 3323 3324 AdServicesHttpClientResponse httpClientResponse = 3325 AuctionEncryptionKeyFixture.mockAuctionKeyFetchResponseWithGivenKey(auctionKey); 3326 when(mMockHttpClient.fetchPayloadWithLogging( 3327 eq(Uri.parse(DEFAULT_FETCH_URI)), 3328 eq(DevContext.createForDevOptionsDisabled()), 3329 any(FetchProcessLogger.class))) 3330 .thenReturn(Futures.immediateFuture(httpClientResponse)); 3331 3332 String expiredKeyId = "400bed24-c62f-46e0-a1ad-211361ad771a"; 3333 DBEncryptionKey dbEncryptionKey = 3334 DBEncryptionKey.builder() 3335 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3336 .setKeyIdentifier(expiredKeyId) 3337 .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION) 3338 .setExpiryTtlSeconds(-1L) 3339 .build(); 3340 mAuctionServerEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey)); 3341 3342 List<DBEncryptionKey> encryptionConfigs = 3343 mAuctionServerEncryptionKeyDao.getLatestExpiryNKeysOfType( 3344 AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION, 100); 3345 Assert.assertEquals(1, encryptionConfigs.size()); 3346 Assert.assertEquals(expiredKeyId, encryptionConfigs.get(0).getKeyIdentifier()); 3347 3348 doReturn(mFlags).when(FlagsFactory::getFlags); 3349 3350 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 3351 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 3352 WINNER_BUYER, 3353 WINNING_CUSTOM_AUDIENCE_NAME, 3354 WINNING_CUSTOM_AUDIENCE_OWNER) 3355 .setAds( 3356 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 3357 WINNER_BUYER)) 3358 .build(), 3359 Uri.EMPTY, 3360 false); 3361 3362 AdSelectionService service = 3363 getService( 3364 MultiCloudTestStrategyFactory.getDisabledTestStrategy( 3365 new ObliviousHttpEncryptorImpl( 3366 new AdSelectionEncryptionKeyManager( 3367 mAuctionServerEncryptionKeyDao, 3368 mFlags, 3369 mMockHttpClient, 3370 mLightweightExecutorService, 3371 mAdServicesLoggerMock), 3372 mEncryptionContextDao, 3373 mLightweightExecutorService))); 3374 3375 GetAdSelectionDataInput input = 3376 new GetAdSelectionDataInput.Builder() 3377 .setSeller(SELLER) 3378 .setCallerPackageName(CALLER_PACKAGE_NAME) 3379 .setCoordinatorOriginUri(Uri.parse(COORDINATOR_HOST)) 3380 .build(); 3381 3382 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 3383 3384 Assert.assertTrue(callback.mIsSuccess); 3385 3386 encryptionConfigs = 3387 mAuctionServerEncryptionKeyDao.getLatestExpiryNKeysOfType( 3388 AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION, 100); 3389 3390 // assert that the DB now contains the new keys when refresh refresh flag is on 3391 Assert.assertEquals(1, encryptionConfigs.size()); 3392 Assert.assertEquals(liveKeyId, encryptionConfigs.get(0).getKeyIdentifier()); 3393 verify(mMockHttpClient) 3394 .fetchPayloadWithLogging( 3395 eq(Uri.parse(DEFAULT_FETCH_URI)), 3396 eq(DevContext.createForDevOptionsDisabled()), 3397 any(FetchProcessLogger.class)); 3398 3399 long adSelectionId = callback.mGetAdSelectionDataResponse.getAdSelectionId(); 3400 3401 // assert that we can decrypt server's response as well even when using non-default 3402 // coordinator 3403 byte[] encryptedServerResponse = 3404 ObliviousHttpGateway.encrypt( 3405 privKey, 3406 callback.mGetAdSelectionDataResponse.getAdSelectionData(), 3407 prepareAuctionResultBytes()); 3408 PersistAdSelectionResultInput persistAdSelectionResultInput = 3409 new PersistAdSelectionResultInput.Builder() 3410 .setAdSelectionId(adSelectionId) 3411 .setSeller(SELLER) 3412 .setAdSelectionResult(encryptedServerResponse) 3413 .setCallerPackageName(CALLER_PACKAGE_NAME) 3414 .build(); 3415 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 3416 invokePersistAdSelectionResult(service, persistAdSelectionResultInput); 3417 3418 Assert.assertEquals( 3419 WINNER_AD_RENDER_URI, 3420 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 3421 .getAdRenderUri()); 3422 } 3423 3424 @Test testGetAdSelectionData_multiCloudOff_refreshFlagOff_noNetworkCall()3425 public void testGetAdSelectionData_multiCloudOff_refreshFlagOff_noNetworkCall() 3426 throws Exception { 3427 mFlags = 3428 new AuctionServerE2ETestFlags( 3429 false, 3430 false, 3431 AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 3432 false, 3433 COORDINATOR_ALLOWLIST, 3434 false, 3435 true, 3436 false); 3437 doReturn(mFlags).when(FlagsFactory::getFlags); 3438 3439 String liveKeyId = "400bed24-c62f-46e0-a1ad-211361ad771a"; 3440 String privateKeyHex = "e7b292f49df28b8065992cdeadbc9d032a0e09e8476cb6d8d507212e7be3b9b4"; 3441 OhttpGatewayPrivateKey privKey = 3442 OhttpGatewayPrivateKey.create( 3443 BaseEncoding.base16().lowerCase().decode(privateKeyHex)); 3444 AuctionEncryptionKeyFixture.AuctionKey auctionKey = 3445 AuctionEncryptionKeyFixture.AuctionKey.builder() 3446 .setKeyId(liveKeyId) 3447 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3448 .build(); 3449 3450 AdServicesHttpClientResponse httpClientResponse = 3451 AuctionEncryptionKeyFixture.mockAuctionKeyFetchResponseWithGivenKey(auctionKey); 3452 when(mMockHttpClient.fetchPayloadWithLogging( 3453 eq(Uri.parse(COORDINATOR_URL)), 3454 eq(DevContext.createForDevOptionsDisabled()), 3455 any(FetchProcessLogger.class))) 3456 .thenReturn(Futures.immediateFuture(httpClientResponse)); 3457 3458 String expiredKeyId = "000bed24-c62f-46e0-a1ad-211361ad771a"; 3459 DBEncryptionKey dbEncryptionKey = 3460 DBEncryptionKey.builder() 3461 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3462 .setKeyIdentifier(expiredKeyId) 3463 .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION) 3464 .setExpiryTtlSeconds(-1L) 3465 .build(); 3466 mAuctionServerEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey)); 3467 3468 List<DBEncryptionKey> encryptionConfigs = 3469 mAuctionServerEncryptionKeyDao.getLatestExpiryNKeysOfType( 3470 AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION, 100); 3471 Assert.assertEquals(1, encryptionConfigs.size()); 3472 Assert.assertEquals(expiredKeyId, encryptionConfigs.get(0).getKeyIdentifier()); 3473 3474 doReturn(mFlags).when(FlagsFactory::getFlags); 3475 3476 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 3477 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId( 3478 WINNER_BUYER, 3479 WINNING_CUSTOM_AUDIENCE_NAME, 3480 WINNING_CUSTOM_AUDIENCE_OWNER) 3481 .setAds( 3482 DBAdDataFixture.getValidDbAdDataListByBuyerWithAdRenderId( 3483 WINNER_BUYER)) 3484 .build(), 3485 Uri.EMPTY, 3486 false); 3487 3488 AdSelectionService service = 3489 getService( 3490 MultiCloudTestStrategyFactory.getDisabledTestStrategy( 3491 new ObliviousHttpEncryptorImpl( 3492 new AdSelectionEncryptionKeyManager( 3493 mAuctionServerEncryptionKeyDao, 3494 mFlags, 3495 mMockHttpClient, 3496 mLightweightExecutorService, 3497 mAdServicesLoggerMock), 3498 mEncryptionContextDao, 3499 mLightweightExecutorService))); 3500 3501 GetAdSelectionDataInput input = 3502 new GetAdSelectionDataInput.Builder() 3503 .setSeller(SELLER) 3504 .setCallerPackageName(CALLER_PACKAGE_NAME) 3505 .setCoordinatorOriginUri(Uri.parse(COORDINATOR_HOST)) 3506 .build(); 3507 3508 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 3509 3510 Assert.assertTrue(callback.mIsSuccess); 3511 3512 encryptionConfigs = 3513 mAuctionServerEncryptionKeyDao.getLatestExpiryNKeysOfType( 3514 AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION, 100); 3515 3516 // assert that the DB now contains the new keys when refresh refresh flag is on 3517 Assert.assertEquals(1, encryptionConfigs.size()); 3518 Assert.assertEquals(expiredKeyId, encryptionConfigs.get(0).getKeyIdentifier()); 3519 verify(mMockHttpClient, never()) 3520 .fetchPayloadWithLogging( 3521 eq(Uri.parse(DEFAULT_FETCH_URI)), 3522 eq(DevContext.createForDevOptionsDisabled()), 3523 any(FetchProcessLogger.class)); 3524 3525 long adSelectionId = callback.mGetAdSelectionDataResponse.getAdSelectionId(); 3526 3527 // assert that we can decrypt server's response as well even when using non-default 3528 // coordinator 3529 byte[] encryptedServerResponse = 3530 ObliviousHttpGateway.encrypt( 3531 privKey, 3532 callback.mGetAdSelectionDataResponse.getAdSelectionData(), 3533 prepareAuctionResultBytes()); 3534 PersistAdSelectionResultInput persistAdSelectionResultInput = 3535 new PersistAdSelectionResultInput.Builder() 3536 .setAdSelectionId(adSelectionId) 3537 .setSeller(SELLER) 3538 .setAdSelectionResult(encryptedServerResponse) 3539 .setCallerPackageName(CALLER_PACKAGE_NAME) 3540 .build(); 3541 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 3542 invokePersistAdSelectionResult(service, persistAdSelectionResultInput); 3543 3544 Assert.assertEquals( 3545 WINNER_AD_RENDER_URI, 3546 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 3547 .getAdRenderUri()); 3548 } 3549 3550 @Test testGetAdSelectionData_multiCloudOn_nullCoordinator_success()3551 public void testGetAdSelectionData_multiCloudOn_nullCoordinator_success() throws Exception { 3552 mFlags = 3553 new AuctionServerE2ETestFlags( 3554 false, 3555 false, 3556 AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 3557 true, 3558 COORDINATOR_ALLOWLIST, 3559 false, 3560 true, 3561 false); 3562 doReturn(mFlags).when(FlagsFactory::getFlags); 3563 3564 AuctionEncryptionKeyFixture.AuctionKey auctionKey = 3565 AuctionEncryptionKeyFixture.AuctionKey.builder() 3566 .setKeyId("400bed24-c62f-46e0-a1ad-211361ad771a") 3567 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3568 .build(); 3569 3570 AdServicesHttpClientResponse httpClientResponse = 3571 AuctionEncryptionKeyFixture.mockAuctionKeyFetchResponseWithGivenKey(auctionKey); 3572 when(mMockHttpClient.fetchPayloadWithLogging( 3573 eq(Uri.parse(DEFAULT_FETCH_URI)), 3574 eq(DevContext.createForDevOptionsDisabled()), 3575 any(FetchProcessLogger.class))) 3576 .thenReturn(Futures.immediateFuture(httpClientResponse)); 3577 3578 doReturn(mFlags).when(FlagsFactory::getFlags); 3579 3580 Map<String, AdTechIdentifier> nameAndBuyersMap = 3581 Map.of( 3582 "Shoes CA of Buyer 1", WINNER_BUYER, 3583 "Shirts CA of Buyer 1", WINNER_BUYER, 3584 "Shoes CA Of Buyer 2", DIFFERENT_BUYER); 3585 createAndPersistDBCustomAudiences(nameAndBuyersMap); 3586 3587 AdSelectionService service = 3588 getService( 3589 MultiCloudTestStrategyFactory.getEnabledTestStrategy( 3590 new ObliviousHttpEncryptorImpl( 3591 new ProtectedServersEncryptionConfigManager( 3592 mProtectedServersEncryptionConfigDao, 3593 mFlags, 3594 mMockHttpClient, 3595 mLightweightExecutorService, 3596 mAdServicesLoggerMock), 3597 mEncryptionContextDao, 3598 mLightweightExecutorService), 3599 COORDINATOR_ALLOWLIST)); 3600 3601 GetAdSelectionDataInput input = 3602 new GetAdSelectionDataInput.Builder() 3603 .setSeller(SELLER) 3604 .setCallerPackageName(CALLER_PACKAGE_NAME) 3605 .build(); 3606 3607 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 3608 3609 assertTrue(callback.mIsSuccess); 3610 Assert.assertNotNull(callback.mGetAdSelectionDataResponse); 3611 Assert.assertNotNull(callback.mGetAdSelectionDataResponse.getAdSelectionData()); 3612 long adSelectionId = callback.mGetAdSelectionDataResponse.getAdSelectionId(); 3613 byte[] encryptedBytes = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 3614 Assert.assertNotNull(encryptedBytes); 3615 Assert.assertNotNull( 3616 mEncryptionContextDao.getEncryptionContext( 3617 adSelectionId, ENCRYPTION_KEY_TYPE_AUCTION)); 3618 } 3619 3620 @Test testGetAdSelectionData_multiCloudOn_inValidCoordinator_fails()3621 public void testGetAdSelectionData_multiCloudOn_inValidCoordinator_fails() throws Exception { 3622 mFlags = 3623 new AuctionServerE2ETestFlags( 3624 false, 3625 false, 3626 AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 3627 true, 3628 COORDINATOR_ALLOWLIST, 3629 false, 3630 true, 3631 false); 3632 doReturn(mFlags).when(FlagsFactory::getFlags); 3633 3634 AuctionEncryptionKeyFixture.AuctionKey auctionKey = 3635 AuctionEncryptionKeyFixture.AuctionKey.builder() 3636 .setKeyId("400bed24-c62f-46e0-a1ad-211361ad771a") 3637 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3638 .build(); 3639 3640 AdServicesHttpClientResponse httpClientResponse = 3641 AuctionEncryptionKeyFixture.mockAuctionKeyFetchResponseWithGivenKey(auctionKey); 3642 when(mMockHttpClient.fetchPayloadWithLogging( 3643 eq(Uri.parse(COORDINATOR_URL)), 3644 eq(DevContext.createForDevOptionsDisabled()), 3645 any(FetchProcessLogger.class))) 3646 .thenReturn(Futures.immediateFuture(httpClientResponse)); 3647 3648 doReturn(mFlags).when(FlagsFactory::getFlags); 3649 3650 Map<String, AdTechIdentifier> nameAndBuyersMap = 3651 Map.of( 3652 "Shoes CA of Buyer 1", WINNER_BUYER, 3653 "Shirts CA of Buyer 1", WINNER_BUYER, 3654 "Shoes CA Of Buyer 2", DIFFERENT_BUYER); 3655 createAndPersistDBCustomAudiences(nameAndBuyersMap); 3656 3657 AdSelectionService service = 3658 getService( 3659 MultiCloudTestStrategyFactory.getEnabledTestStrategy( 3660 new ObliviousHttpEncryptorImpl( 3661 new ProtectedServersEncryptionConfigManager( 3662 mProtectedServersEncryptionConfigDao, 3663 mFlags, 3664 mMockHttpClient, 3665 mLightweightExecutorService, 3666 mAdServicesLoggerMock), 3667 mEncryptionContextDao, 3668 mLightweightExecutorService), 3669 COORDINATOR_ALLOWLIST)); 3670 3671 GetAdSelectionDataInput input = 3672 new GetAdSelectionDataInput.Builder() 3673 .setSeller(SELLER) 3674 .setCallerPackageName(CALLER_PACKAGE_NAME) 3675 .setCoordinatorOriginUri(Uri.parse("a/b")) 3676 .build(); 3677 3678 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 3679 3680 Assert.assertFalse(callback.mIsSuccess); 3681 Assert.assertEquals(STATUS_INVALID_ARGUMENT, callback.mFledgeErrorResponse.getStatusCode()); 3682 } 3683 3684 @Test testGetAdSelectionData_multiCloudOff_nullCoordinator_success()3685 public void testGetAdSelectionData_multiCloudOff_nullCoordinator_success() throws Exception { 3686 mFlags = 3687 new AuctionServerE2ETestFlags( 3688 false, 3689 false, 3690 AUCTION_SERVER_AD_ID_FETCHER_TIMEOUT_MS, 3691 false, 3692 COORDINATOR_ALLOWLIST, 3693 false, 3694 true, 3695 false); 3696 doReturn(mFlags).when(FlagsFactory::getFlags); 3697 3698 AuctionEncryptionKeyFixture.AuctionKey auctionKey = 3699 AuctionEncryptionKeyFixture.AuctionKey.builder() 3700 .setKeyId("400bed24-c62f-46e0-a1ad-211361ad771a") 3701 .setPublicKey("87ey8XZPXAd+/+ytKv2GFUWW5j9zdepSJ2G4gebDwyM=") 3702 .build(); 3703 3704 AdServicesHttpClientResponse httpClientResponse = 3705 AuctionEncryptionKeyFixture.mockAuctionKeyFetchResponseWithGivenKey(auctionKey); 3706 when(mMockHttpClient.fetchPayloadWithLogging( 3707 eq(Uri.parse(DEFAULT_FETCH_URI)), 3708 eq(DevContext.createForDevOptionsDisabled()), 3709 any(FetchProcessLogger.class))) 3710 .thenReturn(Futures.immediateFuture(httpClientResponse)); 3711 3712 doReturn(mFlags).when(FlagsFactory::getFlags); 3713 3714 Map<String, AdTechIdentifier> nameAndBuyersMap = 3715 Map.of( 3716 "Shoes CA of Buyer 1", WINNER_BUYER, 3717 "Shirts CA of Buyer 1", WINNER_BUYER, 3718 "Shoes CA Of Buyer 2", DIFFERENT_BUYER); 3719 createAndPersistDBCustomAudiences(nameAndBuyersMap); 3720 3721 AdSelectionService service = 3722 getService( 3723 MultiCloudTestStrategyFactory.getDisabledTestStrategy( 3724 (new ObliviousHttpEncryptorImpl( 3725 new AdSelectionEncryptionKeyManager( 3726 mAuctionServerEncryptionKeyDao, 3727 mFlags, 3728 mMockHttpClient, 3729 mLightweightExecutorService, 3730 mAdServicesLoggerMock), 3731 mEncryptionContextDao, 3732 mLightweightExecutorService)))); 3733 3734 GetAdSelectionDataInput input = 3735 new GetAdSelectionDataInput.Builder() 3736 .setSeller(SELLER) 3737 .setCallerPackageName(CALLER_PACKAGE_NAME) 3738 .setCoordinatorOriginUri(Uri.parse(COORDINATOR_HOST)) 3739 .build(); 3740 3741 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 3742 3743 Assert.assertTrue(callback.mIsSuccess); 3744 Assert.assertNotNull(callback.mGetAdSelectionDataResponse); 3745 Assert.assertNotNull(callback.mGetAdSelectionDataResponse.getAdSelectionData()); 3746 long adSelectionId = callback.mGetAdSelectionDataResponse.getAdSelectionId(); 3747 byte[] encryptedBytes = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 3748 Assert.assertNotNull(encryptedBytes); 3749 Assert.assertNotNull( 3750 mEncryptionContextDao.getEncryptionContext( 3751 adSelectionId, ENCRYPTION_KEY_TYPE_AUCTION)); 3752 } 3753 3754 @Test testGetAdSelectionData_withoutEncrypt_protectedSignals_success()3755 public void testGetAdSelectionData_withoutEncrypt_protectedSignals_success() throws Exception { 3756 mFlags = new AuctionServerE2ETestFlags(); 3757 doReturn(mFlags).when(FlagsFactory::getFlags); 3758 3759 byte[] encodedSignals = new byte[] {2, 3, 5, 7, 11, 13, 17, 19}; 3760 createAndPersistEncodedSignals(WINNER_BUYER, encodedSignals); 3761 3762 when(mObliviousHttpEncryptorMock.encryptBytes( 3763 any(byte[].class), anyLong(), anyLong(), any(), any())) 3764 .thenAnswer( 3765 invocation -> 3766 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 3767 3768 GetAdSelectionDataInput input = 3769 new GetAdSelectionDataInput.Builder() 3770 .setSeller(SELLER) 3771 .setCallerPackageName(CALLER_PACKAGE_NAME) 3772 .build(); 3773 3774 GetAdSelectionDataTestCallback callback = 3775 invokeGetAdSelectionData(mAdSelectionService, input); 3776 3777 assertTrue(callback.mIsSuccess); 3778 Assert.assertNotNull(callback.mGetAdSelectionDataResponse); 3779 Assert.assertNotNull(callback.mGetAdSelectionDataResponse.getAdSelectionData()); 3780 3781 byte[] encryptedBytes = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 3782 // Since encryption is mocked to do nothing then just passing encrypted byte[] 3783 Map<AdTechIdentifier, BuyerInput> buyerInputMap = 3784 getBuyerInputMapFromDecryptedBytes(encryptedBytes); 3785 Assert.assertEquals(1, buyerInputMap.keySet().size()); 3786 Assert.assertTrue(buyerInputMap.keySet().contains(WINNER_BUYER)); 3787 BuyerInput buyerInput = buyerInputMap.get(WINNER_BUYER); 3788 ProtectedAppSignals protectedAppSignals = buyerInput.getProtectedAppSignals(); 3789 Assert.assertArrayEquals( 3790 encodedSignals, protectedAppSignals.getAppInstallSignals().toByteArray()); 3791 } 3792 3793 @Test testPersistAdSelectionResult_withoutDecrypt_validSignalsRequest_success()3794 public void testPersistAdSelectionResult_withoutDecrypt_validSignalsRequest_success() 3795 throws Exception { 3796 mFlags = new AuctionServerE2ETestFlags(); 3797 doReturn(mFlags).when(FlagsFactory::getFlags); 3798 3799 when(mObliviousHttpEncryptorMock.encryptBytes( 3800 any(byte[].class), anyLong(), anyLong(), any(), any())) 3801 .thenAnswer( 3802 invocation -> 3803 FluentFuture.from(immediateFuture(invocation.getArgument(0)))); 3804 when(mObliviousHttpEncryptorMock.decryptBytes(any(byte[].class), anyLong())) 3805 .thenAnswer(invocation -> invocation.getArgument(0)); 3806 3807 byte[] encodedSignals = new byte[] {2, 3, 5, 7, 11, 13, 17, 19}; 3808 createAndPersistEncodedSignals(WINNER_BUYER, encodedSignals); 3809 3810 GetAdSelectionDataInput input = 3811 new GetAdSelectionDataInput.Builder() 3812 .setSeller(SELLER) 3813 .setCallerPackageName(CALLER_PACKAGE_NAME) 3814 .build(); 3815 3816 GetAdSelectionDataTestCallback getAdSelectionDataTestCallback = 3817 invokeGetAdSelectionData(mAdSelectionService, input); 3818 long adSelectionId = 3819 getAdSelectionDataTestCallback.mGetAdSelectionDataResponse.getAdSelectionId(); 3820 3821 PersistAdSelectionResultInput persistAdSelectionResultInput = 3822 new PersistAdSelectionResultInput.Builder() 3823 .setAdSelectionId(adSelectionId) 3824 .setSeller(SELLER) 3825 .setAdSelectionResult(prepareAuctionResultBytesPas()) 3826 .setCallerPackageName(CALLER_PACKAGE_NAME) 3827 .build(); 3828 3829 PersistAdSelectionResultTestCallback persistAdSelectionResultTestCallback = 3830 invokePersistAdSelectionResult(mAdSelectionService, persistAdSelectionResultInput); 3831 3832 assertTrue(persistAdSelectionResultTestCallback.mIsSuccess); 3833 Assert.assertEquals( 3834 WINNER_AD_RENDER_URI, 3835 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 3836 .getAdRenderUri()); 3837 Assert.assertEquals( 3838 adSelectionId, 3839 persistAdSelectionResultTestCallback.mPersistAdSelectionResultResponse 3840 .getAdSelectionId()); 3841 ReportingData reportingData = 3842 mAdSelectionEntryDao.getReportingDataForId(adSelectionId, false); 3843 Assert.assertEquals( 3844 BUYER_REPORTING_URI, reportingData.getBuyerWinReportingUri().toString()); 3845 Assert.assertEquals( 3846 SELLER_REPORTING_URI, reportingData.getSellerWinReportingUri().toString()); 3847 } 3848 getService(MultiCloudSupportStrategy multiCloudSupportStrategy)3849 private AdSelectionServiceImpl getService(MultiCloudSupportStrategy multiCloudSupportStrategy) { 3850 return new AdSelectionServiceImpl( 3851 mAdSelectionEntryDao, 3852 mAppInstallDao, 3853 mCustomAudienceDaoSpy, 3854 mEncodedPayloadDaoSpy, 3855 mFrequencyCapDaoSpy, 3856 mEncryptionKeyDao, 3857 mEnrollmentDao, 3858 mAdServicesHttpsClientSpy, 3859 mDevContextFilterMock, 3860 mLightweightExecutorService, 3861 mBackgroundExecutorService, 3862 mScheduledExecutor, 3863 mContext, 3864 mAdServicesLoggerMock, 3865 mFlags, 3866 CallingAppUidSupplierProcessImpl.create(), 3867 mFledgeAuthorizationFilterMock, 3868 mAdSelectionServiceFilterMock, 3869 mAdFilteringFeatureFactory, 3870 mConsentManagerMock, 3871 multiCloudSupportStrategy, 3872 mAdSelectionDebugReportDaoSpy, 3873 mAdIdFetcher, 3874 mUnusedKAnonSignJoinFactory, 3875 false, 3876 mRetryStrategyFactory, 3877 mConsentedDebugConfigurationGeneratorFactory, 3878 mEgressConfigurationGenerator, 3879 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 3880 } 3881 getProtectedAuctionInputFromCipherText( byte[] adSelectionResponse, OhttpGatewayPrivateKey privKey)3882 private ProtectedAuctionInput getProtectedAuctionInputFromCipherText( 3883 byte[] adSelectionResponse, OhttpGatewayPrivateKey privKey) throws Exception { 3884 byte[] decrypted = ObliviousHttpGateway.decrypt(privKey, adSelectionResponse); 3885 AuctionServerPayloadExtractor extractor = 3886 AuctionServerPayloadFormatterFactory.createPayloadExtractor( 3887 AuctionServerPayloadFormatterV0.VERSION, mAdServicesLoggerMock); 3888 AuctionServerPayloadUnformattedData unformatted = 3889 extractor.extract(AuctionServerPayloadFormattedData.create(decrypted)); 3890 return ProtectedAuctionInput.parseFrom(unformatted.getData()); 3891 } 3892 getDecompressedBuyerInputs( ProtectedAuctionInput protectedAuctionInput)3893 private Map<String, BuyerInput> getDecompressedBuyerInputs( 3894 ProtectedAuctionInput protectedAuctionInput) throws Exception { 3895 Map<String, BuyerInput> decompressedBuyerInputs = new HashMap<>(); 3896 for (Map.Entry<String, ByteString> entry : 3897 protectedAuctionInput.getBuyerInputMap().entrySet()) { 3898 byte[] buyerInputBytes = entry.getValue().toByteArray(); 3899 AuctionServerDataCompressor compressor = 3900 AuctionServerDataCompressorFactory.getDataCompressor( 3901 AuctionServerDataCompressorGzip.VERSION); 3902 byte[] decompressed = 3903 compressor 3904 .decompress( 3905 AuctionServerDataCompressor.CompressedData.create( 3906 buyerInputBytes)) 3907 .getData(); 3908 decompressedBuyerInputs.put(entry.getKey(), BuyerInput.parseFrom(decompressed)); 3909 } 3910 return decompressedBuyerInputs; 3911 } 3912 setAppInstallAdvertisers( Set<AdTechIdentifier> advertisers, AdSelectionService adSelectionService)3913 private void setAppInstallAdvertisers( 3914 Set<AdTechIdentifier> advertisers, AdSelectionService adSelectionService) 3915 throws RemoteException, InterruptedException { 3916 SetAppInstallAdvertisersInput setAppInstallAdvertisersInput = 3917 new SetAppInstallAdvertisersInput.Builder() 3918 .setAdvertisers(advertisers) 3919 .setCallerPackageName(CommonFixture.TEST_PACKAGE_NAME) 3920 .build(); 3921 AppInstallResultCapturingCallback appInstallCallback = 3922 invokeSetAppInstallAdvertisers(setAppInstallAdvertisersInput, adSelectionService); 3923 assertTrue( 3924 "App Install call failed with: " + appInstallCallback.getException(), 3925 appInstallCallback.isSuccess()); 3926 } 3927 invokeSetAppInstallAdvertisers( SetAppInstallAdvertisersInput input, AdSelectionService adSelectionService)3928 private AppInstallResultCapturingCallback invokeSetAppInstallAdvertisers( 3929 SetAppInstallAdvertisersInput input, AdSelectionService adSelectionService) 3930 throws RemoteException, InterruptedException { 3931 CountDownLatch appInstallDone = new CountDownLatch(1); 3932 AppInstallResultCapturingCallback appInstallCallback = 3933 new AppInstallResultCapturingCallback(appInstallDone); 3934 adSelectionService.setAppInstallAdvertisers(input, appInstallCallback); 3935 assertTrue(appInstallDone.await(5, TimeUnit.SECONDS)); 3936 return appInstallCallback; 3937 } 3938 testGetAdSelectionData_withEncryptHelper(Flags flags)3939 private void testGetAdSelectionData_withEncryptHelper(Flags flags) throws Exception { 3940 doReturn(flags).when(FlagsFactory::getFlags); 3941 3942 Map<String, AdTechIdentifier> nameAndBuyersMap = 3943 Map.of( 3944 "Shoes CA of Buyer 1", WINNER_BUYER, 3945 "Shirts CA of Buyer 1", WINNER_BUYER, 3946 "Shoes CA Of Buyer 2", DIFFERENT_BUYER); 3947 createAndPersistDBCustomAudiences(nameAndBuyersMap); 3948 3949 DBEncryptionKey dbEncryptionKey = 3950 DBEncryptionKey.builder() 3951 .setPublicKey("bSHP4J++pRIvnrwusqafzE8GQIzVSqyTTwEudvzc72I=") 3952 .setKeyIdentifier("050bed24-c62f-46e0-a1ad-211361ad771a") 3953 .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION) 3954 .setExpiryTtlSeconds(TimeUnit.DAYS.toSeconds(7)) 3955 .build(); 3956 mAuctionServerEncryptionKeyDao.insertAllKeys(ImmutableList.of(dbEncryptionKey)); 3957 3958 String seed = "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"; 3959 byte[] seedBytes = seed.getBytes(StandardCharsets.US_ASCII); 3960 AdSelectionService service = 3961 new AdSelectionServiceImpl( 3962 mAdSelectionEntryDao, 3963 mAppInstallDao, 3964 mCustomAudienceDaoSpy, 3965 mEncodedPayloadDaoSpy, 3966 mFrequencyCapDaoSpy, 3967 mEncryptionKeyDao, 3968 mEnrollmentDao, 3969 mAdServicesHttpsClientSpy, 3970 mDevContextFilterMock, 3971 mLightweightExecutorService, 3972 mBackgroundExecutorService, 3973 mScheduledExecutor, 3974 mContext, 3975 mAdServicesLoggerMock, 3976 flags, 3977 CallingAppUidSupplierProcessImpl.create(), 3978 mFledgeAuthorizationFilterMock, 3979 mAdSelectionServiceFilterMock, 3980 mAdFilteringFeatureFactory, 3981 mConsentManagerMock, 3982 MultiCloudTestStrategyFactory.getDisabledTestStrategy( 3983 new ObliviousHttpEncryptorWithSeedImpl( 3984 new AdSelectionEncryptionKeyManager( 3985 mAuctionServerEncryptionKeyDao, 3986 mFlags, 3987 mAdServicesHttpsClientSpy, 3988 mLightweightExecutorService, 3989 mAdServicesLoggerMock), 3990 mEncryptionContextDao, 3991 seedBytes, 3992 mLightweightExecutorService)), 3993 mAdSelectionDebugReportDaoSpy, 3994 mAdIdFetcher, 3995 mUnusedKAnonSignJoinFactory, 3996 false, 3997 mRetryStrategyFactory, 3998 mConsentedDebugConfigurationGeneratorFactory, 3999 mEgressConfigurationGenerator, 4000 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 4001 4002 GetAdSelectionDataInput input = 4003 new GetAdSelectionDataInput.Builder() 4004 .setSeller(SELLER) 4005 .setCallerPackageName(CALLER_PACKAGE_NAME) 4006 .build(); 4007 4008 GetAdSelectionDataTestCallback callback = invokeGetAdSelectionData(service, input); 4009 4010 assertTrue(callback.mIsSuccess); 4011 Assert.assertNotNull(callback.mGetAdSelectionDataResponse); 4012 Assert.assertNotNull(callback.mGetAdSelectionDataResponse.getAdSelectionData()); 4013 long adSelectionId = callback.mGetAdSelectionDataResponse.getAdSelectionId(); 4014 byte[] encryptedBytes = callback.mGetAdSelectionDataResponse.getAdSelectionData(); 4015 Assert.assertNotNull(encryptedBytes); 4016 Assert.assertNotNull( 4017 mEncryptionContextDao.getEncryptionContext( 4018 adSelectionId, ENCRYPTION_KEY_TYPE_AUCTION)); 4019 } 4020 4021 /** 4022 * Asserts if a {@link BuyerInput.CustomAudience} and {@link DBCustomAudience} objects are 4023 * equal. 4024 */ assertCasEquals( BuyerInput.CustomAudience buyerInputCA, DBCustomAudience dbCustomAudience)4025 private void assertCasEquals( 4026 BuyerInput.CustomAudience buyerInputCA, DBCustomAudience dbCustomAudience) { 4027 Assert.assertEquals(buyerInputCA.getName(), dbCustomAudience.getName()); 4028 Assert.assertNotNull(dbCustomAudience.getTrustedBiddingData()); 4029 Assert.assertEquals( 4030 buyerInputCA.getBiddingSignalsKeysList(), 4031 dbCustomAudience.getTrustedBiddingData().getKeys()); 4032 Assert.assertNotNull(dbCustomAudience.getUserBiddingSignals()); 4033 Assert.assertEquals( 4034 buyerInputCA.getUserBiddingSignals(), 4035 dbCustomAudience.getUserBiddingSignals().toString()); 4036 } 4037 createAdSelectionService()4038 private AdSelectionService createAdSelectionService() { 4039 return new AdSelectionServiceImpl( 4040 mAdSelectionEntryDao, 4041 mAppInstallDao, 4042 mCustomAudienceDaoSpy, 4043 mEncodedPayloadDaoSpy, 4044 mFrequencyCapDaoSpy, 4045 mEncryptionKeyDao, 4046 mEnrollmentDao, 4047 mAdServicesHttpsClientSpy, 4048 mDevContextFilterMock, 4049 mLightweightExecutorService, 4050 mBackgroundExecutorService, 4051 mScheduledExecutor, 4052 mContext, 4053 mAdServicesLoggerMock, 4054 mFlags, 4055 CallingAppUidSupplierProcessImpl.create(), 4056 mFledgeAuthorizationFilterMock, 4057 mAdSelectionServiceFilterMock, 4058 mAdFilteringFeatureFactory, 4059 mConsentManagerMock, 4060 mMultiCloudSupportStrategy, 4061 mAdSelectionDebugReportDaoSpy, 4062 mAdIdFetcher, 4063 mUnusedKAnonSignJoinFactory, 4064 false, 4065 mRetryStrategyFactory, 4066 mConsentedDebugConfigurationGeneratorFactory, 4067 mEgressConfigurationGenerator, 4068 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 4069 } 4070 createAdSelectionService( Flags flags, AdFilteringFeatureFactory filteringFeatureFactory)4071 private AdSelectionService createAdSelectionService( 4072 Flags flags, AdFilteringFeatureFactory filteringFeatureFactory) { 4073 return new AdSelectionServiceImpl( 4074 mAdSelectionEntryDao, 4075 mAppInstallDao, 4076 mCustomAudienceDaoSpy, 4077 mEncodedPayloadDaoSpy, 4078 mFrequencyCapDaoSpy, 4079 mEncryptionKeyDao, 4080 mEnrollmentDao, 4081 mAdServicesHttpsClientSpy, 4082 mDevContextFilterMock, 4083 mLightweightExecutorService, 4084 mBackgroundExecutorService, 4085 mScheduledExecutor, 4086 mContext, 4087 mAdServicesLoggerMock, 4088 flags, 4089 CallingAppUidSupplierProcessImpl.create(), 4090 mFledgeAuthorizationFilterMock, 4091 mAdSelectionServiceFilterMock, 4092 filteringFeatureFactory, 4093 mConsentManagerMock, 4094 mMultiCloudSupportStrategy, 4095 mAdSelectionDebugReportDaoSpy, 4096 mAdIdFetcher, 4097 mUnusedKAnonSignJoinFactory, 4098 false, 4099 mRetryStrategyFactory, 4100 mConsentedDebugConfigurationGeneratorFactory, 4101 mEgressConfigurationGenerator, 4102 CONSOLE_MESSAGE_IN_LOGS_ENABLED); 4103 } 4104 getBuyerInputMapFromDecryptedBytes( byte[] decryptedBytes)4105 private Map<AdTechIdentifier, BuyerInput> getBuyerInputMapFromDecryptedBytes( 4106 byte[] decryptedBytes) { 4107 try { 4108 byte[] unformatted = 4109 mPayloadExtractor 4110 .extract(AuctionServerPayloadFormattedData.create(decryptedBytes)) 4111 .getData(); 4112 ProtectedAuctionInput protectedAuctionInput = 4113 ProtectedAuctionInput.parseFrom(unformatted); 4114 Map<String, ByteString> buyerInputBytesMap = protectedAuctionInput.getBuyerInputMap(); 4115 Function<Map.Entry<String, ByteString>, AdTechIdentifier> entryToAdTechIdentifier = 4116 entry -> AdTechIdentifier.fromString(entry.getKey()); 4117 Function<Map.Entry<String, ByteString>, BuyerInput> entryToBuyerInput = 4118 entry -> { 4119 try { 4120 byte[] compressedBytes = entry.getValue().toByteArray(); 4121 byte[] decompressedBytes = 4122 mDataCompressor 4123 .decompress( 4124 AuctionServerDataCompressor.CompressedData 4125 .create(compressedBytes)) 4126 .getData(); 4127 return BuyerInput.parseFrom(decompressedBytes); 4128 } catch (InvalidProtocolBufferException e) { 4129 throw new UncheckedIOException(e); 4130 } 4131 }; 4132 return buyerInputBytesMap.entrySet().stream() 4133 .collect(Collectors.toMap(entryToAdTechIdentifier, entryToBuyerInput)); 4134 } catch (InvalidProtocolBufferException e) { 4135 throw new UncheckedIOException(e); 4136 } 4137 } 4138 createAndPersistDBCustomAudiences( Map<String, AdTechIdentifier> nameAndBuyers)4139 private Map<String, DBCustomAudience> createAndPersistDBCustomAudiences( 4140 Map<String, AdTechIdentifier> nameAndBuyers) { 4141 Map<String, DBCustomAudience> customAudiences = new HashMap<>(); 4142 for (Map.Entry<String, AdTechIdentifier> entry : nameAndBuyers.entrySet()) { 4143 AdTechIdentifier buyer = entry.getValue(); 4144 String name = entry.getKey(); 4145 DBCustomAudience thisCustomAudience = 4146 DBCustomAudienceFixture.getValidBuilderByBuyerWithAdRenderId(buyer, name) 4147 .build(); 4148 customAudiences.put(name, thisCustomAudience); 4149 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience( 4150 thisCustomAudience, Uri.EMPTY, false); 4151 } 4152 return customAudiences; 4153 } 4154 createAndPersistEncodedSignals( AdTechIdentifier buyer, byte[] signals)4155 private DBEncodedPayload createAndPersistEncodedSignals( 4156 AdTechIdentifier buyer, byte[] signals) { 4157 DBEncodedPayload payload = 4158 DBEncodedPayload.builder() 4159 .setEncodedPayload(signals) 4160 .setCreationTime(Instant.now()) 4161 .setBuyer(buyer) 4162 .setVersion(0) 4163 .build(); 4164 mEncodedPayloadDaoSpy.persistEncodedPayload(payload); 4165 return payload; 4166 } 4167 createAndPersistDBCustomAudienceWithOmitAdsEnabled( String name, AdTechIdentifier buyer)4168 private DBCustomAudience createAndPersistDBCustomAudienceWithOmitAdsEnabled( 4169 String name, AdTechIdentifier buyer) { 4170 DBCustomAudience thisCustomAudience = 4171 DBCustomAudienceFixture.getValidBuilderByBuyerWithOmitAdsEnabled(buyer, name) 4172 .build(); 4173 mCustomAudienceDaoSpy.insertOrOverwriteCustomAudience(thisCustomAudience, Uri.EMPTY, false); 4174 return thisCustomAudience; 4175 } 4176 prepareAuctionResultBytes()4177 private byte[] prepareAuctionResultBytes() { 4178 byte[] auctionResultBytes = AUCTION_RESULT.toByteArray(); 4179 AuctionServerDataCompressor.CompressedData compressedData = 4180 mDataCompressor.compress( 4181 AuctionServerDataCompressor.UncompressedData.create(auctionResultBytes)); 4182 AuctionServerPayloadFormattedData formattedData = 4183 mPayloadFormatter.apply( 4184 AuctionServerPayloadUnformattedData.create(compressedData.getData()), 4185 AuctionServerDataCompressorGzip.VERSION); 4186 return formattedData.getData(); 4187 } 4188 prepareAuctionResultBytesPas()4189 private byte[] prepareAuctionResultBytesPas() { 4190 byte[] auctionResultBytes = AUCTION_RESULT_PAS.toByteArray(); 4191 AuctionServerDataCompressor.CompressedData compressedData = 4192 mDataCompressor.compress( 4193 AuctionServerDataCompressor.UncompressedData.create(auctionResultBytes)); 4194 AuctionServerPayloadFormattedData formattedData = 4195 mPayloadFormatter.apply( 4196 AuctionServerPayloadUnformattedData.create(compressedData.getData()), 4197 AuctionServerDataCompressorGzip.VERSION); 4198 return formattedData.getData(); 4199 } 4200 extractCAAdRenderIdListFromBuyerInput( GetAdSelectionDataTestCallback callback, AdTechIdentifier buyer, String name, String owner)4201 private List<String> extractCAAdRenderIdListFromBuyerInput( 4202 GetAdSelectionDataTestCallback callback, 4203 AdTechIdentifier buyer, 4204 String name, 4205 String owner) { 4206 List<BuyerInput.CustomAudience> customAudienceList = 4207 getBuyerInputMapFromDecryptedBytes( 4208 callback.mGetAdSelectionDataResponse.getAdSelectionData()) 4209 .get(buyer) 4210 .getCustomAudiencesList(); 4211 Optional<BuyerInput.CustomAudience> winningCustomAudienceFromBuyerInputOption = 4212 customAudienceList.stream() 4213 .filter(ca -> ca.getName().equals(name) && ca.getOwner().equals(owner)) 4214 .findFirst(); 4215 Assert.assertTrue(winningCustomAudienceFromBuyerInputOption.isPresent()); 4216 return winningCustomAudienceFromBuyerInputOption.get().getAdRenderIdsList(); 4217 } 4218 getFilterableAndServerEligibleFCapAd(int sequenceNumber, int filterMaxCount)4219 private DBAdData getFilterableAndServerEligibleFCapAd(int sequenceNumber, int filterMaxCount) { 4220 KeyedFrequencyCap fCap = 4221 new KeyedFrequencyCap.Builder(sequenceNumber, filterMaxCount, ONE_DAY_DURATION) 4222 .build(); 4223 FrequencyCapFilters clickEventFilter = 4224 new FrequencyCapFilters.Builder() 4225 .setKeyedFrequencyCapsForClickEvents(ImmutableList.of(fCap)) 4226 .build(); 4227 return getValidDbAdDataNoFiltersBuilder(WINNER_BUYER, sequenceNumber) 4228 .setAdCounterKeys(ImmutableSet.<Integer>builder().add(sequenceNumber).build()) 4229 .setAdFilters( 4230 new AdFilters.Builder().setFrequencyCapFilters(clickEventFilter).build()) 4231 .setAdRenderId(String.valueOf(sequenceNumber)) 4232 .build(); 4233 } 4234 getFilterableAndServerEligibleAppInstallAd(int sequenceNumber)4235 private DBAdData getFilterableAndServerEligibleAppInstallAd(int sequenceNumber) { 4236 return getValidDbAdDataNoFiltersBuilder(WINNER_BUYER, sequenceNumber) 4237 .setAdCounterKeys(ImmutableSet.<Integer>builder().add(sequenceNumber).build()) 4238 .setAdFilters( 4239 new AdFilters.Builder().setAppInstallFilters(CURRENT_APP_FILTER).build()) 4240 .setAdRenderId(String.valueOf(sequenceNumber)) 4241 .build(); 4242 } 4243 invokeGetAdSelectionData( AdSelectionService service, GetAdSelectionDataInput input)4244 public GetAdSelectionDataTestCallback invokeGetAdSelectionData( 4245 AdSelectionService service, GetAdSelectionDataInput input) 4246 throws RemoteException, InterruptedException { 4247 CountDownLatch countDownLatch = new CountDownLatch(1); 4248 GetAdSelectionDataTestCallback callback = 4249 new GetAdSelectionDataTestCallback(countDownLatch); 4250 service.getAdSelectionData(input, sCallerMetadata, callback); 4251 callback.mCountDownLatch.await(); 4252 return callback; 4253 } 4254 invokePersistAdSelectionResult( AdSelectionService service, PersistAdSelectionResultInput input)4255 public PersistAdSelectionResultTestCallback invokePersistAdSelectionResult( 4256 AdSelectionService service, PersistAdSelectionResultInput input) 4257 throws RemoteException, InterruptedException { 4258 CountDownLatch countDownLatch = new CountDownLatch(1); 4259 PersistAdSelectionResultTestCallback callback = 4260 new PersistAdSelectionResultTestCallback(countDownLatch); 4261 service.persistAdSelectionResult(input, sCallerMetadata, callback); 4262 callback.mCountDownLatch.await(); 4263 return callback; 4264 } 4265 invokeAdSelectionFromOutcomes( AdSelectionService service, AdSelectionFromOutcomesInput input)4266 public AdSelectionFromOutcomesTestCallback invokeAdSelectionFromOutcomes( 4267 AdSelectionService service, AdSelectionFromOutcomesInput input) 4268 throws RemoteException, InterruptedException { 4269 CountDownLatch countDownLatch = new CountDownLatch(1); 4270 AdSelectionFromOutcomesTestCallback callback = 4271 new AdSelectionFromOutcomesTestCallback(countDownLatch); 4272 service.selectAdsFromOutcomes(input, null, callback); 4273 callback.mCountDownLatch.await(); 4274 return callback; 4275 } 4276 invokeReportImpression( AdSelectionService service, ReportImpressionInput input)4277 public ReportImpressionTestCallback invokeReportImpression( 4278 AdSelectionService service, ReportImpressionInput input) 4279 throws RemoteException, InterruptedException { 4280 CountDownLatch countDownLatch = new CountDownLatch(1); 4281 ReportImpressionTestCallback callback = new ReportImpressionTestCallback(countDownLatch); 4282 service.reportImpression(input, callback); 4283 callback.mCountDownLatch.await(); 4284 return callback; 4285 } 4286 invokeReportInteractions( AdSelectionService service, ReportInteractionInput input)4287 public ReportInteractionsTestCallback invokeReportInteractions( 4288 AdSelectionService service, ReportInteractionInput input) 4289 throws RemoteException, InterruptedException { 4290 CountDownLatch countDownLatch = new CountDownLatch(1); 4291 ReportInteractionsTestCallback callback = 4292 new ReportInteractionsTestCallback(countDownLatch); 4293 service.reportInteraction(input, callback); 4294 callback.mCountDownLatch.await(); 4295 return callback; 4296 } 4297 invokeUpdateAdCounterHistogram( AdSelectionService service, UpdateAdCounterHistogramInput input)4298 public UpdateAdCounterHistogramTestCallback invokeUpdateAdCounterHistogram( 4299 AdSelectionService service, UpdateAdCounterHistogramInput input) 4300 throws RemoteException, InterruptedException { 4301 CountDownLatch countDownLatch = new CountDownLatch(1); 4302 UpdateAdCounterHistogramTestCallback callback = 4303 new UpdateAdCounterHistogramTestCallback(countDownLatch); 4304 service.updateAdCounterHistogram(input, callback); 4305 callback.mCountDownLatch.await(); 4306 return callback; 4307 } 4308 4309 static class GetAdSelectionDataTestCallback extends GetAdSelectionDataCallback.Stub { 4310 final CountDownLatch mCountDownLatch; 4311 boolean mIsSuccess = false; 4312 GetAdSelectionDataResponse mGetAdSelectionDataResponse; 4313 FledgeErrorResponse mFledgeErrorResponse; 4314 GetAdSelectionDataTestCallback(CountDownLatch countDownLatch)4315 GetAdSelectionDataTestCallback(CountDownLatch countDownLatch) { 4316 mCountDownLatch = countDownLatch; 4317 mGetAdSelectionDataResponse = null; 4318 mFledgeErrorResponse = null; 4319 } 4320 4321 @Override onSuccess(GetAdSelectionDataResponse getAdSelectionDataResponse)4322 public void onSuccess(GetAdSelectionDataResponse getAdSelectionDataResponse) 4323 throws RemoteException { 4324 mIsSuccess = true; 4325 mGetAdSelectionDataResponse = getAdSelectionDataResponse; 4326 mCountDownLatch.countDown(); 4327 } 4328 4329 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)4330 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 4331 mIsSuccess = false; 4332 mFledgeErrorResponse = fledgeErrorResponse; 4333 mCountDownLatch.countDown(); 4334 } 4335 } 4336 4337 static class PersistAdSelectionResultTestCallback 4338 extends PersistAdSelectionResultCallback.Stub { 4339 final CountDownLatch mCountDownLatch; 4340 boolean mIsSuccess = false; 4341 PersistAdSelectionResultResponse mPersistAdSelectionResultResponse; 4342 FledgeErrorResponse mFledgeErrorResponse; 4343 PersistAdSelectionResultTestCallback(CountDownLatch countDownLatch)4344 PersistAdSelectionResultTestCallback(CountDownLatch countDownLatch) { 4345 mCountDownLatch = countDownLatch; 4346 mPersistAdSelectionResultResponse = null; 4347 mFledgeErrorResponse = null; 4348 } 4349 4350 @Override onSuccess(PersistAdSelectionResultResponse persistAdSelectionResultResponse)4351 public void onSuccess(PersistAdSelectionResultResponse persistAdSelectionResultResponse) 4352 throws RemoteException { 4353 mIsSuccess = true; 4354 mPersistAdSelectionResultResponse = persistAdSelectionResultResponse; 4355 mCountDownLatch.countDown(); 4356 } 4357 4358 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)4359 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 4360 mIsSuccess = false; 4361 mFledgeErrorResponse = fledgeErrorResponse; 4362 mCountDownLatch.countDown(); 4363 } 4364 } 4365 4366 private static class AppInstallResultCapturingCallback 4367 implements SetAppInstallAdvertisersCallback { 4368 private boolean mIsSuccess; 4369 private Exception mException; 4370 private final CountDownLatch mCountDownLatch; 4371 isSuccess()4372 public boolean isSuccess() { 4373 return mIsSuccess; 4374 } 4375 getException()4376 public Exception getException() { 4377 return mException; 4378 } 4379 AppInstallResultCapturingCallback(CountDownLatch countDownLatch)4380 AppInstallResultCapturingCallback(CountDownLatch countDownLatch) { 4381 mCountDownLatch = countDownLatch; 4382 } 4383 4384 @Override onSuccess()4385 public void onSuccess() throws RemoteException { 4386 mIsSuccess = true; 4387 mCountDownLatch.countDown(); 4388 } 4389 4390 @Override onFailure(FledgeErrorResponse responseParcel)4391 public void onFailure(FledgeErrorResponse responseParcel) throws RemoteException { 4392 mIsSuccess = false; 4393 mException = AdServicesStatusUtils.asException(responseParcel); 4394 mCountDownLatch.countDown(); 4395 } 4396 4397 @Override asBinder()4398 public IBinder asBinder() { 4399 throw new RuntimeException("Should not be called."); 4400 } 4401 } 4402 4403 static class AdSelectionFromOutcomesTestCallback extends AdSelectionCallback.Stub { 4404 4405 final CountDownLatch mCountDownLatch; 4406 boolean mIsSuccess = false; 4407 AdSelectionResponse mAdSelectionResponse; 4408 FledgeErrorResponse mFledgeErrorResponse; 4409 AdSelectionFromOutcomesTestCallback(CountDownLatch countDownLatch)4410 AdSelectionFromOutcomesTestCallback(CountDownLatch countDownLatch) { 4411 mCountDownLatch = countDownLatch; 4412 mAdSelectionResponse = null; 4413 mFledgeErrorResponse = null; 4414 } 4415 4416 @Override onSuccess(AdSelectionResponse adSelectionResponse)4417 public void onSuccess(AdSelectionResponse adSelectionResponse) throws RemoteException { 4418 mIsSuccess = true; 4419 mAdSelectionResponse = adSelectionResponse; 4420 mCountDownLatch.countDown(); 4421 } 4422 4423 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)4424 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 4425 mIsSuccess = false; 4426 mFledgeErrorResponse = fledgeErrorResponse; 4427 mCountDownLatch.countDown(); 4428 } 4429 } 4430 4431 static class ReportImpressionTestCallback extends ReportImpressionCallback.Stub { 4432 final CountDownLatch mCountDownLatch; 4433 boolean mIsSuccess = false; 4434 FledgeErrorResponse mFledgeErrorResponse; 4435 ReportImpressionTestCallback(CountDownLatch countDownLatch)4436 ReportImpressionTestCallback(CountDownLatch countDownLatch) { 4437 mCountDownLatch = countDownLatch; 4438 mFledgeErrorResponse = null; 4439 } 4440 4441 @Override onSuccess()4442 public void onSuccess() throws RemoteException { 4443 mIsSuccess = true; 4444 mCountDownLatch.countDown(); 4445 } 4446 4447 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)4448 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 4449 mIsSuccess = false; 4450 mFledgeErrorResponse = fledgeErrorResponse; 4451 mCountDownLatch.countDown(); 4452 } 4453 } 4454 4455 static class ReportInteractionsTestCallback extends ReportInteractionCallback.Stub { 4456 final CountDownLatch mCountDownLatch; 4457 boolean mIsSuccess = false; 4458 FledgeErrorResponse mFledgeErrorResponse; 4459 ReportInteractionsTestCallback(CountDownLatch countDownLatch)4460 ReportInteractionsTestCallback(CountDownLatch countDownLatch) { 4461 mCountDownLatch = countDownLatch; 4462 mFledgeErrorResponse = null; 4463 } 4464 4465 @Override onSuccess()4466 public void onSuccess() throws RemoteException { 4467 mIsSuccess = true; 4468 mCountDownLatch.countDown(); 4469 } 4470 4471 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)4472 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 4473 mIsSuccess = false; 4474 mFledgeErrorResponse = fledgeErrorResponse; 4475 mCountDownLatch.countDown(); 4476 } 4477 } 4478 4479 static class UpdateAdCounterHistogramTestCallback 4480 extends UpdateAdCounterHistogramCallback.Stub { 4481 final CountDownLatch mCountDownLatch; 4482 boolean mIsSuccess = false; 4483 FledgeErrorResponse mFledgeErrorResponse; 4484 UpdateAdCounterHistogramTestCallback(CountDownLatch countDownLatch)4485 UpdateAdCounterHistogramTestCallback(CountDownLatch countDownLatch) { 4486 mCountDownLatch = countDownLatch; 4487 mFledgeErrorResponse = null; 4488 } 4489 4490 @Override onSuccess()4491 public void onSuccess() throws RemoteException { 4492 mIsSuccess = true; 4493 mCountDownLatch.countDown(); 4494 } 4495 4496 @Override onFailure(FledgeErrorResponse fledgeErrorResponse)4497 public void onFailure(FledgeErrorResponse fledgeErrorResponse) throws RemoteException { 4498 mIsSuccess = false; 4499 mFledgeErrorResponse = fledgeErrorResponse; 4500 mCountDownLatch.countDown(); 4501 } 4502 } 4503 4504 static class AuctionServerE2ETestFlags implements Flags { 4505 private final boolean mFledgeAuctionServerKillSwitch; 4506 4507 private final boolean mDebugReportingEnabled; 4508 4509 private final long mAdIdFetcherTimeoutMs; 4510 4511 private final boolean mMultiCloudEnabled; 4512 private final String mCoordinatorAllowlist; 4513 private final boolean mOmitAdsEnabled; 4514 private final boolean mProtectedSignalsPeriodicEncodingEnabled; 4515 private final boolean mRefreshKeysDuringAuction; 4516 AuctionServerE2ETestFlags()4517 AuctionServerE2ETestFlags() { 4518 this(false, false, 20, false); 4519 } 4520 AuctionServerE2ETestFlags(boolean omitAdsEnabled)4521 AuctionServerE2ETestFlags(boolean omitAdsEnabled) { 4522 this(false, false, 20, omitAdsEnabled); 4523 } 4524 AuctionServerE2ETestFlags( boolean fledgeAuctionServerKillSwitch, boolean debugReportingEnabled, long adIdFetcherTimeoutMs, boolean omitAdsEnabled)4525 AuctionServerE2ETestFlags( 4526 boolean fledgeAuctionServerKillSwitch, 4527 boolean debugReportingEnabled, 4528 long adIdFetcherTimeoutMs, 4529 boolean omitAdsEnabled) { 4530 this( 4531 fledgeAuctionServerKillSwitch, 4532 debugReportingEnabled, 4533 adIdFetcherTimeoutMs, 4534 false, 4535 COORDINATOR_ALLOWLIST, 4536 omitAdsEnabled, 4537 true, 4538 false); 4539 } 4540 AuctionServerE2ETestFlags( boolean fledgeAuctionServerKillSwitch, boolean debugReportingEnabled, long adIdFetcherTimeoutMs, boolean multiCloudEnabled, String allowList, boolean omitAdsEnabled)4541 AuctionServerE2ETestFlags( 4542 boolean fledgeAuctionServerKillSwitch, 4543 boolean debugReportingEnabled, 4544 long adIdFetcherTimeoutMs, 4545 boolean multiCloudEnabled, 4546 String allowList, 4547 boolean omitAdsEnabled) { 4548 this( 4549 fledgeAuctionServerKillSwitch, 4550 debugReportingEnabled, 4551 adIdFetcherTimeoutMs, 4552 multiCloudEnabled, 4553 allowList, 4554 omitAdsEnabled, 4555 true, 4556 false); 4557 } 4558 AuctionServerE2ETestFlags( boolean fledgeAuctionServerKillSwitch, boolean debugReportingEnabled, long adIdFetcherTimeoutMs, boolean multiCloudEnabled, String allowList, boolean omitAdsEnabled, boolean protectedSignalsPeriodicEncodingEnabled, boolean refreshKeysDuringAuction)4559 AuctionServerE2ETestFlags( 4560 boolean fledgeAuctionServerKillSwitch, 4561 boolean debugReportingEnabled, 4562 long adIdFetcherTimeoutMs, 4563 boolean multiCloudEnabled, 4564 String allowList, 4565 boolean omitAdsEnabled, 4566 boolean protectedSignalsPeriodicEncodingEnabled, 4567 boolean refreshKeysDuringAuction) { 4568 mFledgeAuctionServerKillSwitch = fledgeAuctionServerKillSwitch; 4569 mDebugReportingEnabled = debugReportingEnabled; 4570 mAdIdFetcherTimeoutMs = adIdFetcherTimeoutMs; 4571 mMultiCloudEnabled = multiCloudEnabled; 4572 mCoordinatorAllowlist = COORDINATOR_ALLOWLIST; 4573 mOmitAdsEnabled = omitAdsEnabled; 4574 mProtectedSignalsPeriodicEncodingEnabled = protectedSignalsPeriodicEncodingEnabled; 4575 mRefreshKeysDuringAuction = refreshKeysDuringAuction; 4576 } 4577 4578 @Override getFledgeFrequencyCapFilteringEnabled()4579 public boolean getFledgeFrequencyCapFilteringEnabled() { 4580 return true; 4581 } 4582 4583 @Override getFledgeAuctionServerEnabledForUpdateHistogram()4584 public boolean getFledgeAuctionServerEnabledForUpdateHistogram() { 4585 return true; 4586 } 4587 4588 @Override getFledgeAuctionServerEnabledForReportEvent()4589 public boolean getFledgeAuctionServerEnabledForReportEvent() { 4590 return true; 4591 } 4592 4593 @Override getFledgeAuctionServerEnabledForSelectAdsMediation()4594 public boolean getFledgeAuctionServerEnabledForSelectAdsMediation() { 4595 return true; 4596 } 4597 4598 @Override getFledgeRegisterAdBeaconEnabled()4599 public boolean getFledgeRegisterAdBeaconEnabled() { 4600 return true; 4601 } 4602 4603 @Override getFledgeAuctionServerKillSwitch()4604 public boolean getFledgeAuctionServerKillSwitch() { 4605 return mFledgeAuctionServerKillSwitch; 4606 } 4607 4608 @Override getFledgeAuctionServerEnabledForReportImpression()4609 public boolean getFledgeAuctionServerEnabledForReportImpression() { 4610 return true; 4611 } 4612 4613 @Override getFledgeAuctionServerEnableDebugReporting()4614 public boolean getFledgeAuctionServerEnableDebugReporting() { 4615 return mDebugReportingEnabled; 4616 } 4617 4618 @Override getFledgeAuctionServerAdIdFetcherTimeoutMs()4619 public long getFledgeAuctionServerAdIdFetcherTimeoutMs() { 4620 return mAdIdFetcherTimeoutMs; 4621 } 4622 4623 @Override getFledgeAuctionServerMultiCloudEnabled()4624 public boolean getFledgeAuctionServerMultiCloudEnabled() { 4625 return mMultiCloudEnabled; 4626 } 4627 4628 @Override getFledgeAuctionServerCoordinatorUrlAllowlist()4629 public String getFledgeAuctionServerCoordinatorUrlAllowlist() { 4630 return mCoordinatorAllowlist; 4631 } 4632 4633 @Override getFledgeAuctionServerAuctionKeyFetchUri()4634 public String getFledgeAuctionServerAuctionKeyFetchUri() { 4635 return DEFAULT_FETCH_URI; 4636 } 4637 4638 @Override getFledgeAuctionServerOmitAdsEnabled()4639 public boolean getFledgeAuctionServerOmitAdsEnabled() { 4640 return mOmitAdsEnabled; 4641 } 4642 4643 @Override getProtectedSignalsPeriodicEncodingEnabled()4644 public boolean getProtectedSignalsPeriodicEncodingEnabled() { 4645 return mProtectedSignalsPeriodicEncodingEnabled; 4646 } 4647 4648 @Override getFledgeAuctionServerRefreshExpiredKeysDuringAuction()4649 public boolean getFledgeAuctionServerRefreshExpiredKeysDuringAuction() { 4650 return mRefreshKeysDuringAuction; 4651 } 4652 4653 @Override getFledgeAuctionServerMediaTypeChangeEnabled()4654 public boolean getFledgeAuctionServerMediaTypeChangeEnabled() { 4655 return false; 4656 } 4657 } 4658 } 4659