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 package com.android.adservices.ui.settings; 17 18 import static com.android.adservices.service.ui.ux.collection.PrivacySandboxUxCollection.GA_UX; 19 20 import static com.google.common.truth.Truth.assertThat; 21 22 import static org.mockito.ArgumentMatchers.any; 23 import static org.mockito.Mockito.doNothing; 24 import static org.mockito.Mockito.doReturn; 25 import static org.mockito.Mockito.timeout; 26 import static org.mockito.Mockito.verify; 27 28 import android.content.Context; 29 import android.content.Intent; 30 import android.os.RemoteException; 31 32 import androidx.test.ext.junit.runners.AndroidJUnit4; 33 import androidx.test.filters.FlakyTest; 34 import androidx.test.platform.app.InstrumentationRegistry; 35 import androidx.test.uiautomator.By; 36 import androidx.test.uiautomator.UiDevice; 37 import androidx.test.uiautomator.UiObject2; 38 import androidx.test.uiautomator.Until; 39 40 import com.android.adservices.LogUtil; 41 import com.android.adservices.api.R; 42 import com.android.adservices.common.AdServicesExtendedMockitoTestCase; 43 import com.android.adservices.common.AdservicesTestHelper; 44 import com.android.adservices.data.topics.Topic; 45 import com.android.adservices.service.Flags; 46 import com.android.adservices.service.FlagsFactory; 47 import com.android.adservices.service.common.BackgroundJobsManager; 48 import com.android.adservices.service.consent.AdServicesApiConsent; 49 import com.android.adservices.service.consent.AdServicesApiType; 50 import com.android.adservices.service.consent.App; 51 import com.android.adservices.service.consent.ConsentManager; 52 import com.android.adservices.shared.testing.annotations.RequiresSdkLevelAtLeastT; 53 import com.android.adservices.ui.util.ApkTestUtil; 54 import com.android.dx.mockito.inline.extended.ExtendedMockito; 55 import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic; 56 57 import com.google.common.collect.ImmutableList; 58 59 import org.junit.After; 60 import org.junit.Before; 61 import org.junit.Test; 62 import org.junit.runner.RunWith; 63 import org.mockito.Mock; 64 65 import java.util.ArrayList; 66 import java.util.List; 67 68 @SpyStatic(FlagsFactory.class) 69 @SpyStatic(BackgroundJobsManager.class) 70 @SpyStatic(ConsentManager.class) 71 @RequiresSdkLevelAtLeastT(reason = "Back Compat only support GA UX") 72 @RunWith(AndroidJUnit4.class) 73 public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase { 74 75 private static final String PRIVACY_SANDBOX_TEST_PACKAGE = "android.test.adservices.ui.MAIN"; 76 private static final int LAUNCH_TIMEOUT = 5000; 77 private static UiDevice sDevice; 78 79 @Mock 80 private ConsentManager mConsentManager; 81 @Mock 82 private Flags mMockFlags; 83 84 @Before setup()85 public void setup() throws Exception { 86 mocker.mockGetFlags(mMockFlags); 87 doReturn(true).when(mMockFlags).getGaUxFeatureEnabled(); 88 doReturn(false).when(mMockFlags).getUiOtaStringsFeatureEnabled(); 89 // UiDialogFragmentEnable flag should be on for this test 90 doReturn(true).when(mMockFlags).getUiDialogFragmentEnabled(); 91 doReturn(true).when(mMockFlags).getUiDialogsFeatureEnabled(); 92 doReturn(true).when(mMockFlags).getRecordManualInteractionEnabled(); 93 List<Topic> tempList = new ArrayList<>(); 94 tempList.add(Topic.create(10001, 1, 1)); 95 tempList.add(Topic.create(10002, 1, 1)); 96 tempList.add(Topic.create(10003, 1, 1)); 97 ImmutableList<Topic> topicsList = ImmutableList.copyOf(tempList); 98 doReturn(topicsList).when(mConsentManager).getKnownTopicsWithConsent(); 99 100 tempList = new ArrayList<>(); 101 tempList.add(Topic.create(10004, 1, 1)); 102 tempList.add(Topic.create(10005, 1, 1)); 103 ImmutableList<Topic> blockedTopicsList = ImmutableList.copyOf(tempList); 104 doReturn(blockedTopicsList).when(mConsentManager).getTopicsWithRevokedConsent(); 105 106 List<App> appTempList = new ArrayList<>(); 107 appTempList.add(App.create("app1")); 108 appTempList.add(App.create("app2")); 109 ImmutableList<App> appsList = ImmutableList.copyOf(appTempList); 110 doReturn(appsList).when(mConsentManager).getKnownAppsWithConsent(); 111 112 appTempList = new ArrayList<>(); 113 appTempList.add(App.create("app3")); 114 ImmutableList<App> blockedAppsList = ImmutableList.copyOf(appTempList); 115 doReturn(blockedAppsList).when(mConsentManager).getAppsWithRevokedConsent(); 116 117 doNothing().when(mConsentManager).resetTopicsAndBlockedTopics(); 118 doNothing().when(mConsentManager).resetTopics(); 119 doNothing().when(mConsentManager).revokeConsentForTopic(any(Topic.class)); 120 doNothing().when(mConsentManager).restoreConsentForTopic(any(Topic.class)); 121 doNothing().when(mConsentManager).resetAppsAndBlockedApps(); 122 doNothing().when(mConsentManager).resetApps(); 123 doNothing().when(mConsentManager).revokeConsentForApp(any(App.class)); 124 doNothing().when(mConsentManager).restoreConsentForApp(any(App.class)); 125 doNothing().when(mConsentManager).resetMeasurement(); 126 127 ExtendedMockito.doNothing() 128 .when(() -> BackgroundJobsManager.scheduleAllBackgroundJobs(any(Context.class))); 129 ExtendedMockito.doReturn(mConsentManager).when(() -> ConsentManager.getInstance()); 130 doReturn(AdServicesApiConsent.GIVEN).when(mConsentManager).getConsent(); 131 doReturn(AdServicesApiConsent.GIVEN) 132 .when(mConsentManager) 133 .getConsent(AdServicesApiType.TOPICS); 134 doReturn(AdServicesApiConsent.GIVEN) 135 .when(mConsentManager) 136 .getConsent(AdServicesApiType.FLEDGE); 137 doReturn(AdServicesApiConsent.GIVEN) 138 .when(mConsentManager) 139 .getConsent(AdServicesApiType.MEASUREMENTS); 140 141 doNothing().when(mConsentManager).enable(any(Context.class)); 142 doNothing().when(mConsentManager).disable(any(Context.class)); 143 doReturn(GA_UX).when(mConsentManager).getUx(); 144 145 try { 146 startActivityFromHomeAndCheckMainSwitch(); 147 } catch (RemoteException e) { 148 LogUtil.e("RemoteException from setOrientation."); 149 } 150 } 151 startActivityFromHomeAndCheckMainSwitch()152 private void startActivityFromHomeAndCheckMainSwitch() throws RemoteException { 153 // Initialize UiDevice instance 154 sDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 155 156 // Start from the home screen 157 sDevice.pressHome(); 158 sDevice.setOrientationNatural(); 159 160 // Wait for launcher 161 final String launcherPackage = sDevice.getLauncherPackageName(); 162 assertThat(launcherPackage).isNotNull(); 163 sDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); 164 165 // launch app 166 Context context = appContext.get(); 167 Intent intent = new Intent(PRIVACY_SANDBOX_TEST_PACKAGE); 168 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 169 context.startActivity(intent); 170 171 // Wait for the app to appear 172 sDevice.wait( 173 Until.hasObject(By.pkg(PRIVACY_SANDBOX_TEST_PACKAGE).depth(0)), LAUNCH_TIMEOUT); 174 } 175 176 @After teardown()177 public void teardown() { 178 ApkTestUtil.takeScreenshot(sDevice, getClass().getSimpleName() + "_" + getTestName() + "_"); 179 AdservicesTestHelper.killAdservicesProcess(sContext); 180 } 181 182 @Test 183 @FlakyTest(bugId = 301779505) blockTopicDialogTest()184 public void blockTopicDialogTest() throws Exception { 185 // open topics view 186 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_ga_title); 187 UiObject2 blockTopicText = 188 ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_topic_title, 0); 189 assertThat(blockTopicText).isNotNull(); 190 191 // click block 192 blockTopicText.click(); 193 UiObject2 dialogTitle = 194 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_topic_message); 195 UiObject2 positiveText = 196 ApkTestUtil.getElement( 197 sDevice, R.string.settingsUI_dialog_block_topic_positive_text); 198 assertThat(dialogTitle).isNotNull(); 199 assertThat(positiveText).isNotNull(); 200 201 // confirm 202 positiveText.click(); 203 verify(mConsentManager, timeout(1000)).revokeConsentForTopic(any(Topic.class)); 204 blockTopicText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_topic_title, 0); 205 assertThat(blockTopicText).isNotNull(); 206 207 // click block again 208 blockTopicText.click(); 209 dialogTitle = 210 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_topic_message); 211 UiObject2 negativeText = 212 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text); 213 assertThat(dialogTitle).isNotNull(); 214 assertThat(negativeText).isNotNull(); 215 216 // cancel and verify it has still only been called once 217 negativeText.click(); 218 verify(mConsentManager).revokeConsentForTopic(any(Topic.class)); 219 } 220 221 @Test 222 @FlakyTest(bugId = 301779505) unblockTopicDialogTest()223 public void unblockTopicDialogTest() throws Exception { 224 // open topics view 225 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_ga_title); 226 227 // open blocked topics view 228 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_topics_ga_title); 229 UiObject2 unblockTopicText = 230 ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_topic_title, 0); 231 assertThat(unblockTopicText).isNotNull(); 232 233 // click unblock 234 unblockTopicText.click(); 235 UiObject2 dialogTitle = 236 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_topic_message); 237 UiObject2 positiveText = 238 ApkTestUtil.getElement( 239 sDevice, R.string.settingsUI_dialog_unblock_topic_positive_text); 240 assertThat(dialogTitle).isNotNull(); 241 assertThat(positiveText).isNotNull(); 242 243 // confirm 244 positiveText.click(); 245 verify(mConsentManager).restoreConsentForTopic(any(Topic.class)); 246 unblockTopicText = 247 ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_topic_title, 0); 248 assertThat(unblockTopicText).isNotNull(); 249 } 250 251 @Test resetTopicDialogTest()252 public void resetTopicDialogTest() throws Exception { 253 // open topics view 254 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_ga_title); 255 256 // click reset 257 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_topics_ga_title); 258 UiObject2 dialogTitle = 259 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_topic_message); 260 UiObject2 positiveText = 261 ApkTestUtil.getElement( 262 sDevice, R.string.settingsUI_dialog_reset_topic_positive_text); 263 assertThat(dialogTitle).isNotNull(); 264 assertThat(positiveText).isNotNull(); 265 266 // confirm 267 positiveText.click(); 268 verify(mConsentManager, timeout(1000)).resetTopics(); 269 270 // click reset again 271 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_topics_ga_title); 272 dialogTitle = 273 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_topic_message); 274 UiObject2 negativeText = 275 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text); 276 assertThat(dialogTitle).isNotNull(); 277 assertThat(negativeText).isNotNull(); 278 279 // cancel and verify it has still only been called once 280 negativeText.click(); 281 verify(mConsentManager).resetTopics(); 282 } 283 284 @Test 285 @FlakyTest(bugId = 301779505) blockAppDialogTest()286 public void blockAppDialogTest() throws Exception { 287 // perform a gentle swipe so scroll won't miss the text close to the 288 // bottom of the current screen. 289 UiObject2 appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_ga_title); 290 if (appsTitle == null) { 291 ApkTestUtil.gentleSwipe(sDevice); 292 } 293 294 // open apps view 295 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_ga_title); 296 UiObject2 blockAppText = 297 ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title, 0); 298 assertThat(blockAppText).isNotNull(); 299 300 // click block 301 blockAppText.click(); 302 UiObject2 dialogTitle = 303 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_message); 304 UiObject2 positiveText = 305 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_positive_text); 306 assertThat(dialogTitle).isNotNull(); 307 assertThat(positiveText).isNotNull(); 308 309 // confirm 310 positiveText.click(); 311 verify(mConsentManager, timeout(1000)).revokeConsentForApp(any(App.class)); 312 blockAppText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title, 0); 313 assertThat(blockAppText).isNotNull(); 314 315 // click block again 316 blockAppText.click(); 317 dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_message); 318 UiObject2 negativeText = 319 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text); 320 assertThat(dialogTitle).isNotNull(); 321 assertThat(negativeText).isNotNull(); 322 323 // cancel and verify it has still only been called once 324 negativeText.click(); 325 verify(mConsentManager).revokeConsentForApp(any(App.class)); 326 } 327 328 @Test 329 @FlakyTest(bugId = 301779505) unblockAppDialogTest()330 public void unblockAppDialogTest() throws Exception { 331 UiObject2 appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_ga_title); 332 if (appsTitle == null) { 333 ApkTestUtil.gentleSwipe(sDevice); 334 } 335 336 // open apps view 337 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_ga_title); 338 339 // perform a gentle swipe so scroll won't miss the text close to the 340 // bottom of the current screen. 341 ApkTestUtil.gentleSwipe(sDevice); 342 343 // open blocked apps view 344 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_apps_ga_title); 345 UiObject2 unblockAppText = 346 ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_app_title, 0); 347 assertThat(unblockAppText).isNotNull(); 348 349 // click unblock 350 unblockAppText.click(); 351 UiObject2 dialogTitle = 352 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_app_message); 353 UiObject2 positiveText = 354 ApkTestUtil.getElement( 355 sDevice, R.string.settingsUI_dialog_unblock_app_positive_text); 356 assertThat(dialogTitle).isNotNull(); 357 assertThat(positiveText).isNotNull(); 358 359 // confirm 360 positiveText.click(); 361 verify(mConsentManager).restoreConsentForApp(any(App.class)); 362 unblockAppText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_app_title, 0); 363 assertThat(unblockAppText).isNotNull(); 364 } 365 366 @Test resetAppDialogTest()367 public void resetAppDialogTest() throws Exception { 368 UiObject2 appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_ga_title); 369 if (appsTitle != null) { 370 ApkTestUtil.gentleSwipe(sDevice); 371 } 372 373 // open apps view 374 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_ga_title); 375 376 // click reset 377 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_apps_ga_title); 378 UiObject2 dialogTitle = 379 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_message); 380 UiObject2 positiveText = 381 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_positive_text); 382 assertThat(dialogTitle).isNotNull(); 383 assertThat(positiveText).isNotNull(); 384 385 // confirm 386 positiveText.click(); 387 verify(mConsentManager, timeout(1000)).resetApps(); 388 389 // click reset again 390 ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_apps_ga_title); 391 dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_message); 392 UiObject2 negativeText = 393 ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text); 394 assertThat(dialogTitle).isNotNull(); 395 assertThat(negativeText).isNotNull(); 396 397 // cancel and verify it has still only been called once 398 negativeText.click(); 399 verify(mConsentManager).resetApps(); 400 } 401 } 402