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