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