1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.adservices.customaudience; 18 19 import static android.adservices.common.AdDataFixture.getValidFilterAdDataWithAdRenderIdByBuyer; 20 import static android.adservices.customaudience.TrustedBiddingDataFixture.getValidTrustedBiddingDataByBuyer; 21 22 import android.adservices.common.AdData; 23 import android.adservices.common.AdDataFixture; 24 import android.adservices.common.AdSelectionSignals; 25 import android.adservices.common.AdTechIdentifier; 26 import android.adservices.common.CommonFixture; 27 import android.net.Uri; 28 29 30 import java.time.Duration; 31 import java.time.Instant; 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.List; 35 import java.util.stream.Collectors; 36 37 /** Utility class supporting custom audience API unit tests */ 38 public final class CustomAudienceFixture { 39 40 public static final Duration CUSTOM_AUDIENCE_MAX_ACTIVATION_DELAY_IN = 41 Duration.ofMillis( 42 CommonFixture.FLAGS_FOR_TEST.getFledgeCustomAudienceMaxActivationDelayInMs()); 43 public static final Duration CUSTOM_AUDIENCE_MAX_EXPIRE_IN = 44 Duration.ofMillis(CommonFixture.FLAGS_FOR_TEST.getFledgeCustomAudienceMaxExpireInMs()); 45 public static final Duration CUSTOM_AUDIENCE_DEFAULT_EXPIRE_IN = 46 Duration.ofMillis( 47 CommonFixture.FLAGS_FOR_TEST.getFledgeCustomAudienceDefaultExpireInMs()); 48 public static final long DAY_IN_SECONDS = 60 * 60 * 24; 49 50 public static final String VALID_OWNER = CommonFixture.TEST_PACKAGE_NAME; 51 public static final String VALID_NAME = "testCustomAudienceName"; 52 53 public static final Instant VALID_ACTIVATION_TIME = 54 CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI; 55 public static final Instant VALID_DELAYED_ACTIVATION_TIME = 56 CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI.plus( 57 CUSTOM_AUDIENCE_MAX_ACTIVATION_DELAY_IN.dividedBy(2)); 58 public static final Instant INVALID_DELAYED_ACTIVATION_TIME = 59 CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI.plus( 60 CUSTOM_AUDIENCE_MAX_ACTIVATION_DELAY_IN.multipliedBy(2)); 61 62 public static final Instant VALID_EXPIRATION_TIME = 63 VALID_ACTIVATION_TIME.plus(CUSTOM_AUDIENCE_DEFAULT_EXPIRE_IN); 64 public static final Instant VALID_DELAYED_EXPIRATION_TIME = 65 VALID_DELAYED_ACTIVATION_TIME.plusSeconds(DAY_IN_SECONDS); 66 public static final Instant INVALID_BEFORE_NOW_EXPIRATION_TIME = 67 VALID_ACTIVATION_TIME.minusSeconds(DAY_IN_SECONDS); 68 public static final Instant INVALID_NOW_EXPIRATION_TIME = 69 CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI.minusSeconds(DAY_IN_SECONDS); 70 public static final Instant INVALID_BEFORE_DELAYED_EXPIRATION_TIME = 71 VALID_DELAYED_ACTIVATION_TIME.minusSeconds(DAY_IN_SECONDS); 72 public static final Instant INVALID_BEYOND_MAX_EXPIRATION_TIME = 73 VALID_ACTIVATION_TIME.plus(CUSTOM_AUDIENCE_MAX_EXPIRE_IN.multipliedBy(2)); 74 public static final Instant VALID_LAST_UPDATE_TIME_24_HRS_BEFORE = 75 CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI.minusSeconds(DAY_IN_SECONDS); 76 public static final Instant INVALID_LAST_UPDATE_TIME_72_DAYS_BEFORE = 77 CommonFixture.FIXED_NOW_TRUNCATED_TO_MILLI.minusSeconds(DAY_IN_SECONDS * 72); 78 79 public static final AdSelectionSignals VALID_USER_BIDDING_SIGNALS = 80 AdSelectionSignals.fromString("{\"valid\":\"yep\",\"opaque\":\"definitely\"}"); 81 getValidFetchUriByBuyer(AdTechIdentifier buyer, String token)82 public static Uri getValidFetchUriByBuyer(AdTechIdentifier buyer, String token) { 83 boolean hasToken = token != null && !token.isEmpty(); 84 return CommonFixture.getUri(buyer, "/ca" + (hasToken ? "?token=" + token : "")); 85 } 86 getValidFetchUriByBuyer(AdTechIdentifier buyer)87 public static Uri getValidFetchUriByBuyer(AdTechIdentifier buyer) { 88 return getValidFetchUriByBuyer(buyer, null); 89 } 90 getValidDailyUpdateUriByBuyer(AdTechIdentifier buyer)91 public static Uri getValidDailyUpdateUriByBuyer(AdTechIdentifier buyer) { 92 return CommonFixture.getUri(buyer, "/update"); 93 } 94 getValidBiddingLogicUriByBuyer(AdTechIdentifier buyer)95 public static Uri getValidBiddingLogicUriByBuyer(AdTechIdentifier buyer) { 96 return CommonFixture.getUri(buyer, "/bidding/logic/here/"); 97 } 98 getValidBuilderForBuyer(AdTechIdentifier buyer)99 public static CustomAudience.Builder getValidBuilderForBuyer(AdTechIdentifier buyer) { 100 return new CustomAudience.Builder() 101 .setBuyer(buyer) 102 .setName(CustomAudienceFixture.VALID_NAME) 103 .setActivationTime(CustomAudienceFixture.VALID_ACTIVATION_TIME) 104 .setExpirationTime(CustomAudienceFixture.VALID_EXPIRATION_TIME) 105 .setDailyUpdateUri(CustomAudienceFixture.getValidDailyUpdateUriByBuyer(buyer)) 106 .setUserBiddingSignals(CustomAudienceFixture.VALID_USER_BIDDING_SIGNALS) 107 .setTrustedBiddingData(getValidTrustedBiddingDataByBuyer(buyer)) 108 .setBiddingLogicUri(CustomAudienceFixture.getValidBiddingLogicUriByBuyer(buyer)) 109 .setAds(AdDataFixture.getValidAdsByBuyer(buyer)); 110 } 111 112 /** Build valid CA with server auction flags */ getValidBuilderByBuyerWithAuctionServerRequestFlags( AdTechIdentifier buyer, @CustomAudience.AuctionServerRequestFlag int auctionServerRequestFlags)113 public static CustomAudience.Builder getValidBuilderByBuyerWithAuctionServerRequestFlags( 114 AdTechIdentifier buyer, 115 @CustomAudience.AuctionServerRequestFlag int auctionServerRequestFlags) { 116 return getValidBuilderForBuyer(buyer) 117 .setAuctionServerRequestFlags(auctionServerRequestFlags); 118 } 119 getValidBuilderWithSubdomainsForBuyer( AdTechIdentifier buyer)120 public static CustomAudience.Builder getValidBuilderWithSubdomainsForBuyer( 121 AdTechIdentifier buyer) { 122 return getValidBuilderForBuyer(buyer) 123 .setBiddingLogicUri( 124 CommonFixture.getUriWithValidSubdomain(buyer.toString(), "/bidding/logic")) 125 .setDailyUpdateUri( 126 CommonFixture.getUriWithValidSubdomain(buyer.toString(), "/dailyupdate")) 127 .setTrustedBiddingData( 128 new TrustedBiddingData.Builder() 129 .setTrustedBiddingUri( 130 CommonFixture.getUriWithValidSubdomain( 131 buyer.toString(), "/trustedbidding")) 132 .setTrustedBiddingKeys( 133 TrustedBiddingDataFixture.VALID_TRUSTED_BIDDING_KEYS) 134 .build()) 135 .setAds( 136 Arrays.asList( 137 AdDataFixture.getValidAdDataWithSubdomainBuilderByBuyer(buyer, 0) 138 .build(), 139 AdDataFixture.getValidAdDataWithSubdomainBuilderByBuyer(buyer, 1) 140 .build())); 141 } 142 143 // TODO(b/266837113) Merge with getValidBuilderForBuyer once filters are unhidden getValidBuilderForBuyerFilters(AdTechIdentifier buyer)144 public static CustomAudience.Builder getValidBuilderForBuyerFilters(AdTechIdentifier buyer) { 145 return new CustomAudience.Builder() 146 .setBuyer(buyer) 147 .setName(CustomAudienceFixture.VALID_NAME) 148 .setActivationTime(CustomAudienceFixture.VALID_ACTIVATION_TIME) 149 .setExpirationTime(CustomAudienceFixture.VALID_EXPIRATION_TIME) 150 .setDailyUpdateUri(CustomAudienceFixture.getValidDailyUpdateUriByBuyer(buyer)) 151 .setUserBiddingSignals(CustomAudienceFixture.VALID_USER_BIDDING_SIGNALS) 152 .setTrustedBiddingData(getValidTrustedBiddingDataByBuyer(buyer)) 153 .setBiddingLogicUri(CustomAudienceFixture.getValidBiddingLogicUriByBuyer(buyer)) 154 .setAds(AdDataFixture.getValidFilterAdsByBuyer(buyer)); 155 } 156 157 /** Build valid CA with filters and render id */ getValidBuilderForBuyerFiltersWithAdRenderId( AdTechIdentifier buyer)158 public static CustomAudience.Builder getValidBuilderForBuyerFiltersWithAdRenderId( 159 AdTechIdentifier buyer) { 160 return new CustomAudience.Builder() 161 .setBuyer(buyer) 162 .setName(CustomAudienceFixture.VALID_NAME) 163 .setActivationTime(CustomAudienceFixture.VALID_ACTIVATION_TIME) 164 .setExpirationTime(CustomAudienceFixture.VALID_EXPIRATION_TIME) 165 .setDailyUpdateUri(CustomAudienceFixture.getValidDailyUpdateUriByBuyer(buyer)) 166 .setUserBiddingSignals(CustomAudienceFixture.VALID_USER_BIDDING_SIGNALS) 167 .setTrustedBiddingData(getValidTrustedBiddingDataByBuyer(buyer)) 168 .setBiddingLogicUri(CustomAudienceFixture.getValidBiddingLogicUriByBuyer(buyer)) 169 .setAds(AdDataFixture.getValidFilterAdsWithAdRenderIdByBuyer(buyer)); 170 } 171 172 /** Build N valid CAs with filters and render id */ getNValidCustomAudiences( int nBuyers, int nCAsPerBuyer, int nAdsPerCA)173 public static List<CustomAudience> getNValidCustomAudiences( 174 int nBuyers, int nCAsPerBuyer, int nAdsPerCA) { 175 List<CustomAudience> customAudiences = new ArrayList<>(); 176 for (int b = 0; b < nBuyers; b++) { 177 AdTechIdentifier buyer = AdTechIdentifier.fromString("buyer%d.com".formatted(b)); 178 for (int c = 0; c < nCAsPerBuyer; c++) { 179 List<AdData> ads = new ArrayList<>(); 180 for (int a = 0; a < nAdsPerCA; a++) { 181 ads.add( 182 getValidFilterAdDataWithAdRenderIdByBuyer( 183 buyer, /* sequenceString= */ generateHash(a, b, c))); 184 } 185 CustomAudience customAudience = 186 new CustomAudience.Builder() 187 .setBuyer(buyer) 188 .setName("testCustomAudience_%s".formatted(generateHash(b, c))) 189 .setActivationTime(VALID_ACTIVATION_TIME) 190 .setExpirationTime(VALID_EXPIRATION_TIME) 191 .setDailyUpdateUri(getValidDailyUpdateUriByBuyer(buyer)) 192 .setBiddingLogicUri(getValidBiddingLogicUriByBuyer(buyer)) 193 .setUserBiddingSignals(VALID_USER_BIDDING_SIGNALS) 194 .setTrustedBiddingData(getValidTrustedBiddingDataByBuyer(buyer)) 195 .setAds(ads) 196 .build(); 197 customAudiences.add(customAudience); 198 } 199 } 200 return customAudiences; 201 } 202 generateHash(int... vargs)203 private static String generateHash(int... vargs) { 204 return Arrays.stream(vargs).mapToObj(String::valueOf).collect(Collectors.joining("-")); 205 } 206 } 207