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.cts; 18 19 import static com.android.adservices.AdServicesCommon.BINDER_TIMEOUT_SYSTEM_PROPERTY_NAME; 20 import static com.android.adservices.service.FlagsConstants.KEY_ENABLE_ENROLLMENT_TEST_SEED; 21 import static com.android.adservices.service.FlagsConstants.KEY_ENFORCE_ISOLATE_MAX_HEAP_SIZE; 22 import static com.android.adservices.service.FlagsConstants.KEY_ISOLATE_MAX_HEAP_SIZE_BYTES; 23 24 import static com.google.common.truth.Truth.assertThat; 25 26 import static org.junit.Assert.assertThrows; 27 28 import android.Manifest; 29 import android.adservices.adselection.AdSelectionConfig; 30 import android.adservices.adselection.AdSelectionConfigFixture; 31 import android.adservices.adselection.AdSelectionFromOutcomesConfig; 32 import android.adservices.adselection.AdSelectionFromOutcomesConfigFixture; 33 import android.adservices.adselection.AdSelectionOutcome; 34 import android.adservices.adselection.AddAdSelectionFromOutcomesOverrideRequest; 35 import android.adservices.adselection.AddAdSelectionOverrideRequest; 36 import android.adservices.adselection.RemoveAdSelectionFromOutcomesOverrideRequest; 37 import android.adservices.adselection.RemoveAdSelectionOverrideRequest; 38 import android.adservices.adselection.ReportImpressionRequest; 39 import android.adservices.clients.adselection.AdSelectionClient; 40 import android.adservices.clients.adselection.TestAdSelectionClient; 41 import android.adservices.common.AdSelectionSignals; 42 import android.adservices.common.AdTechIdentifier; 43 import android.adservices.utils.CtsWebViewSupportUtil; 44 import android.net.Uri; 45 import android.os.Process; 46 47 import androidx.test.platform.app.InstrumentationRegistry; 48 49 import com.android.adservices.LoggerFactory; 50 import com.android.adservices.common.AdServicesFlagsSetterRule; 51 import com.android.adservices.common.AdservicesTestHelper; 52 import com.android.adservices.service.devapi.DevContext; 53 import com.android.adservices.service.devapi.DevContextFilter; 54 import com.android.adservices.shared.testing.annotations.RequiresSdkLevelAtLeastS; 55 import com.android.adservices.shared.testing.annotations.SetFlagDisabled; 56 import com.android.adservices.shared.testing.annotations.SetFlagEnabled; 57 import com.android.adservices.shared.testing.annotations.SetLongDebugFlag; 58 59 import com.google.common.util.concurrent.ListenableFuture; 60 61 import org.junit.Assume; 62 import org.junit.Before; 63 import org.junit.Test; 64 65 import java.util.ArrayList; 66 import java.util.concurrent.ExecutionException; 67 import java.util.concurrent.Executor; 68 import java.util.concurrent.Executors; 69 import java.util.concurrent.TimeUnit; 70 71 @RequiresSdkLevelAtLeastS // TODO(b/291488819) - Remove SDK Level check if Fledge is enabled on R. 72 @SetFlagEnabled(KEY_ENABLE_ENROLLMENT_TEST_SEED) 73 @SetFlagDisabled(KEY_ENFORCE_ISOLATE_MAX_HEAP_SIZE) 74 @SetFlagDisabled(KEY_ISOLATE_MAX_HEAP_SIZE_BYTES) 75 // TODO (b/330324133): Short-term solution to allow test to extend binder timeout to 76 // resolve the test flakiness. 77 @SetLongDebugFlag(name = BINDER_TIMEOUT_SYSTEM_PROPERTY_NAME, value = 10_000) 78 public final class TestAdSelectionManagerTest extends ForegroundCtsTestCase { 79 80 private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger(); 81 private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool(); 82 83 private static final String DECISION_LOGIC_JS = "function test() { return \"hello world\"; }"; 84 private static final long AD_SELECTION_ID = 1; 85 private static final AdTechIdentifier SELLER = AdTechIdentifier.fromString("test.com"); 86 private static final Uri DECISION_LOGIC_URI = 87 Uri.parse("https://test.com/test/decisions_logic_uris"); 88 private static final Uri TRUSTED_SCORING_SIGNALS_URI = 89 Uri.parse("https://test.com/test/decisions_logic_uris"); 90 private static final AdSelectionSignals TRUSTED_SCORING_SIGNALS = 91 AdSelectionSignals.fromString( 92 "{\n" 93 + "\t\"render_uri_1\": \"signals_for_1\",\n" 94 + "\t\"render_uri_2\": \"signals_for_2\"\n" 95 + "}"); 96 private static final AdSelectionConfig AD_SELECTION_CONFIG = 97 AdSelectionConfigFixture.anAdSelectionConfigBuilder() 98 .setSeller(SELLER) 99 .setDecisionLogicUri(DECISION_LOGIC_URI) 100 .setTrustedScoringSignalsUri(TRUSTED_SCORING_SIGNALS_URI) 101 .build(); 102 103 private static final AdSelectionSignals SELECTION_SIGNALS = AdSelectionSignals.EMPTY; 104 105 private static final AdSelectionFromOutcomesConfig AD_SELECTION_FROM_OUTCOMES_CONFIG = 106 AdSelectionFromOutcomesConfigFixture.anAdSelectionFromOutcomesConfig( 107 SELLER, DECISION_LOGIC_URI); 108 109 private TestAdSelectionClient mTestAdSelectionClient; 110 private boolean mIsDebugMode; 111 112 @Override getAdServicesFlagsSetterRule()113 protected AdServicesFlagsSetterRule getAdServicesFlagsSetterRule() { 114 return AdServicesFlagsSetterRule.forAllApisEnabledTests() 115 .setCompatModeFlags() 116 .setPpapiAppAllowList(mPackageName); 117 } 118 119 @Before setup()120 public void setup() { 121 122 if (sdkLevel.isAtLeastT()) { 123 assertForegroundActivityStarted(); 124 } 125 126 mTestAdSelectionClient = 127 new TestAdSelectionClient.Builder() 128 .setContext(sContext) 129 .setExecutor(CALLBACK_EXECUTOR) 130 .build(); 131 DevContext devContext = DevContextFilter.create(sContext).createDevContext(Process.myUid()); 132 mIsDebugMode = devContext.getDevOptionsEnabled(); 133 134 InstrumentationRegistry.getInstrumentation() 135 .getUiAutomation() 136 .adoptShellPermissionIdentity(Manifest.permission.WRITE_DEVICE_CONFIG); 137 138 // Kill AdServices process 139 AdservicesTestHelper.killAdservicesProcess(sContext); 140 } 141 142 @Test testFailsWithInvalidAdSelectionId()143 public void testFailsWithInvalidAdSelectionId() { 144 Assume.assumeTrue(CtsWebViewSupportUtil.isJSSandboxAvailable(sContext)); 145 sLogger.i("Calling Report Impression"); 146 147 AdSelectionClient adSelectionClient = 148 new AdSelectionClient.Builder() 149 .setContext(sContext) 150 .setExecutor(CALLBACK_EXECUTOR) 151 .build(); 152 assertInvalidAdSelectionIdFailsImpressionReporting(adSelectionClient); 153 } 154 155 @Test testFailsWithInvalidAdSelectionId_usingGetMethodToCreateManager()156 public void testFailsWithInvalidAdSelectionId_usingGetMethodToCreateManager() { 157 Assume.assumeTrue(CtsWebViewSupportUtil.isJSSandboxAvailable(sContext)); 158 sLogger.i("Calling Report Impression"); 159 160 AdSelectionClient adSelectionClient = 161 new AdSelectionClient.Builder() 162 .setContext(sContext) 163 .setExecutor(CALLBACK_EXECUTOR) 164 .setUseGetMethodToCreateManagerInstance(true) 165 .build(); 166 assertInvalidAdSelectionIdFailsImpressionReporting(adSelectionClient); 167 } 168 assertInvalidAdSelectionIdFailsImpressionReporting( AdSelectionClient adSelectionClient)169 private void assertInvalidAdSelectionIdFailsImpressionReporting( 170 AdSelectionClient adSelectionClient) { 171 ReportImpressionRequest input = 172 new ReportImpressionRequest(AD_SELECTION_ID, AD_SELECTION_CONFIG); 173 174 ListenableFuture<Void> result = adSelectionClient.reportImpression(input); 175 176 Exception exception = 177 assertThrows( 178 ExecutionException.class, 179 () -> { 180 result.get(10, TimeUnit.SECONDS); 181 }); 182 assertThat(exception.getCause()).isInstanceOf(IllegalArgumentException.class); 183 } 184 185 @Test testAddOverrideFailsWithDebugModeDisabled()186 public void testAddOverrideFailsWithDebugModeDisabled() { 187 Assume.assumeFalse(mIsDebugMode); 188 189 AddAdSelectionOverrideRequest request = 190 new AddAdSelectionOverrideRequest( 191 AD_SELECTION_CONFIG, DECISION_LOGIC_JS, TRUSTED_SCORING_SIGNALS); 192 193 ListenableFuture<Void> result = 194 mTestAdSelectionClient.overrideAdSelectionConfigRemoteInfo(request); 195 196 Exception exception = 197 assertThrows( 198 ExecutionException.class, 199 () -> { 200 result.get(10, TimeUnit.SECONDS); 201 }); 202 assertThat(exception.getCause()).isInstanceOf(SecurityException.class); 203 } 204 205 @Test testAddOverrideFailsWithDebugModeDisabled_usingGetMethodToCreateManager()206 public void testAddOverrideFailsWithDebugModeDisabled_usingGetMethodToCreateManager() 207 throws Exception { 208 Assume.assumeFalse(mIsDebugMode); 209 overrideAdSelectionClient(); 210 testAddOverrideFailsWithDebugModeDisabled(); 211 } 212 213 @Test testRemoveOverrideFailsWithDebugModeDisabled()214 public void testRemoveOverrideFailsWithDebugModeDisabled() { 215 Assume.assumeFalse(mIsDebugMode); 216 217 RemoveAdSelectionOverrideRequest request = 218 new RemoveAdSelectionOverrideRequest(AD_SELECTION_CONFIG); 219 220 ListenableFuture<Void> result = 221 mTestAdSelectionClient.removeAdSelectionConfigRemoteInfoOverride(request); 222 223 Exception exception = 224 assertThrows( 225 ExecutionException.class, 226 () -> { 227 result.get(10, TimeUnit.SECONDS); 228 }); 229 assertThat(exception.getCause()).isInstanceOf(SecurityException.class); 230 } 231 232 @Test testRemoveOverrideFailsWithDebugModeDisabled_usingGetMethodToCreateManager()233 public void testRemoveOverrideFailsWithDebugModeDisabled_usingGetMethodToCreateManager() 234 throws Exception { 235 Assume.assumeFalse(mIsDebugMode); 236 overrideAdSelectionClient(); 237 testRemoveOverrideFailsWithDebugModeDisabled(); 238 } 239 240 @Test testResetAllOverridesFailsWithDebugModeDisabled()241 public void testResetAllOverridesFailsWithDebugModeDisabled() { 242 Assume.assumeFalse(mIsDebugMode); 243 244 TestAdSelectionClient testAdSelectionClient = 245 new TestAdSelectionClient.Builder() 246 .setContext(sContext) 247 .setExecutor(CALLBACK_EXECUTOR) 248 .build(); 249 assertResetAllOverridesFailsWithDebugModeDisabled(testAdSelectionClient); 250 } 251 252 @Test testResetAllOverridesFailsWithDebugModeDisabled_usingGetMethodToCreateManager()253 public void testResetAllOverridesFailsWithDebugModeDisabled_usingGetMethodToCreateManager() { 254 Assume.assumeFalse(mIsDebugMode); 255 256 TestAdSelectionClient testAdSelectionClient = 257 new TestAdSelectionClient.Builder() 258 .setContext(sContext) 259 .setExecutor(CALLBACK_EXECUTOR) 260 .setUseGetMethodToCreateManagerInstance(true) 261 .build(); 262 assertResetAllOverridesFailsWithDebugModeDisabled(testAdSelectionClient); 263 } 264 assertResetAllOverridesFailsWithDebugModeDisabled( TestAdSelectionClient testAdSelectionClient)265 private void assertResetAllOverridesFailsWithDebugModeDisabled( 266 TestAdSelectionClient testAdSelectionClient) { 267 ListenableFuture<Void> result = 268 testAdSelectionClient.resetAllAdSelectionConfigRemoteOverrides(); 269 270 Exception exception = 271 assertThrows( 272 ExecutionException.class, 273 () -> { 274 result.get(10, TimeUnit.SECONDS); 275 }); 276 assertThat(exception.getCause()).isInstanceOf(SecurityException.class); 277 } 278 279 @Test testFailsWithInvalidAdSelectionConfigNoBuyers()280 public void testFailsWithInvalidAdSelectionConfigNoBuyers() { 281 Assume.assumeTrue(CtsWebViewSupportUtil.isJSSandboxAvailable(sContext)); 282 AdSelectionClient adSelectionClient = 283 new AdSelectionClient.Builder() 284 .setContext(sContext) 285 .setExecutor(CALLBACK_EXECUTOR) 286 .build(); 287 assertNoBuyersConfigFailsAdSelection(adSelectionClient); 288 } 289 290 @Test testFailsWithInvalidAdSelectionConfigNoBuyers_usingGetMethodToCreateManager()291 public void testFailsWithInvalidAdSelectionConfigNoBuyers_usingGetMethodToCreateManager() { 292 Assume.assumeTrue(CtsWebViewSupportUtil.isJSSandboxAvailable(sContext)); 293 AdSelectionClient adSelectionClient = 294 new AdSelectionClient.Builder() 295 .setContext(sContext) 296 .setExecutor(CALLBACK_EXECUTOR) 297 .setUseGetMethodToCreateManagerInstance(true) 298 .build(); 299 assertNoBuyersConfigFailsAdSelection(adSelectionClient); 300 } 301 assertNoBuyersConfigFailsAdSelection(AdSelectionClient adSelectionClient)302 private void assertNoBuyersConfigFailsAdSelection(AdSelectionClient adSelectionClient) { 303 sLogger.i("Calling Ad Selection"); 304 AdSelectionConfig adSelectionConfigNoBuyers = 305 AdSelectionConfigFixture.anAdSelectionConfigBuilder() 306 .setSeller(SELLER) 307 .setDecisionLogicUri(DECISION_LOGIC_URI) 308 .setCustomAudienceBuyers(new ArrayList<>()) 309 .setTrustedScoringSignalsUri(TRUSTED_SCORING_SIGNALS_URI) 310 .build(); 311 312 ListenableFuture<AdSelectionOutcome> result = 313 adSelectionClient.selectAds(adSelectionConfigNoBuyers); 314 315 Exception exception = 316 assertThrows( 317 ExecutionException.class, 318 () -> { 319 result.get(10, TimeUnit.SECONDS); 320 }); 321 assertThat(exception.getCause()).isInstanceOf(IllegalArgumentException.class); 322 } 323 overrideAdSelectionClient()324 private void overrideAdSelectionClient() { 325 mTestAdSelectionClient = 326 new TestAdSelectionClient.Builder() 327 .setContext(sContext) 328 .setExecutor(CALLBACK_EXECUTOR) 329 .setUseGetMethodToCreateManagerInstance(true) 330 .build(); 331 } 332 333 @Test testAddFromOutcomesOverrideFailsWithDebugModeDisabled()334 public void testAddFromOutcomesOverrideFailsWithDebugModeDisabled() throws Exception { 335 Assume.assumeFalse(mIsDebugMode); 336 337 AddAdSelectionFromOutcomesOverrideRequest request = 338 new AddAdSelectionFromOutcomesOverrideRequest( 339 AD_SELECTION_FROM_OUTCOMES_CONFIG, DECISION_LOGIC_JS, SELECTION_SIGNALS); 340 341 ListenableFuture<Void> result = 342 mTestAdSelectionClient.overrideAdSelectionFromOutcomesConfigRemoteInfo(request); 343 344 Exception exception = 345 assertThrows( 346 ExecutionException.class, 347 () -> { 348 result.get(10, TimeUnit.SECONDS); 349 }); 350 assertThat(exception.getCause()).isInstanceOf(SecurityException.class); 351 } 352 353 @Test testRemoveFromOutcomesOverrideFailsWithDebugModeDisabled()354 public void testRemoveFromOutcomesOverrideFailsWithDebugModeDisabled() throws Exception { 355 Assume.assumeFalse(mIsDebugMode); 356 357 RemoveAdSelectionFromOutcomesOverrideRequest request = 358 new RemoveAdSelectionFromOutcomesOverrideRequest(AD_SELECTION_FROM_OUTCOMES_CONFIG); 359 360 ListenableFuture<Void> result = 361 mTestAdSelectionClient.removeAdSelectionFromOutcomesConfigRemoteInfoOverride( 362 request); 363 364 Exception exception = 365 assertThrows( 366 ExecutionException.class, 367 () -> { 368 result.get(10, TimeUnit.SECONDS); 369 }); 370 assertThat(exception.getCause()).isInstanceOf(SecurityException.class); 371 } 372 373 @Test testResetAllFromOutcomesOverridesFailsWithDebugModeDisabled()374 public void testResetAllFromOutcomesOverridesFailsWithDebugModeDisabled() throws Exception { 375 Assume.assumeFalse(mIsDebugMode); 376 377 ListenableFuture<Void> result = 378 mTestAdSelectionClient.resetAllAdSelectionFromOutcomesConfigRemoteOverrides(); 379 380 Exception exception = 381 assertThrows( 382 ExecutionException.class, 383 () -> { 384 result.get(10, TimeUnit.SECONDS); 385 }); 386 assertThat(exception.getCause()).isInstanceOf(SecurityException.class); 387 } 388 389 // TODO(b/221876775): Add override CTS tests for frequency cap API review 390 } 391