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 com.android.adservices.ui.settings; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.os.Build; 25 26 import androidx.test.core.app.ApplicationProvider; 27 import androidx.test.ext.junit.runners.AndroidJUnit4; 28 import androidx.test.platform.app.InstrumentationRegistry; 29 import androidx.test.uiautomator.By; 30 import androidx.test.uiautomator.UiDevice; 31 import androidx.test.uiautomator.UiObject2; 32 import androidx.test.uiautomator.UiObjectNotFoundException; 33 import androidx.test.uiautomator.Until; 34 35 import com.android.adservices.api.R; 36 import com.android.adservices.common.AdServicesFlagsSetterRule; 37 import com.android.adservices.common.AdservicesTestHelper; 38 import com.android.adservices.service.Flags; 39 import com.android.adservices.ui.util.ApkTestUtil; 40 import com.android.compatibility.common.util.ShellUtils; 41 import com.android.modules.utils.build.SdkLevel; 42 43 import org.junit.After; 44 import org.junit.Assume; 45 import org.junit.Before; 46 import org.junit.Ignore; 47 import org.junit.Rule; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 51 @RunWith(AndroidJUnit4.class) 52 public class AppConsentSettingsUiAutomatorTest { 53 private static final Context CONTEXT = ApplicationProvider.getApplicationContext(); 54 private static final String TEST_APP_NAME = "com.example.adservices.samples.ui.consenttestapp"; 55 private static final String TEST_APP_APK_PATH = 56 "/data/local/tmp/cts/install/" + TEST_APP_NAME + ".apk"; 57 private static final String TEST_APP_ACTIVITY_NAME = TEST_APP_NAME + ".MainActivity"; 58 private static final ComponentName COMPONENT = 59 new ComponentName(TEST_APP_NAME, TEST_APP_ACTIVITY_NAME); 60 61 private static final String PRIVACY_SANDBOX_PACKAGE = "android.adservices.ui.SETTINGS"; 62 private static final String PRIVACY_SANDBOX_TEST_PACKAGE = "android.test.adservices.ui.MAIN"; 63 private static final int LAUNCH_TIMEOUT = 5000; 64 private static UiDevice sDevice; 65 66 private String mTestName; 67 68 @Rule(order = 0) 69 public final AdServicesFlagsSetterRule flags = 70 AdServicesFlagsSetterRule.forGlobalKillSwitchDisabledTests().setCompatModeFlags(); 71 72 @Before setup()73 public void setup() throws UiObjectNotFoundException { 74 String installMessage = ShellUtils.runShellCommand("pm install -r " + TEST_APP_APK_PATH); 75 assertThat(installMessage).contains("Success"); 76 77 // Initialize UiDevice instance 78 sDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 79 80 // Start from the home screen 81 sDevice.pressHome(); 82 } 83 84 @After teardown()85 public void teardown() { 86 ApkTestUtil.takeScreenshot(sDevice, getClass().getSimpleName() + "_" + mTestName + "_"); 87 88 AdservicesTestHelper.killAdservicesProcess(CONTEXT); 89 90 // Note aosp_x86 requires --user 0 to uninstall though arm doesn't. 91 ShellUtils.runShellCommand("pm uninstall --user 0 " + TEST_APP_NAME); 92 } 93 94 // TODO: Remove this blank test along with the other @Ignore. b/268351419 95 @Test placeholderTest()96 public void placeholderTest() { 97 mTestName = new Object() {}.getClass().getEnclosingMethod().getName(); 98 99 // As this class is the only test class in the test module and need to be @Ignore for the 100 // moment, add a blank test to help presubmit to pass. 101 assertThat(true).isTrue(); 102 } 103 104 @Test 105 @Ignore("Flaky test. (b/268351419)") consentSystemServerOnlyTest()106 public void consentSystemServerOnlyTest() throws InterruptedException { 107 mTestName = new Object() {}.getClass().getEnclosingMethod().getName(); 108 109 // System server is not available on S-, skip this test for S- 110 Assume.assumeTrue(SdkLevel.isAtLeastT()); 111 appConsentTest(0, false); 112 } 113 114 @Test 115 @Ignore("Flaky test. (b/268351419)") consentPpApiOnlyTest()116 public void consentPpApiOnlyTest() throws InterruptedException { 117 mTestName = new Object() {}.getClass().getEnclosingMethod().getName(); 118 119 appConsentTest(1, false); 120 } 121 122 @Test 123 @Ignore("Flaky test. (b/268351419)") consentSystemServerAndPpApiTest()124 public void consentSystemServerAndPpApiTest() throws InterruptedException { 125 mTestName = new Object() {}.getClass().getEnclosingMethod().getName(); 126 127 // System server is not available on S-, skip this test for S- 128 Assume.assumeTrue(SdkLevel.isAtLeastT()); 129 appConsentTest(2, false); 130 } 131 132 @Test 133 @Ignore("Flaky test. (b/268351419)") consentAppSearchOnlyTest()134 public void consentAppSearchOnlyTest() throws UiObjectNotFoundException, InterruptedException { 135 ShellUtils.runShellCommand( 136 "device_config put adservices enable_appsearch_consent_data true"); 137 ShellUtils.runShellCommand("device_config put adservices consent_source_of_truth 3"); 138 appConsentTest(Flags.APPSEARCH_ONLY, false); 139 ShellUtils.runShellCommand("device_config put adservices consent_source_of_truth null"); 140 } 141 142 @Test 143 @Ignore("Flaky test. (b/268351419)") consentAppSearchOnlyDialogsOnTest()144 public void consentAppSearchOnlyDialogsOnTest() 145 throws UiObjectNotFoundException, InterruptedException { 146 ShellUtils.runShellCommand( 147 "device_config put adservices enable_appsearch_consent_data true"); 148 ShellUtils.runShellCommand("device_config put adservices consent_source_of_truth 3"); 149 appConsentTest(Flags.APPSEARCH_ONLY, true); 150 ShellUtils.runShellCommand("device_config put adservices consent_source_of_truth null"); 151 } 152 153 @Test 154 @Ignore("Flaky test. (b/268351419)") consentSystemServerOnlyDialogsOnTest()155 public void consentSystemServerOnlyDialogsOnTest() 156 throws UiObjectNotFoundException, InterruptedException { 157 mTestName = new Object() {}.getClass().getEnclosingMethod().getName(); 158 159 // System server is not available on S-, skip this test for S- 160 Assume.assumeTrue(SdkLevel.isAtLeastT()); 161 appConsentTest(0, true); 162 } 163 164 @Test 165 @Ignore("Flaky test. (b/268351419)") consentPpApiOnlyDialogsOnTest()166 public void consentPpApiOnlyDialogsOnTest() throws InterruptedException { 167 mTestName = new Object() {}.getClass().getEnclosingMethod().getName(); 168 169 appConsentTest(1, true); 170 } 171 172 @Test 173 @Ignore("Flaky test. (b/268351419)") consentSystemServerAndPpApiDialogsOnTest()174 public void consentSystemServerAndPpApiDialogsOnTest() throws InterruptedException { 175 mTestName = new Object() {}.getClass().getEnclosingMethod().getName(); 176 177 // System server is not available on S-, skip this test for S- 178 Assume.assumeTrue(SdkLevel.isAtLeastT()); 179 appConsentTest(2, true); 180 } 181 setPpApiConsentToGiven()182 private void setPpApiConsentToGiven() { 183 // launch app 184 launchSettingApp(); 185 186 UiObject2 mainSwitch = ApkTestUtil.getConsentSwitch(sDevice); 187 assertThat(mainSwitch).isNotNull(); 188 189 if (!mainSwitch.isChecked()) { 190 mainSwitch.click(); 191 } 192 } 193 launchSettingApp()194 private void launchSettingApp() { 195 String privacySandboxUi; 196 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { 197 privacySandboxUi = PRIVACY_SANDBOX_TEST_PACKAGE; 198 } else { 199 privacySandboxUi = PRIVACY_SANDBOX_PACKAGE; 200 } 201 Context context = ApplicationProvider.getApplicationContext(); 202 Intent intent = new Intent(privacySandboxUi); 203 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 204 context.startActivity(intent); 205 206 // Wait for the app to appear 207 sDevice.wait(Until.hasObject(By.pkg(privacySandboxUi).depth(0)), LAUNCH_TIMEOUT); 208 } 209 appConsentTest(int consentSourceOfTruth, boolean dialogsOn)210 private void appConsentTest(int consentSourceOfTruth, boolean dialogsOn) 211 throws InterruptedException { 212 ShellUtils.runShellCommand( 213 "device_config put adservices consent_source_of_truth " + consentSourceOfTruth); 214 ShellUtils.runShellCommand( 215 "device_config put adservices ui_dialogs_feature_enabled " + dialogsOn); 216 AdservicesTestHelper.killAdservicesProcess(CONTEXT); 217 218 // Wait for launcher 219 final String launcherPackage = sDevice.getLauncherPackageName(); 220 assertThat(launcherPackage).isNotNull(); 221 sDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); 222 ShellUtils.runShellCommand("device_config put adservices ga_ux_enabled false"); 223 224 setPpApiConsentToGiven(); 225 226 // Initiate test app consent. 227 initiateTestAppConsent(); 228 229 // open apps view 230 launchSettingApp(); 231 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title); 232 233 blockAppConsent(dialogsOn); 234 235 unblockAppConsent(dialogsOn); 236 237 assertThat(ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title)) 238 .isNotNull(); 239 240 resetAppConsent(dialogsOn); 241 242 assertThat(ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title, 0)) 243 .isNull(); 244 assertThat(ApkTestUtil.getElement(sDevice, R.string.settingsUI_blocked_apps_title, 0)) 245 .isNull(); 246 assertThat(ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_view_no_apps_text, 0)) 247 .isNotNull(); 248 } 249 unblockAppConsent(boolean dialogsOn)250 private void unblockAppConsent(boolean dialogsOn) throws InterruptedException { 251 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_apps_title); 252 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_unblock_app_title); 253 254 if (dialogsOn) { 255 // click unblock 256 UiObject2 dialogTitle = 257 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_app_message); 258 UiObject2 positiveText = 259 ApkTestUtil.getElement( 260 sDevice, R.string.settingsUI_dialog_unblock_app_positive_text); 261 assertThat(dialogTitle).isNotNull(); 262 assertThat(positiveText).isNotNull(); 263 264 // confirm 265 positiveText.click(); 266 } 267 268 assertThat( 269 ApkTestUtil.getElement( 270 sDevice, 271 R.string.settingsUI_apps_view_no_blocked_apps_text)) 272 .isNotNull(); 273 sDevice.pressBack(); 274 } 275 resetAppConsent(boolean dialogsOn)276 private void resetAppConsent(boolean dialogsOn) throws InterruptedException { 277 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_apps_title); 278 279 if (dialogsOn) { 280 UiObject2 dialogTitle = 281 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_message); 282 UiObject2 positiveText = 283 ApkTestUtil.getElement( 284 sDevice, R.string.settingsUI_dialog_reset_app_positive_text); 285 assertThat(dialogTitle).isNotNull(); 286 assertThat(positiveText).isNotNull(); 287 288 // confirm 289 positiveText.click(); 290 } 291 } 292 blockAppConsent(boolean dialogsOn)293 private void blockAppConsent(boolean dialogsOn) throws InterruptedException { 294 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_block_app_title); 295 296 if (dialogsOn) { 297 UiObject2 dialogTitle = 298 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_message); 299 UiObject2 positiveText = 300 ApkTestUtil.getElement( 301 sDevice, R.string.settingsUI_dialog_block_app_positive_text); 302 assertThat(dialogTitle).isNotNull(); 303 assertThat(positiveText).isNotNull(); 304 positiveText.click(); 305 } 306 } 307 initiateTestAppConsent()308 private void initiateTestAppConsent() throws InterruptedException { 309 String installMessage = ShellUtils.runShellCommand("pm install -r " + TEST_APP_APK_PATH); 310 assertThat(installMessage).contains("Success"); 311 312 ShellUtils.runShellCommand("device_config set_sync_disabled_for_tests persistent"); 313 ShellUtils.runShellCommand("device_config put adservices global_kill_switch false"); 314 ShellUtils.runShellCommand( 315 "device_config put adservices" 316 + " fledge_custom_audience_service_kill_switch false"); 317 ShellUtils.runShellCommand( 318 "device_config put adservices" 319 + " fledge_schedule_custom_audience_update_enabled true"); 320 ShellUtils.runShellCommand( 321 "device_config put adservices disable_fledge_enrollment_check true"); 322 323 ShellUtils.runShellCommand("device_config put adservices ppapi_app_allow_list *"); 324 325 Context context = ApplicationProvider.getApplicationContext(); 326 Intent intent = new Intent().setComponent(COMPONENT); 327 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 328 context.startActivity(intent); 329 330 sDevice.wait(Until.hasObject(By.pkg(TEST_APP_NAME).depth(0)), LAUNCH_TIMEOUT); 331 332 Thread.sleep(1000); 333 334 ShellUtils.runShellCommand("device_config set_sync_disabled_for_tests none"); 335 ShellUtils.runShellCommand( 336 "am force-stop com.example.adservices.samples.ui.consenttestapp"); 337 ShellUtils.runShellCommand( 338 "device_config put adservices disable_fledge_enrollment_check null"); 339 } 340 } 341