1 /* 2 * Copyright (C) 2018 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.settings.homepage; 18 19 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertNotEquals; 26 import static org.junit.Assert.assertTrue; 27 import static org.mockito.ArgumentMatchers.any; 28 import static org.mockito.ArgumentMatchers.anyInt; 29 import static org.mockito.ArgumentMatchers.anyString; 30 import static org.mockito.ArgumentMatchers.eq; 31 import static org.mockito.Mockito.doReturn; 32 import static org.mockito.Mockito.mock; 33 import static org.mockito.Mockito.never; 34 import static org.mockito.Mockito.spy; 35 import static org.mockito.Mockito.verify; 36 import static org.mockito.Mockito.when; 37 38 import android.app.ActivityManager; 39 import android.content.Intent; 40 import android.content.pm.PackageManager; 41 import android.net.Uri; 42 import android.os.Build; 43 import android.os.UserHandle; 44 import android.platform.test.annotations.DisableFlags; 45 import android.platform.test.flag.junit.SetFlagsRule; 46 import android.provider.Settings; 47 import android.util.ArraySet; 48 import android.view.View; 49 import android.view.Window; 50 import android.view.WindowManager; 51 import android.widget.FrameLayout; 52 53 import androidx.fragment.app.Fragment; 54 import androidx.test.core.app.ApplicationProvider; 55 56 import com.android.settings.R; 57 import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl; 58 import com.android.settings.flags.Flags; 59 import com.android.settings.testutils.shadow.ShadowActivityEmbeddingUtils; 60 import com.android.settings.testutils.shadow.ShadowPasswordUtils; 61 import com.android.settings.testutils.shadow.ShadowUserManager; 62 import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin; 63 64 import org.junit.After; 65 import org.junit.Before; 66 import org.junit.Rule; 67 import org.junit.Test; 68 import org.junit.runner.RunWith; 69 import org.mockito.ArgumentCaptor; 70 import org.mockito.junit.MockitoJUnit; 71 import org.mockito.junit.MockitoRule; 72 import org.robolectric.Robolectric; 73 import org.robolectric.RobolectricTestRunner; 74 import org.robolectric.android.controller.ActivityController; 75 import org.robolectric.annotation.Config; 76 import org.robolectric.annotation.Implementation; 77 import org.robolectric.annotation.Implements; 78 import org.robolectric.shadow.api.Shadow; 79 import org.robolectric.shadows.ShadowActivityManager; 80 import org.robolectric.util.ReflectionHelpers; 81 82 import java.util.Set; 83 84 @RunWith(RobolectricTestRunner.class) 85 @Config(shadows = { 86 ShadowUserManager.class, 87 SettingsHomepageActivityTest.ShadowSuggestionFeatureProviderImpl.class, 88 ShadowActivityManager.class, 89 }) 90 public class SettingsHomepageActivityTest { 91 @Rule 92 public final MockitoRule mMockitoRule = MockitoJUnit.rule(); 93 @Rule 94 public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 95 96 @Before setup()97 public void setup() { 98 Settings.Global.putInt(ApplicationProvider.getApplicationContext().getContentResolver(), 99 Settings.Global.DEVICE_PROVISIONED, 1); 100 } 101 102 @After tearDown()103 public void tearDown() { 104 ShadowPasswordUtils.reset(); 105 } 106 107 @Test launch_deviceUnprovisioned_finish()108 public void launch_deviceUnprovisioned_finish() { 109 Settings.Global.putInt(ApplicationProvider.getApplicationContext().getContentResolver(), 110 Settings.Global.DEVICE_PROVISIONED, 0); 111 112 SettingsHomepageActivity activity = Robolectric.buildActivity( 113 SettingsHomepageActivity.class).create().get(); 114 115 assertThat(activity.isFinishing()).isTrue(); 116 } 117 118 @Test launch_shouldHaveAnimationForIaFragment()119 public void launch_shouldHaveAnimationForIaFragment() { 120 final SettingsHomepageActivity activity = Robolectric.buildActivity( 121 SettingsHomepageActivity.class).create().get(); 122 final FrameLayout frameLayout = activity.findViewById(R.id.main_content); 123 124 assertThat(frameLayout.getLayoutTransition()).isNotNull(); 125 } 126 127 @Test 128 @DisableFlags(Flags.FLAG_HOMEPAGE_REVAMP) launch_configDisabled_shouldHideAvatar()129 public void launch_configDisabled_shouldHideAvatar() { 130 final SettingsHomepageActivity activity = Robolectric.buildActivity( 131 SettingsHomepageActivity.class).create().get(); 132 133 final View avatarView = activity.findViewById(R.id.account_avatar); 134 assertThat(avatarView.getVisibility()).isNotEqualTo(View.VISIBLE); 135 } 136 137 @Test 138 @Config(qualifiers = "mcc999") 139 @DisableFlags(Flags.FLAG_HOMEPAGE_REVAMP) launch_configEnabled_shouldShowAvatar()140 public void launch_configEnabled_shouldShowAvatar() { 141 final SettingsHomepageActivity activity = Robolectric.buildActivity( 142 SettingsHomepageActivity.class).create().get(); 143 144 final View avatarView = activity.findViewById(R.id.account_avatar); 145 assertThat(avatarView.getVisibility()).isEqualTo(View.VISIBLE); 146 } 147 148 @Test 149 @Config(qualifiers = "mcc999") 150 @DisableFlags(Flags.FLAG_HOMEPAGE_REVAMP) launch_LowRamDevice_shouldHideAvatar()151 public void launch_LowRamDevice_shouldHideAvatar() { 152 final ShadowActivityManager activityManager = Shadow.extract( 153 ApplicationProvider.getApplicationContext().getSystemService( 154 ActivityManager.class)); 155 activityManager.setIsLowRamDevice(true); 156 157 final SettingsHomepageActivity activity = Robolectric.buildActivity( 158 SettingsHomepageActivity.class).create().get(); 159 160 final View avatarView = activity.findViewById(R.id.account_avatar); 161 assertThat(avatarView.getVisibility()).isNotEqualTo(View.VISIBLE); 162 } 163 164 @Test showHomepageWithSuggestion_showSuggestion()165 public void showHomepageWithSuggestion_showSuggestion() { 166 final SettingsHomepageActivity activity = Robolectric.buildActivity( 167 SettingsHomepageActivity.class).create().get(); 168 final View viewRoot = activity.findViewById(R.id.settings_homepage_container); 169 final View suggestionTile = activity.findViewById(R.id.suggestion_content); 170 171 activity.showHomepageWithSuggestion(true); 172 173 assertThat(viewRoot.getVisibility()).isEqualTo(View.VISIBLE); 174 assertThat(suggestionTile.getVisibility()).isEqualTo(View.VISIBLE); 175 } 176 177 @Test showHomepageWithSuggestion_hideSuggestion()178 public void showHomepageWithSuggestion_hideSuggestion() { 179 final SettingsHomepageActivity activity = Robolectric.buildActivity( 180 SettingsHomepageActivity.class).create().get(); 181 final View viewRoot = activity.findViewById(R.id.settings_homepage_container); 182 final View suggestionTile = activity.findViewById(R.id.suggestion_content); 183 184 activity.showHomepageWithSuggestion(false); 185 186 assertThat(viewRoot.getVisibility()).isEqualTo(View.VISIBLE); 187 assertThat(suggestionTile.getVisibility()).isEqualTo(View.GONE); 188 } 189 190 @Test showHomepageWithSuggestion_callTwice_shouldKeepPreviousVisibility()191 public void showHomepageWithSuggestion_callTwice_shouldKeepPreviousVisibility() { 192 final SettingsHomepageActivity activity = Robolectric.buildActivity( 193 SettingsHomepageActivity.class).create().get(); 194 final View suggestionTile = activity.findViewById(R.id.suggestion_content); 195 196 activity.showHomepageWithSuggestion(false); 197 activity.showHomepageWithSuggestion(true); 198 199 assertThat(suggestionTile.getVisibility()).isEqualTo(View.GONE); 200 } 201 202 @Test showHomepageWithSuggestion_callAfterOnStop_shouldUpdateVisibility()203 public void showHomepageWithSuggestion_callAfterOnStop_shouldUpdateVisibility() { 204 final SettingsHomepageActivity activity = Robolectric.buildActivity( 205 SettingsHomepageActivity.class).create().get(); 206 final View suggestionTile = activity.findViewById(R.id.suggestion_content); 207 208 activity.showHomepageWithSuggestion(true); 209 activity.onStop(); 210 activity.showHomepageWithSuggestion(false); 211 212 assertThat(suggestionTile.getVisibility()).isEqualTo(View.GONE); 213 } 214 215 @Test onStart_isNotDebuggable_shouldHideSystemOverlay()216 public void onStart_isNotDebuggable_shouldHideSystemOverlay() { 217 ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false); 218 219 final ActivityController<SettingsHomepageActivity> activityController = 220 Robolectric.buildActivity(SettingsHomepageActivity.class).create(); 221 final SettingsHomepageActivity activity = spy(activityController.get()); 222 final Window window = mock(Window.class); 223 when(activity.getWindow()).thenReturn(window); 224 activity.getLifecycle().addObserver(new HideNonSystemOverlayMixin(activity)); 225 226 activityController.start(); 227 228 verify(window).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 229 } 230 231 @Test onStop_isNotDebuggable_shouldRemoveHideSystemOverlay()232 public void onStop_isNotDebuggable_shouldRemoveHideSystemOverlay() { 233 ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", false); 234 235 final ActivityController<SettingsHomepageActivity> activityController = 236 Robolectric.buildActivity(SettingsHomepageActivity.class).create(); 237 final SettingsHomepageActivity activity = spy(activityController.get()); 238 final Window window = mock(Window.class); 239 when(activity.getWindow()).thenReturn(window); 240 activity.getLifecycle().addObserver(new HideNonSystemOverlayMixin(activity)); 241 242 activityController.start(); 243 244 verify(window).addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 245 246 final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); 247 when(window.getAttributes()).thenReturn(layoutParams); 248 249 activityController.stop(); 250 final ArgumentCaptor<WindowManager.LayoutParams> paramCaptor = ArgumentCaptor.forClass( 251 WindowManager.LayoutParams.class); 252 253 verify(window).setAttributes(paramCaptor.capture()); 254 assertThat(paramCaptor.getValue().privateFlags 255 & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS).isEqualTo(0); 256 } 257 258 @Test onCreate_TaskRoot_shouldNotFinish()259 public void onCreate_TaskRoot_shouldNotFinish() { 260 SettingsHomepageActivity activity = 261 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 262 doReturn(true).when(activity).isTaskRoot(); 263 264 activity.onCreate(/* savedInstanceState= */ null); 265 266 verify(activity, never()).finish(); 267 } 268 269 @Test onCreate_notTaskRoot_shouldRestartActivity()270 public void onCreate_notTaskRoot_shouldRestartActivity() { 271 SettingsHomepageActivity activity = 272 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 273 doReturn(false).when(activity).isTaskRoot(); 274 275 activity.onCreate(/* savedInstanceState= */ null); 276 277 verify(activity).finish(); 278 verify(activity).startActivity(any(Intent.class)); 279 } 280 281 @Test onCreate_notTaskRoot_flagNewTask_shouldOnlyFinish()282 public void onCreate_notTaskRoot_flagNewTask_shouldOnlyFinish() { 283 SettingsHomepageActivity activity = 284 spy(Robolectric.buildActivity(SettingsHomepageActivity.class, 285 new Intent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)).get()); 286 doReturn(false).when(activity).isTaskRoot(); 287 288 activity.onCreate(/* savedInstanceState= */ null); 289 290 verify(activity).finish(); 291 verify(activity, never()).startActivity(any(Intent.class)); 292 } 293 294 @Test 295 @Config(shadows = ShadowActivityEmbeddingUtils.class) onCreate_eligibleProfile_shouldNotRestartActivity()296 public void onCreate_eligibleProfile_shouldNotRestartActivity() { 297 ShadowActivityEmbeddingUtils.setIsEmbeddingActivityEnabled(true); 298 SettingsHomepageActivity activity = 299 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 300 doReturn(0).when(activity).getUserId(); 301 doReturn(true).when(activity).isTaskRoot(); 302 303 activity.onCreate(/* savedInstanceState= */ null); 304 305 verify(activity, never()).finish(); 306 verify(activity, never()).startActivityAsUser(any(Intent.class), any(UserHandle.class)); 307 } 308 309 @Test 310 @Config(shadows = ShadowActivityEmbeddingUtils.class) onCreate_managedProfile_shouldRestartActivity()311 public void onCreate_managedProfile_shouldRestartActivity() { 312 ShadowActivityEmbeddingUtils.setIsEmbeddingActivityEnabled(true); 313 SettingsHomepageActivity activity = 314 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 315 final Set<Integer> profileIds = new ArraySet<>(); 316 profileIds.add(10); 317 ShadowUserManager.getShadow().setManagedProfiles(profileIds); 318 doReturn(10).when(activity).getUserId(); 319 doReturn(true).when(activity).isTaskRoot(); 320 321 activity.onCreate(/* savedInstanceState= */ null); 322 323 verify(activity).finish(); 324 verify(activity).startActivityAsUser(any(Intent.class), any(UserHandle.class)); 325 } 326 327 @Test 328 @Config(shadows = ShadowActivityEmbeddingUtils.class) onCreate_privateProfile_shouldRestartActivity()329 public void onCreate_privateProfile_shouldRestartActivity() { 330 ShadowActivityEmbeddingUtils.setIsEmbeddingActivityEnabled(true); 331 SettingsHomepageActivity activity = 332 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 333 ShadowUserManager.getShadow().setPrivateProfile(11, "private", 0); 334 doReturn(11).when(activity).getUserId(); 335 doReturn(true).when(activity).isTaskRoot(); 336 337 activity.onCreate(/* savedInstanceState= */ null); 338 339 verify(activity).finish(); 340 verify(activity).startActivityAsUser(any(Intent.class), any(UserHandle.class)); 341 } 342 343 /** This test is for large screen devices Activity embedding. */ 344 @Test 345 @Config(shadows = ShadowActivityEmbeddingUtils.class) onCreate_flagClearTop_shouldInitRules()346 public void onCreate_flagClearTop_shouldInitRules() { 347 ShadowActivityEmbeddingUtils.setIsEmbeddingActivityEnabled(true); 348 SettingsHomepageActivity activity = 349 spy(Robolectric.buildActivity(SettingsHomepageActivity.class, 350 new Intent().setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)).get()); 351 352 activity.onCreate(/* savedInstanceState= */ null); 353 354 verify(activity).initSplitPairRules(); 355 } 356 357 @Test getInitialReferrer_differentPackage_returnCurrentReferrer()358 public void getInitialReferrer_differentPackage_returnCurrentReferrer() { 359 SettingsHomepageActivity activity = 360 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 361 String referrer = "com.abc"; 362 doReturn(referrer).when(activity).getCurrentReferrer(); 363 364 assertEquals(activity.getInitialReferrer(), referrer); 365 } 366 367 @Test getInitialReferrer_noReferrerExtra_returnCurrentReferrer()368 public void getInitialReferrer_noReferrerExtra_returnCurrentReferrer() { 369 SettingsHomepageActivity activity = 370 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 371 String referrer = activity.getPackageName(); 372 doReturn(referrer).when(activity).getCurrentReferrer(); 373 374 assertEquals(activity.getInitialReferrer(), referrer); 375 } 376 377 @Test getInitialReferrer_hasReferrerExtra_returnGivenReferrer()378 public void getInitialReferrer_hasReferrerExtra_returnGivenReferrer() { 379 String referrer = "com.abc"; 380 SettingsHomepageActivity activity = 381 spy(Robolectric.buildActivity(SettingsHomepageActivity.class, 382 new Intent().putExtra(SettingsHomepageActivity.EXTRA_INITIAL_REFERRER, 383 referrer)).get()); 384 doReturn(activity.getPackageName()).when(activity).getCurrentReferrer(); 385 386 assertEquals(activity.getInitialReferrer(), referrer); 387 } 388 389 @Test getCurrentReferrer_hasReferrerExtra_shouldNotEqual()390 public void getCurrentReferrer_hasReferrerExtra_shouldNotEqual() { 391 String referrer = "com.abc"; 392 Uri uri = new Uri.Builder().scheme("android-app").authority(referrer).build(); 393 SettingsHomepageActivity activity = 394 spy(Robolectric.buildActivity(SettingsHomepageActivity.class, 395 new Intent().putExtra(Intent.EXTRA_REFERRER, uri)).get()); 396 397 assertNotEquals(activity.getCurrentReferrer(), referrer); 398 } 399 400 @Test getCurrentReferrer_hasReferrerNameExtra_shouldNotEqual()401 public void getCurrentReferrer_hasReferrerNameExtra_shouldNotEqual() { 402 String referrer = "com.abc"; 403 SettingsHomepageActivity activity = 404 spy(Robolectric.buildActivity(SettingsHomepageActivity.class, 405 new Intent().putExtra(Intent.EXTRA_REFERRER_NAME, referrer)).get()); 406 407 assertNotEquals(activity.getCurrentReferrer(), referrer); 408 } 409 410 @Test isCallingAppPermitted_emptyPermission_returnTrue()411 public void isCallingAppPermitted_emptyPermission_returnTrue() { 412 SettingsHomepageActivity activity = 413 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 414 doReturn(PackageManager.PERMISSION_DENIED).when(activity) 415 .checkPermission(anyString(), anyInt(), anyInt()); 416 417 assertTrue(activity.isCallingAppPermitted("", 1000)); 418 } 419 420 @Test isCallingAppPermitted_notGrantedPermission_returnFalse()421 public void isCallingAppPermitted_notGrantedPermission_returnFalse() { 422 SettingsHomepageActivity activity = 423 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 424 doReturn(PackageManager.PERMISSION_DENIED).when(activity) 425 .checkPermission(anyString(), anyInt(), anyInt()); 426 427 assertFalse(activity.isCallingAppPermitted("android.permission.TEST", 1000)); 428 } 429 430 @Test isCallingAppPermitted_grantedPermission_returnTrue()431 public void isCallingAppPermitted_grantedPermission_returnTrue() { 432 SettingsHomepageActivity activity = 433 spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get()); 434 String permission = "android.permission.TEST"; 435 doReturn(PackageManager.PERMISSION_DENIED).when(activity) 436 .checkPermission(anyString(), anyInt(), anyInt()); 437 doReturn(PackageManager.PERMISSION_GRANTED).when(activity) 438 .checkPermission(eq(permission), anyInt(), eq(1000)); 439 440 assertTrue(activity.isCallingAppPermitted(permission, 1000)); 441 } 442 443 @Implements(SuggestionFeatureProviderImpl.class) 444 public static class ShadowSuggestionFeatureProviderImpl { 445 446 @Implementation getContextualSuggestionFragment()447 public Class<? extends Fragment> getContextualSuggestionFragment() { 448 return Fragment.class; 449 } 450 } 451 } 452