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 package com.android.adservices.tests.ui.libs; 17 18 import static android.Manifest.permission.POST_NOTIFICATIONS; 19 20 import static com.android.adservices.tests.ui.libs.UiConstants.AD_ID_ENABLED; 21 import static com.android.adservices.tests.ui.libs.UiConstants.ENTRY_POINT_ENABLED; 22 import static com.android.adservices.tests.ui.libs.UiConstants.SYSTEM_UI_NAME; 23 import static com.android.adservices.tests.ui.libs.UiConstants.SYSTEM_UI_RESOURCE_ID; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import android.adservices.common.AdServicesCommonManager; 28 import android.adservices.common.AdServicesStates; 29 import android.content.Context; 30 import android.graphics.Point; 31 import android.os.OutcomeReceiver; 32 33 import androidx.test.platform.app.InstrumentationRegistry; 34 import androidx.test.uiautomator.By; 35 import androidx.test.uiautomator.BySelector; 36 import androidx.test.uiautomator.Direction; 37 import androidx.test.uiautomator.SearchCondition; 38 import androidx.test.uiautomator.UiDevice; 39 import androidx.test.uiautomator.UiObject2; 40 import androidx.test.uiautomator.Until; 41 42 import com.android.adservices.LogUtil; 43 import com.android.adservices.api.R; 44 import com.android.adservices.common.AdservicesTestHelper; 45 import com.android.adservices.shared.testing.common.FileHelper; 46 import com.android.compatibility.common.util.ShellUtils; 47 48 import com.google.common.util.concurrent.SettableFuture; 49 50 import java.io.File; 51 import java.text.SimpleDateFormat; 52 import java.time.Instant; 53 import java.util.Date; 54 import java.util.List; 55 import java.util.Locale; 56 import java.util.UUID; 57 import java.util.concurrent.Executors; 58 import java.util.regex.Pattern; 59 60 public class UiUtils { 61 private static final String PRIVACY_SANDBOX_PACKAGE_NAME = "android.adservices.ui.SETTINGS"; 62 private static final String NOTIFICATION_PACKAGE_NAME = "android.adservices.ui.NOTIFICATIONS"; 63 public static final int LAUNCH_TIMEOUT = 5000; 64 public static final int PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT = 500; 65 public static final int SCROLL_WAIT_TIME = 1000; 66 67 private static final int DEFAULT_BINDER_CONNECTION_TIMEOUT_MS = 10000; 68 69 private static final String ANDROID_WIDGET_SCROLLVIEW = "android.widget.ScrollView"; 70 forceSetFlag(String flagName, boolean newFlagValue)71 private static void forceSetFlag(String flagName, boolean newFlagValue) throws Exception { 72 String shellCmdGetTemplate; 73 String shellCmdSetTemplate; 74 if (flagName.endsWith("debug_mode")) { 75 shellCmdGetTemplate = "getprop debug.adservices.%s"; 76 shellCmdSetTemplate = "setprop debug.adservices.%s %s"; 77 } else { 78 shellCmdGetTemplate = "device_config get adservices %s"; 79 shellCmdSetTemplate = "device_config put adservices %s %s"; 80 } 81 String currentFlagValue = ShellUtils.runShellCommand(shellCmdGetTemplate, flagName); 82 83 for (int i = 0; i < 5; i++) { 84 if (currentFlagValue.equals(String.valueOf(newFlagValue))) { 85 return; 86 } 87 88 ShellUtils.runShellCommand(shellCmdSetTemplate, flagName, newFlagValue); 89 90 Thread.sleep(250); 91 92 currentFlagValue = ShellUtils.runShellCommand(shellCmdGetTemplate, flagName); 93 94 LogUtil.e(String.format("Flag was not set on iteration %d.", i)); 95 } 96 97 throw new IllegalStateException("Unable to set flag in 5 iterations."); 98 } 99 refreshConsentResetToken()100 public static void refreshConsentResetToken() { 101 ShellUtils.runShellCommand( 102 "device_config put adservices consent_notification_reset_token " 103 + UUID.randomUUID().toString()); 104 } 105 turnOffEnableAdsServicesAPI()106 public static void turnOffEnableAdsServicesAPI() throws Exception { 107 forceSetFlag("enable_ad_services_system_api", false); 108 } 109 turnOnEnableAdsServicesAPI()110 public static void turnOnEnableAdsServicesAPI() throws Exception { 111 forceSetFlag("enable_ad_services_system_api", true); 112 } 113 disableSchedulingParams()114 public static void disableSchedulingParams() { 115 ShellUtils.runShellCommand( 116 "device_config put adservices consent_notification_interval_begin_ms 0"); 117 // set the notification interval end time to 12:00 AM 118 ShellUtils.runShellCommand( 119 "device_config put adservices consent_notification_interval_end_ms 86400000"); 120 } 121 enableConsentDebugMode()122 public static void enableConsentDebugMode() throws Exception { 123 forceSetFlag("consent_notification_debug_mode", true); 124 } 125 disableConsentDebugMode()126 public static void disableConsentDebugMode() throws Exception { 127 forceSetFlag("consent_notification_debug_mode", false); 128 } 129 enableGlobalKillSwitch()130 public static void enableGlobalKillSwitch() throws Exception { 131 forceSetFlag("global_kill_switch", true); 132 } 133 setAsEuDevice()134 public static void setAsEuDevice() throws Exception { 135 forceSetFlag("is_eea_device", true); 136 } 137 setAsRowDevice()138 public static void setAsRowDevice() throws Exception { 139 forceSetFlag("is_eea_device", false); 140 } 141 enableU18()142 public static void enableU18() throws Exception { 143 forceSetFlag("u18_ux_enabled", true); 144 } 145 enableGa()146 public static void enableGa() throws Exception { 147 forceSetFlag("ga_ux_enabled", true); 148 } 149 150 /** Override flag rvc_ux_enabled in tests to true */ enableRvc()151 public static void enableRvc() throws Exception { 152 forceSetFlag("rvc_ux_enabled", true); 153 } 154 155 /** Override flag rvc_post_ota_notification_enabled in tests to true */ enableRvcNotification()156 public static void enableRvcNotification() throws Exception { 157 forceSetFlag("rvc_post_ota_notification_enabled", true); 158 } 159 160 /** Override flag rvc_ux_enabled in tests to false */ disableRvc()161 public static void disableRvc() throws Exception { 162 forceSetFlag("rvc_ux_enabled", false); 163 } 164 165 /** Disables the enableAdServices system API. */ turnOffEnableAdServicesSystemApi()166 public static void turnOffEnableAdServicesSystemApi() throws Exception { 167 forceSetFlag("enable_ad_services_system_api", false); 168 } 169 170 /** Enables the enableAdServices system API. */ turnOnAdServicesSystemApi()171 public static void turnOnAdServicesSystemApi() throws Exception { 172 forceSetFlag("enable_ad_services_system_api", true); 173 } 174 enableBeta()175 public static void enableBeta() throws Exception { 176 forceSetFlag("ga_ux_enabled", false); 177 } 178 enableOtaStrings()179 public static void enableOtaStrings() throws Exception { 180 forceSetFlag("ui_ota_strings_feature_enabled", true); 181 } 182 disableOtaStrings()183 public static void disableOtaStrings() throws Exception { 184 forceSetFlag("ui_ota_strings_feature_enabled", false); 185 } 186 restartAdservices()187 public static void restartAdservices() { 188 ShellUtils.runShellCommand("am force-stop com.google.android.adservices.api"); 189 ShellUtils.runShellCommand("am force-stop com.android.adservices.api"); 190 } 191 clearSavedStatus()192 public static void clearSavedStatus() { 193 ShellUtils.runShellCommand( 194 "rm /data/user/0/com.google.android.adservices.api/files/" 195 + "ConsentManagerStorageIdentifier.xml"); 196 ShellUtils.runShellCommand( 197 "rm /data/user/0/com.android.adservices.api/files/" 198 + "ConsentManagerStorageIdentifier.xml"); 199 ShellUtils.runShellCommand( 200 "rm /data/system/adservices/0/consent/ConsentManagerStorageIdentifier.xml"); 201 } 202 setSourceOfTruthToPPAPI()203 public static void setSourceOfTruthToPPAPI() { 204 ShellUtils.runShellCommand("device_config put adservices consent_source_of_truth 1"); 205 } 206 207 /** Set flag consent_manager_debug_mode to true in tests */ setConsentManagerDebugMode()208 public static void setConsentManagerDebugMode() { 209 ShellUtils.runShellCommand("setprop debug.adservices.consent_manager_debug_mode true"); 210 } 211 212 /** Set flag consent_manager_ota_debug_mode to true in tests */ setConsentManagerOtaDebugMode()213 public static void setConsentManagerOtaDebugMode() { 214 ShellUtils.runShellCommand("setprop debug.adservices.consent_manager_ota_debug_mode true"); 215 } 216 217 /** Set flag consent_manager_debug_mode to false in tests */ resetConsentManagerDebugMode()218 public static void resetConsentManagerDebugMode() { 219 ShellUtils.runShellCommand("setprop debug.adservices.consent_manager_debug_mode false"); 220 } 221 enableNotificationPermission()222 public static void enableNotificationPermission() { 223 InstrumentationRegistry.getInstrumentation() 224 .getUiAutomation() 225 .grantRuntimePermission("com.android.adservices.api", POST_NOTIFICATIONS); 226 } 227 disableNotificationFlowV2()228 public static void disableNotificationFlowV2() throws Exception { 229 forceSetFlag("eu_notif_flow_change_enabled", false); 230 } 231 232 /** set the binder time for cts test */ setBinderTimeout()233 public static void setBinderTimeout() throws Exception { 234 ShellUtils.runShellCommand( 235 "setprop debug.adservices.binder_timeout %s", DEFAULT_BINDER_CONNECTION_TIMEOUT_MS); 236 } 237 238 /** enable pas */ enablePas()239 public static void enablePas() throws Exception { 240 forceSetFlag("pas_ux_enabled", true); 241 } 242 243 /** disable pas */ disablePas()244 public static void disablePas() throws Exception { 245 forceSetFlag("pas_ux_enabled", false); 246 } 247 verifyNotification( Context context, UiDevice device, boolean isDisplayed, boolean isEuTest, UiConstants.UX ux)248 public static void verifyNotification( 249 Context context, 250 UiDevice device, 251 boolean isDisplayed, 252 boolean isEuTest, 253 UiConstants.UX ux) 254 throws Exception { 255 int notificationTitle = -1; 256 int notificationHeader = -1; 257 switch (ux) { 258 case GA_UX: 259 // Should match the contentTitle string in ConsentNotificationTrigger.java. 260 notificationTitle = 261 isEuTest 262 ? R.string.notificationUI_notification_ga_title_eu_v2 263 : R.string.notificationUI_notification_ga_title_v2; 264 // Should match the text in consent_notification_screen_1_ga_v2_eu.xml and 265 // consent_notification_screen_1_ga_v2_row.xml, respectively. 266 notificationHeader = 267 isEuTest 268 ? R.string.notificationUI_fledge_measurement_title_v2 269 : R.string.notificationUI_header_ga_title_v2; 270 break; 271 case BETA_UX: 272 notificationTitle = 273 isEuTest 274 ? R.string.notificationUI_notification_title_eu 275 : R.string.notificationUI_notification_title; 276 notificationHeader = 277 isEuTest 278 ? R.string.notificationUI_header_title_eu 279 : R.string.notificationUI_header_title; 280 break; 281 case U18_UX: 282 notificationTitle = R.string.notificationUI_u18_notification_title; 283 notificationHeader = R.string.notificationUI_u18_header_title; 284 break; 285 } 286 287 verifyNotification(context, device, isDisplayed, notificationTitle, notificationHeader); 288 } 289 verifyNotification( Context context, UiDevice device, boolean isDisplayed, int notificationTitle, int notificationHeader)290 public static void verifyNotification( 291 Context context, 292 UiDevice device, 293 boolean isDisplayed, 294 int notificationTitle, 295 int notificationHeader) 296 throws Exception { 297 device.openNotification(); 298 device.waitForIdle(LAUNCH_TIMEOUT); 299 // Wait few seconds for Adservices notification to show, waitForIdle is not enough. 300 Thread.sleep(LAUNCH_TIMEOUT); 301 UiObject2 scroller = device.findObject(By.res(SYSTEM_UI_RESOURCE_ID)); 302 303 BySelector notificationTitleSelector = By.text(getString(context, notificationTitle)); 304 if (!isDisplayed) { 305 assertThat(scroller.hasObject(notificationTitleSelector)).isFalse(); 306 return; 307 } 308 assertThat(scroller.hasObject(notificationTitleSelector)).isTrue(); 309 UiObject2 notificationCard = 310 scroller.findObject(By.text(getString(context, notificationTitle))); 311 312 notificationCard.click(); 313 device.waitForIdle(LAUNCH_TIMEOUT); 314 Thread.sleep(LAUNCH_TIMEOUT); 315 UiObject2 title = getElement(context, device, notificationHeader); 316 assertThat(title).isNotNull(); 317 } 318 setupOTAStrings( Context context, UiDevice device, AdServicesCommonManager commonManager, String mddURL)319 public static void setupOTAStrings( 320 Context context, UiDevice device, AdServicesCommonManager commonManager, String mddURL) 321 throws Exception { 322 setAdServicesFlagsForOTATesting(mddURL); 323 324 AdservicesTestHelper.killAdservicesProcess(context); 325 326 // Consent is required to trigger the MDD job. 327 commonManager.setAdServicesEnabled(ENTRY_POINT_ENABLED, AD_ID_ENABLED); 328 Thread.sleep(LAUNCH_TIMEOUT); 329 330 ShellUtils.runShellCommand("cmd jobscheduler run -f com.google.android.adservices.api 14"); 331 332 Thread.sleep(LAUNCH_TIMEOUT); 333 clearNotifications(context, device); 334 } 335 setAdServicesFlagsForOTATesting(String mddURL)336 public static void setAdServicesFlagsForOTATesting(String mddURL) throws Exception { 337 ShellUtils.runShellCommand("device_config put adservices ga_ux_enabled false"); 338 ShellUtils.runShellCommand( 339 "device_config put adservices ui_ota_strings_feature_enabled true"); 340 ShellUtils.runShellCommand("device_config put adservices adservice_enabled true"); 341 ShellUtils.runShellCommand("setprop debug.adservices.consent_notification_debug_mode true"); 342 ShellUtils.runShellCommand("device_config put adservices global_kill_switch false"); 343 ShellUtils.runShellCommand( 344 "device_config put adservices mdd_ui_ota_strings_manifest_file_url " + mddURL); 345 346 // Set as ROW device for default consent opt-in. 347 UiUtils.setAsRowDevice(); 348 } 349 setOTADownloadTimeout(long timeout)350 public static void setOTADownloadTimeout(long timeout) { 351 ShellUtils.runShellCommand( 352 String.format( 353 "device_config put adservices ui_ota_strings_download_deadline %d", 354 timeout)); 355 } 356 clearNotifications(Context context, UiDevice device)357 public static void clearNotifications(Context context, UiDevice device) 358 throws InterruptedException { 359 device.openNotification(); 360 Thread.sleep(LAUNCH_TIMEOUT); 361 UiObject2 scroller2 = 362 device.findObject(By.res("com.android.systemui:id/notification_stack_scroller")); 363 UiObject2 notificationCard = 364 scroller2.findObject( 365 By.textContains( 366 getString(context, R.string.notificationUI_notification_title))); 367 368 if (notificationCard != null) { 369 notificationCard.click(); 370 } 371 Thread.sleep(LAUNCH_TIMEOUT); 372 device.pressHome(); 373 } 374 verifyNotificationAndSettingsPage( Context context, UiDevice device, Boolean isOTA)375 public static void verifyNotificationAndSettingsPage( 376 Context context, UiDevice device, Boolean isOTA) throws InterruptedException { 377 // open notification tray 378 device.openNotification(); 379 Thread.sleep(LAUNCH_TIMEOUT); 380 device.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT); 381 382 // verify notification card 383 UiObject2 scroller = 384 device.findObject(By.res("com.android.systemui:id/notification_stack_scroller")); 385 386 String targetStr = 387 isOTA 388 ? getOTAString(context, R.string.notificationUI_notification_title) 389 : getString(context, R.string.notificationUI_notification_title); 390 391 UiObject2 notificationCard = scroller.findObject(By.text(targetStr)); 392 Thread.sleep(LAUNCH_TIMEOUT); 393 394 notificationCard.click(); 395 396 // Wait for the notification landing page to appear 397 device.wait(Until.hasObject(By.pkg(NOTIFICATION_PACKAGE_NAME).depth(0)), LAUNCH_TIMEOUT); 398 399 // verify strings 400 UiObject2 title = 401 isOTA 402 ? scrollToOTAElement(context, device, R.string.notificationUI_header_title) 403 : scrollToElement(context, device, R.string.notificationUI_header_title); 404 405 assertThat(title).isNotNull(); 406 // open settings 407 scrollToThenClickElementContainingText( 408 device, 409 isOTA 410 ? "Manage privacy settings!" 411 : getString(context, R.string.notificationUI_left_control_button_text)); 412 413 // Wait for the app to appear 414 device.wait(Until.hasObject(By.pkg(PRIVACY_SANDBOX_PACKAGE_NAME).depth(0)), LAUNCH_TIMEOUT); 415 416 // verify strings have changed 417 UiObject2 appButton = 418 isOTA 419 ? scrollToOTAElement(context, device, R.string.settingsUI_apps_title) 420 : scrollToElement(context, device, R.string.settingsUI_apps_title); 421 422 device.waitForIdle(LAUNCH_TIMEOUT); 423 assertThat(appButton).isNotNull(); 424 UiObject2 topicsButton = 425 isOTA 426 ? scrollToOTAElement(context, device, R.string.settingsUI_topics_title) 427 : scrollToElement(context, device, R.string.settingsUI_topics_title); 428 assertThat(topicsButton).isNotNull(); 429 } 430 connectToWifi()431 public static void connectToWifi() { 432 ShellUtils.runShellCommand("svc wifi enable"); 433 ShellUtils.runShellCommand("cmd wifi connect-network VirtWifi open"); 434 } 435 turnOffWifi()436 public static void turnOffWifi() { 437 ShellUtils.runShellCommand("svc wifi disable"); 438 } 439 scrollToThenClickElementContainingText(UiDevice device, String text)440 private static void scrollToThenClickElementContainingText(UiDevice device, String text) { 441 UiObject2 element = scrollToElement(device, text); 442 element.click(); 443 } 444 scrollToOTAElement(Context context, UiDevice device, int resId)445 private static UiObject2 scrollToOTAElement(Context context, UiDevice device, int resId) { 446 return scrollToElement(device, getOTAString(context, resId)); 447 } 448 scrollToElement(UiDevice device, String targetStr)449 private static UiObject2 scrollToElement(UiDevice device, String targetStr) { 450 UiObject2 scrollView = 451 device.findObject(By.clazz(ANDROID_WIDGET_SCROLLVIEW).scrollable(true)); 452 UiObject2 element = 453 scrollView.scrollUntil( 454 Direction.DOWN, Until.findObject(By.textContains(targetStr))); 455 if (element != null) { 456 return element; 457 } 458 return device.findObject(By.textContains(targetStr)); 459 } 460 scrollToElement(Context context, UiDevice device, int resId)461 private static UiObject2 scrollToElement(Context context, UiDevice device, int resId) { 462 return scrollToElement(device, getString(context, resId)); 463 } 464 465 // Test strings for OTA have an exclamation mark appended to the end getOTAString(Context context, int resourceId)466 private static String getOTAString(Context context, int resourceId) { 467 return getString(context, resourceId) + "!"; 468 } 469 470 /** 471 * Swipes through the screen to show elements on the button of the page but hidden by the 472 * navigation bar. 473 */ gentleSwipe(UiDevice device)474 public static void gentleSwipe(UiDevice device) { 475 UiObject2 scrollView = 476 device.findObject(By.scrollable(true).clazz(ANDROID_WIDGET_SCROLLVIEW)); 477 // Some devices on R is not scrollable 478 if (scrollView != null) { 479 scrollView.scroll(Direction.DOWN, /* percent */ 0.25F); 480 } 481 } 482 setFlipFlow(boolean isFlip)483 public static void setFlipFlow(boolean isFlip) { 484 ShellUtils.runShellCommand( 485 "device_config put adservices eu_notif_flow_change_enabled " + isFlip); 486 } 487 488 /** set get adservices common states services enabled */ setGetAdservicesCommonStatesServiceEnable(boolean enable)489 public static void setGetAdservicesCommonStatesServiceEnable(boolean enable) { 490 ShellUtils.runShellCommand( 491 "device_config put adservices get_adservices_common_states_api_enabled " + enable); 492 } 493 494 /** set get adservices common states services enabled */ setGetAdservicesCommonStatesAllowList(String list)495 public static void setGetAdservicesCommonStatesAllowList(String list) { 496 ShellUtils.runShellCommand( 497 "device_config put adservices get_adservices_common_states_allow_list " + list); 498 } 499 getString(Context context, int resourceId)500 public static String getString(Context context, int resourceId) { 501 return context.getResources().getString(resourceId); 502 } 503 scrollToAndClick(Context context, UiDevice device, int resId)504 public static void scrollToAndClick(Context context, UiDevice device, int resId) { 505 scrollTo(context, device, resId); 506 UiObject2 consentPageButton = 507 device.wait( 508 getSearchCondByResId(context, resId), PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT); 509 clickTopLeft(consentPageButton); 510 } 511 getSearchCondByResId(Context context, int resId)512 public static SearchCondition<UiObject2> getSearchCondByResId(Context context, int resId) { 513 String targetStr = getString(context, resId); 514 return Until.findObject(By.text(Pattern.compile(targetStr, Pattern.CASE_INSENSITIVE))); 515 } 516 getPageElement(Context context, UiDevice device, int resId)517 public static UiObject2 getPageElement(Context context, UiDevice device, int resId) { 518 return device.findObject(By.text(getString(context, resId))); 519 } 520 scrollTo(Context context, UiDevice device, int resId)521 public static UiObject2 scrollTo(Context context, UiDevice device, int resId) { 522 UiObject2 scrollView = 523 device.findObject(By.scrollable(true).clazz(ANDROID_WIDGET_SCROLLVIEW)); 524 if (scrollView != null) { 525 String targetStr = getString(context, resId); 526 scrollView.scrollUntil( 527 Direction.DOWN, 528 Until.findObject( 529 By.text(Pattern.compile(targetStr, Pattern.CASE_INSENSITIVE)))); 530 } 531 return getElement(context, device, resId); 532 } 533 getElement(Context context, UiDevice device, int resId)534 public static UiObject2 getElement(Context context, UiDevice device, int resId) { 535 return getElement(context, device, resId, 0); 536 } 537 getElement(Context context, UiDevice device, int resId, int index)538 public static UiObject2 getElement(Context context, UiDevice device, int resId, int index) { 539 String targetStr = getString(context, resId); 540 List<UiObject2> objList = 541 device.findObjects(By.text(Pattern.compile(targetStr, Pattern.CASE_INSENSITIVE))); 542 if (objList.size() <= index) { 543 return null; 544 } 545 return objList.get(index); 546 } 547 clickTopLeft(UiObject2 obj)548 public static void clickTopLeft(UiObject2 obj) { 549 assertThat(obj).isNotNull(); 550 obj.click(new Point(obj.getVisibleBounds().top, obj.getVisibleBounds().left)); 551 } 552 takeScreenshot(UiDevice device, String methodName)553 public static void takeScreenshot(UiDevice device, String methodName) { 554 try { 555 String timeStamp = 556 new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US) 557 .format(Date.from(Instant.now())); 558 559 File screenshotFile = 560 new File( 561 FileHelper.getAdServicesTestsOutputDir(), 562 methodName + timeStamp + ".png"); 563 device.takeScreenshot(screenshotFile); 564 } catch (RuntimeException e) { 565 LogUtil.e("Failed to take screenshot: " + e.getMessage()); 566 } 567 } 568 resetAdServicesConsentData(Context context)569 public static void resetAdServicesConsentData(Context context) throws Exception { 570 // Neeed to disable debug mode since it takes precedence over reset channel. 571 disableConsentDebugMode(); 572 turnOnAdServicesSystemApi(); 573 574 AdServicesCommonManager mCommonManager = AdServicesCommonManager.get(context); 575 576 // Reset consent and thereby AdServices data before each test. 577 UiUtils.refreshConsentResetToken(); 578 579 SettableFuture<Boolean> responseFuture = SettableFuture.create(); 580 581 mCommonManager.enableAdServices( 582 new AdServicesStates.Builder() 583 .setAdIdEnabled(true) 584 .setAdultAccount(true) 585 .setU18Account(true) 586 .setPrivacySandboxUiEnabled(true) 587 .setPrivacySandboxUiRequest(false) 588 .build(), 589 Executors.newCachedThreadPool(), 590 new OutcomeReceiver<>() { 591 @Override 592 public void onResult(Boolean result) { 593 responseFuture.set(result); 594 } 595 596 @Override 597 public void onError(Exception exception) { 598 responseFuture.setException(exception); 599 } 600 }); 601 602 Boolean response = responseFuture.get(); 603 assertThat(response).isTrue(); 604 } 605 606 /** Returns a [BySelector] of a resource in sysui package. */ sysuiResSelector(String resourceId)607 public static BySelector sysuiResSelector(String resourceId) { 608 return By.pkg(SYSTEM_UI_NAME).res(SYSTEM_UI_NAME, resourceId); 609 } 610 } 611