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