1 /* 2 * Copyright (C) 2016 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.dashboard; 18 19 import static android.content.Intent.EXTRA_USER; 20 21 import static com.android.settingslib.drawer.SwitchesProvider.EXTRA_SWITCH_SET_CHECKED_ERROR; 22 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER; 23 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE; 24 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON; 25 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI; 26 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; 27 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; 28 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI; 29 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; 30 import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL; 31 import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY; 32 33 import static com.google.common.truth.Truth.assertThat; 34 35 import static org.mockito.ArgumentMatchers.any; 36 import static org.mockito.ArgumentMatchers.anyInt; 37 import static org.mockito.ArgumentMatchers.eq; 38 import static org.mockito.Mockito.doReturn; 39 import static org.mockito.Mockito.mock; 40 import static org.mockito.Mockito.never; 41 import static org.mockito.Mockito.spy; 42 import static org.mockito.Mockito.verify; 43 import static org.mockito.Mockito.verifyZeroInteractions; 44 import static org.mockito.Mockito.when; 45 46 import android.content.Context; 47 import android.content.Intent; 48 import android.content.pm.ActivityInfo; 49 import android.content.pm.PackageManager; 50 import android.content.pm.ProviderInfo; 51 import android.content.pm.ResolveInfo; 52 import android.graphics.Bitmap; 53 import android.graphics.drawable.Drawable; 54 import android.graphics.drawable.Icon; 55 import android.os.Bundle; 56 import android.os.UserHandle; 57 import android.os.UserManager; 58 import android.util.Pair; 59 60 import androidx.fragment.app.FragmentActivity; 61 import androidx.preference.Preference; 62 import androidx.preference.SwitchPreference; 63 64 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 65 import com.android.settings.R; 66 import com.android.settings.SettingsActivity; 67 import com.android.settings.Utils; 68 import com.android.settings.testutils.FakeFeatureFactory; 69 import com.android.settings.testutils.shadow.ShadowTileUtils; 70 import com.android.settings.testutils.shadow.ShadowUserManager; 71 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 72 import com.android.settingslib.drawer.ActivityTile; 73 import com.android.settingslib.drawer.CategoryKey; 74 import com.android.settingslib.drawer.ProviderTile; 75 import com.android.settingslib.drawer.Tile; 76 import com.android.settingslib.drawer.TileUtils; 77 78 import org.junit.Before; 79 import org.junit.Test; 80 import org.junit.runner.RunWith; 81 import org.mockito.Answers; 82 import org.mockito.ArgumentCaptor; 83 import org.mockito.Mock; 84 import org.mockito.MockitoAnnotations; 85 import org.robolectric.Robolectric; 86 import org.robolectric.RobolectricTestRunner; 87 import org.robolectric.RuntimeEnvironment; 88 import org.robolectric.Shadows; 89 import org.robolectric.annotation.Config; 90 import org.robolectric.shadows.ShadowActivity; 91 import org.robolectric.util.ReflectionHelpers; 92 93 import java.util.ArrayList; 94 import java.util.List; 95 96 @RunWith(RobolectricTestRunner.class) 97 @Config(shadows = ShadowUserManager.class) 98 public class DashboardFeatureProviderImplTest { 99 100 private static final String KEY = "key"; 101 private static final String SWITCH_URI = "content://com.android.settings/tile_switch"; 102 103 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 104 private FragmentActivity mActivity; 105 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 106 private UserManager mUserManager; 107 @Mock 108 private PackageManager mPackageManager; 109 private FakeFeatureFactory mFeatureFactory; 110 111 private Context mContext; 112 private ActivityInfo mActivityInfo; 113 private ProviderInfo mProviderInfo; 114 private Bundle mSwitchMetaData; 115 private DashboardFeatureProviderImpl mImpl; 116 private boolean mForceRoundedIcon; 117 private DashboardFragment mFragment; 118 119 @Before setUp()120 public void setUp() { 121 MockitoAnnotations.initMocks(this); 122 mContext = spy(RuntimeEnvironment.application); 123 doReturn(RuntimeEnvironment.application).when(mActivity).getApplicationContext(); 124 mForceRoundedIcon = false; 125 mActivityInfo = new ActivityInfo(); 126 mActivityInfo.packageName = mContext.getPackageName(); 127 mActivityInfo.name = "class"; 128 mActivityInfo.metaData = new Bundle(); 129 mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_TITLE, R.string.settings_label); 130 mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_SUMMARY, 131 R.string.about_settings_summary); 132 133 mProviderInfo = new ProviderInfo(); 134 mProviderInfo.packageName = mContext.getPackageName(); 135 mProviderInfo.name = "provider"; 136 mProviderInfo.authority = "com.android.settings"; 137 mSwitchMetaData = new Bundle(); 138 mSwitchMetaData.putInt(META_DATA_PREFERENCE_TITLE, R.string.settings_label); 139 mSwitchMetaData.putInt(META_DATA_PREFERENCE_SUMMARY, R.string.about_settings_summary); 140 mSwitchMetaData.putString(META_DATA_PREFERENCE_KEYHINT, KEY); 141 mSwitchMetaData.putString(META_DATA_PREFERENCE_SWITCH_URI, SWITCH_URI); 142 143 doReturn(mPackageManager).when(mContext).getPackageManager(); 144 when(mPackageManager.resolveActivity(any(Intent.class), anyInt())) 145 .thenReturn(new ResolveInfo()); 146 mFeatureFactory = FakeFeatureFactory.setupForTest(); 147 mImpl = new DashboardFeatureProviderImpl(mContext); 148 mFragment = new TestFragment(); 149 } 150 151 @Test shouldHoldAppContext()152 public void shouldHoldAppContext() { 153 assertThat(mImpl.mContext).isEqualTo(mContext.getApplicationContext()); 154 } 155 156 @Test bindPreference_shouldBindAllData()157 public void bindPreference_shouldBindAllData() { 158 final Preference preference = new Preference(RuntimeEnvironment.application); 159 final Tile tile = spy(new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE)); 160 mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10); 161 doReturn(Icon.createWithBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565))) 162 .when(tile).getIcon(any(Context.class)); 163 mActivityInfo.metaData.putString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS, "HI"); 164 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 165 preference, tile, "123", Preference.DEFAULT_ORDER); 166 167 assertThat(preference.getTitle()).isEqualTo(mContext.getText(R.string.settings_label)); 168 assertThat(preference.getSummary()) 169 .isEqualTo(mContext.getText(R.string.about_settings_summary)); 170 assertThat(preference.getIcon()).isNotNull(); 171 assertThat(preference.getFragment()).isEqualTo( 172 mActivityInfo.metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS)); 173 assertThat(preference.getOrder()).isEqualTo(tile.getOrder()); 174 } 175 176 @Test bindPreference_shouldBindAllSwitchData()177 public void bindPreference_shouldBindAllSwitchData() { 178 final Preference preference = new SwitchPreference(RuntimeEnvironment.application); 179 final Tile tile = spy(new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, 180 mSwitchMetaData)); 181 mSwitchMetaData.putInt(META_DATA_KEY_ORDER, 10); 182 doReturn(Icon.createWithBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565))) 183 .when(tile).getIcon(any(Context.class)); 184 final List<DynamicDataObserver> observers = mImpl.bindPreferenceToTileAndGetObservers( 185 mActivity, mFragment, mForceRoundedIcon, preference, tile, null /* key*/, 186 Preference.DEFAULT_ORDER); 187 188 assertThat(preference.getTitle()).isEqualTo(mContext.getText(R.string.settings_label)); 189 assertThat(preference.getSummary()) 190 .isEqualTo(mContext.getText(R.string.about_settings_summary)); 191 assertThat(preference.getKey()).isEqualTo(KEY); 192 assertThat(preference.getIcon()).isNotNull(); 193 assertThat(preference.getOrder()).isEqualTo(tile.getOrder()); 194 assertThat(observers.get(0).getUri().toString()).isEqualTo(SWITCH_URI); 195 } 196 197 @Test bindPreference_noFragmentMetadata_shouldBindIntent()198 public void bindPreference_noFragmentMetadata_shouldBindIntent() { 199 final Preference preference = new Preference(RuntimeEnvironment.application); 200 mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10); 201 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 202 203 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 204 preference, tile, "123", Preference.DEFAULT_ORDER); 205 206 assertThat(preference.getFragment()).isNull(); 207 assertThat(preference.getOnPreferenceClickListener()).isNotNull(); 208 assertThat(preference.getOrder()).isEqualTo(tile.getOrder()); 209 } 210 211 @Test bindPreference_noFragmentMetadata_shouldBindToProfileSelector()212 public void bindPreference_noFragmentMetadata_shouldBindToProfileSelector() { 213 final Preference preference = new Preference(RuntimeEnvironment.application); 214 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 215 tile.userHandle = new ArrayList<>(); 216 tile.userHandle.add(mock(UserHandle.class)); 217 tile.userHandle.add(mock(UserHandle.class)); 218 219 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 220 preference, tile, "123", Preference.DEFAULT_ORDER); 221 preference.getOnPreferenceClickListener().onPreferenceClick(null); 222 223 verify(mActivity).getSupportFragmentManager(); 224 } 225 226 @Test bindPreference_noFragmentMetadataSingleUser_shouldBindToDirectLaunchIntent()227 public void bindPreference_noFragmentMetadataSingleUser_shouldBindToDirectLaunchIntent() { 228 final Preference preference = new Preference(RuntimeEnvironment.application); 229 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 230 tile.userHandle = new ArrayList<>(); 231 tile.userHandle.add(mock(UserHandle.class)); 232 233 when(mActivity.getSystemService(Context.USER_SERVICE)) 234 .thenReturn(mUserManager); 235 236 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 237 preference, tile, "123", Preference.DEFAULT_ORDER); 238 preference.getOnPreferenceClickListener().onPreferenceClick(null); 239 240 verify(mFeatureFactory.metricsFeatureProvider).logStartedIntent( 241 any(Intent.class), 242 eq(MetricsEvent.SETTINGS_GESTURES)); 243 verify(mActivity) 244 .startActivityAsUser(any(Intent.class), any(UserHandle.class)); 245 } 246 247 @Test bindPreference_toInternalSettingActivity_shouldBindToDirectLaunchIntentAndNotLog()248 public void bindPreference_toInternalSettingActivity_shouldBindToDirectLaunchIntentAndNotLog() { 249 final Preference preference = new Preference(RuntimeEnvironment.application); 250 mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName(); 251 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 252 tile.userHandle = new ArrayList<>(); 253 tile.userHandle.add(mock(UserHandle.class)); 254 255 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 256 preference, tile, "123", Preference.DEFAULT_ORDER); 257 preference.getOnPreferenceClickListener().onPreferenceClick(null); 258 verify(mFeatureFactory.metricsFeatureProvider).logStartedIntent( 259 any(Intent.class), 260 anyInt()); 261 verify(mActivity) 262 .startActivityAsUser(any(Intent.class), any(UserHandle.class)); 263 } 264 265 @Test bindPreference_nullPreference_shouldIgnore()266 public void bindPreference_nullPreference_shouldIgnore() { 267 final Tile tile = mock(Tile.class); 268 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 269 null /* keys */, tile, "123", Preference.DEFAULT_ORDER); 270 271 verifyZeroInteractions(tile); 272 } 273 274 @Test bindPreference_withNullKeyNullPriority_shouldGenerateKeyAndPriority()275 public void bindPreference_withNullKeyNullPriority_shouldGenerateKeyAndPriority() { 276 final Preference preference = new Preference(RuntimeEnvironment.application); 277 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 278 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 279 preference, tile, null /* key */, 280 Preference.DEFAULT_ORDER); 281 282 assertThat(preference.getKey()).isNotNull(); 283 assertThat(preference.getOrder()).isEqualTo(Preference.DEFAULT_ORDER); 284 } 285 286 @Test bindPreference_noSummary_shouldSetNullSummary()287 public void bindPreference_noSummary_shouldSetNullSummary() { 288 final Preference preference = new Preference(RuntimeEnvironment.application); 289 mActivityInfo.metaData.remove(META_DATA_PREFERENCE_SUMMARY); 290 291 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 292 293 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 294 preference, tile, null /* key */, Preference.DEFAULT_ORDER); 295 296 assertThat(preference.getSummary()).isNull(); 297 } 298 299 @Test 300 @Config(shadows = {ShadowTileUtils.class}) bindPreference_hasSummaryUri_shouldLoadSummaryFromContentProviderAndHaveObserver()301 public void bindPreference_hasSummaryUri_shouldLoadSummaryFromContentProviderAndHaveObserver() { 302 final Preference preference = new Preference(RuntimeEnvironment.application); 303 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 304 final String uriString = "content://com.android.settings/tile_summary"; 305 mActivityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, uriString); 306 307 final List<DynamicDataObserver> observers = mImpl.bindPreferenceToTileAndGetObservers( 308 mActivity, mFragment, mForceRoundedIcon, preference, tile, null /* key */, 309 Preference.DEFAULT_ORDER); 310 311 assertThat(preference.getSummary()).isEqualTo(ShadowTileUtils.MOCK_SUMMARY); 312 assertThat(observers.get(0).getUri().toString()).isEqualTo(uriString); 313 } 314 315 @Test 316 @Config(shadows = {ShadowTileUtils.class}) bindPreference_hasTitleUri_shouldLoadFromContentProviderAndHaveObserver()317 public void bindPreference_hasTitleUri_shouldLoadFromContentProviderAndHaveObserver() { 318 final Preference preference = new Preference(RuntimeEnvironment.application); 319 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 320 final String uriString = "content://com.android.settings/tile_title"; 321 mActivityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_TITLE_URI, uriString); 322 323 final List<DynamicDataObserver> observers = mImpl.bindPreferenceToTileAndGetObservers( 324 mActivity, mFragment, mForceRoundedIcon, preference, tile, null /* key */, 325 Preference.DEFAULT_ORDER); 326 327 assertThat(preference.getTitle()).isEqualTo(ShadowTileUtils.MOCK_SUMMARY); 328 assertThat(observers.get(0).getUri().toString()).isEqualTo(uriString); 329 } 330 331 @Test 332 @Config(shadows = {ShadowTileUtils.class}) bindPreference_onCheckedChanged_shouldPutStateToContentProvider()333 public void bindPreference_onCheckedChanged_shouldPutStateToContentProvider() { 334 final SwitchPreference preference = new SwitchPreference(RuntimeEnvironment.application); 335 final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, 336 mSwitchMetaData); 337 final Bundle bundle = new Bundle(); 338 bundle.putBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR, false); 339 ShadowTileUtils.setResultBundle(bundle); 340 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 341 preference, tile, null /* key */, Preference.DEFAULT_ORDER); 342 343 preference.callChangeListener(false); 344 345 assertThat(ShadowTileUtils.getProviderChecked()).isFalse(); 346 347 preference.callChangeListener(true); 348 349 assertThat(ShadowTileUtils.getProviderChecked()).isTrue(); 350 } 351 352 @Test 353 @Config(shadows = {ShadowTileUtils.class}) bindPreference_onCheckedChangedError_shouldRevertCheckedState()354 public void bindPreference_onCheckedChangedError_shouldRevertCheckedState() { 355 final SwitchPreference preference = new SwitchPreference(RuntimeEnvironment.application); 356 final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, 357 mSwitchMetaData); 358 final Bundle bundle = new Bundle(); 359 bundle.putBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR, true); 360 ShadowTileUtils.setResultBundle(bundle); 361 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 362 preference, tile, null /* key */, Preference.DEFAULT_ORDER); 363 364 preference.callChangeListener(true); 365 366 assertThat(preference.isChecked()).isFalse(); 367 368 preference.callChangeListener(false); 369 370 assertThat(preference.isChecked()).isTrue(); 371 } 372 373 @Test 374 @Config(shadows = {ShadowTileUtils.class}) bindPreference_callbackOnChanged_shouldLoadFromContentProvider()375 public void bindPreference_callbackOnChanged_shouldLoadFromContentProvider() { 376 final SwitchPreference preference = new SwitchPreference(RuntimeEnvironment.application); 377 final Tile tile = new ProviderTile(mProviderInfo, CategoryKey.CATEGORY_HOMEPAGE, 378 mSwitchMetaData); 379 final List<DynamicDataObserver> observers = mImpl.bindPreferenceToTileAndGetObservers( 380 mActivity, mFragment, mForceRoundedIcon, preference, tile, null /* key */, 381 Preference.DEFAULT_ORDER); 382 383 ShadowTileUtils.setProviderChecked(false); 384 observers.get(0).onDataChanged(); 385 386 assertThat(preference.isChecked()).isFalse(); 387 388 ShadowTileUtils.setProviderChecked(true); 389 observers.get(0).onDataChanged(); 390 391 assertThat(preference.isChecked()).isTrue(); 392 } 393 394 @Test bindPreference_withNullKeyTileKey_shouldUseTileKey()395 public void bindPreference_withNullKeyTileKey_shouldUseTileKey() { 396 final Preference preference = new Preference(RuntimeEnvironment.application); 397 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key"); 398 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 399 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 400 preference, tile, null /* key */, Preference.DEFAULT_ORDER); 401 402 assertThat(preference.getKey()).isEqualTo(tile.getKey(mContext)); 403 } 404 405 @Test bindIcon_withStaticIcon_shouldLoadStaticIcon()406 public void bindIcon_withStaticIcon_shouldLoadStaticIcon() { 407 final Preference preference = new Preference(RuntimeEnvironment.application); 408 mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName(); 409 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 410 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key"); 411 mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_add_40dp); 412 413 mImpl.bindIcon(preference, tile, false /* forceRoundedIcon */); 414 415 final Bitmap preferenceBmp = Utils.createIconWithDrawable(preference.getIcon()).getBitmap(); 416 final Drawable staticIcon = Icon.createWithResource(mActivityInfo.packageName, 417 R.drawable.ic_add_40dp).loadDrawable(preference.getContext()); 418 final Bitmap staticIconBmp = Utils.createIconWithDrawable(staticIcon).getBitmap(); 419 assertThat(preferenceBmp.sameAs(staticIconBmp)).isTrue(); 420 } 421 422 @Test 423 @Config(shadows = {ShadowTileUtils.class}) bindIcon_withIconUri_shouldLoadIconFromContentProvider()424 public void bindIcon_withIconUri_shouldLoadIconFromContentProvider() { 425 final Preference preference = new Preference(RuntimeEnvironment.application); 426 mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName(); 427 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 428 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key"); 429 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_ICON_URI, 430 "content://com.android.settings/tile_icon"); 431 432 mImpl.bindIcon(preference, tile, false /* forceRoundedIcon */); 433 434 assertThat(preference.getIcon()).isNotNull(); 435 } 436 437 @Test 438 @Config(shadows = {ShadowTileUtils.class}) bindIcon_withStaticIconAndIconUri_shouldLoadIconFromContentProvider()439 public void bindIcon_withStaticIconAndIconUri_shouldLoadIconFromContentProvider() { 440 final Preference preference = new Preference(RuntimeEnvironment.application); 441 mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName(); 442 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 443 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key"); 444 mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_add_40dp); 445 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_ICON_URI, 446 "content://com.android.settings/tile_icon"); 447 448 mImpl.bindIcon(preference, tile, false /* forceRoundedIcon */); 449 450 final Bitmap preferenceBmp = Utils.createIconWithDrawable(preference.getIcon()).getBitmap(); 451 final Drawable staticIcon = Icon.createWithResource(mActivityInfo.packageName, 452 R.drawable.ic_add_40dp).loadDrawable(preference.getContext()); 453 final Bitmap staticIconBmp = Utils.createIconWithDrawable(staticIcon).getBitmap(); 454 assertThat(preferenceBmp.sameAs(staticIconBmp)).isFalse(); 455 456 final Pair<String, Integer> iconInfo = TileUtils.getIconFromUri( 457 mContext, "pkg", null /* uri */, null /* providerMap */); 458 final Drawable iconFromUri = Icon.createWithResource(iconInfo.first, iconInfo.second) 459 .loadDrawable(preference.getContext()); 460 final Bitmap iconBmpFromUri = Utils.createIconWithDrawable(iconFromUri).getBitmap(); 461 assertThat(preferenceBmp.sameAs(iconBmpFromUri)).isTrue(); 462 } 463 464 @Test 465 @Config(shadows = {ShadowTileUtils.class}) bindIcon_noIcon_shouldNotLoadIcon()466 public void bindIcon_noIcon_shouldNotLoadIcon() { 467 final Preference preference = new Preference(RuntimeEnvironment.application); 468 mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName(); 469 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 470 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key"); 471 472 mImpl.bindIcon(preference, tile, false /* forceRoundedIcon */); 473 474 assertThat(preference.getIcon()).isNull(); 475 } 476 477 @Test bindPreference_withBaseOrder_shouldOffsetOrder()478 public void bindPreference_withBaseOrder_shouldOffsetOrder() { 479 final int baseOrder = 100; 480 final Preference preference = new Preference(RuntimeEnvironment.application); 481 mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10); 482 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 483 484 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 485 preference, tile, "123", baseOrder); 486 487 assertThat(preference.getOrder()).isEqualTo(tile.getOrder() + baseOrder); 488 } 489 490 @Test bindPreference_withOrderMetadata_shouldUseOrderInMetadata()491 public void bindPreference_withOrderMetadata_shouldUseOrderInMetadata() { 492 final Preference preference = new Preference(RuntimeEnvironment.application); 493 final int testOrder = -30; 494 mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, 10); 495 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 496 mActivityInfo.metaData.putInt(META_DATA_KEY_ORDER, testOrder); 497 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 498 preference, tile, "123", Preference.DEFAULT_ORDER); 499 500 assertThat(preference.getOrder()).isEqualTo(testOrder); 501 } 502 503 @Test bindPreference_invalidOrderMetadata_shouldIgnore()504 public void bindPreference_invalidOrderMetadata_shouldIgnore() { 505 final Preference preference = new Preference(RuntimeEnvironment.application); 506 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 507 mActivityInfo.metaData.putString(META_DATA_KEY_ORDER, "hello"); 508 509 mImpl.bindPreferenceToTileAndGetObservers(mActivity, mFragment, mForceRoundedIcon, 510 preference, tile, "123", Preference.DEFAULT_ORDER); 511 512 assertThat(preference.getOrder()).isEqualTo(Preference.DEFAULT_ORDER); 513 } 514 515 @Test bindPreference_withIntentActionMetadata_shouldSetLaunchAction()516 public void bindPreference_withIntentActionMetadata_shouldSetLaunchAction() { 517 FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).get(); 518 final Preference preference = new Preference(RuntimeEnvironment.application); 519 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 520 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key"); 521 mActivityInfo.metaData.putString("com.android.settings.intent.action", "TestAction"); 522 tile.userHandle = null; 523 mImpl.bindPreferenceToTileAndGetObservers(activity, mFragment, mForceRoundedIcon, 524 preference, tile, "123", Preference.DEFAULT_ORDER); 525 preference.performClick(); 526 ShadowActivity shadowActivity = Shadows.shadowOf(activity); 527 528 final Intent launchIntent = shadowActivity.getNextStartedActivityForResult().intent; 529 assertThat(launchIntent.getAction()) 530 .isEqualTo("TestAction"); 531 assertThat( 532 launchIntent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, 0)) 533 .isEqualTo(MetricsEvent.SETTINGS_GESTURES); 534 } 535 536 @Test clickPreference_withUnresolvableIntent_shouldNotLaunchAnything()537 public void clickPreference_withUnresolvableIntent_shouldNotLaunchAnything() { 538 ReflectionHelpers.setField( 539 mImpl, "mPackageManager", RuntimeEnvironment.application.getPackageManager()); 540 FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).get(); 541 final Preference preference = new Preference(RuntimeEnvironment.application); 542 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 543 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "key"); 544 mActivityInfo.metaData.putString("com.android.settings.intent.action", "TestAction"); 545 tile.userHandle = null; 546 547 mImpl.bindPreferenceToTileAndGetObservers(activity, mFragment, mForceRoundedIcon, 548 preference, tile, "123", Preference.DEFAULT_ORDER); 549 preference.performClick(); 550 551 final ShadowActivity.IntentForResult launchIntent = 552 Shadows.shadowOf(activity).getNextStartedActivityForResult(); 553 554 assertThat(launchIntent).isNull(); 555 } 556 557 @Test openTileIntent_profileSelectionDialog_shouldShow()558 public void openTileIntent_profileSelectionDialog_shouldShow() { 559 ShadowUserManager.getShadow().addUser(10, "Someone", 0); 560 561 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 562 final ArrayList<UserHandle> handles = new ArrayList<>(); 563 handles.add(new UserHandle(0)); 564 handles.add(new UserHandle(10)); 565 tile.userHandle = handles; 566 mImpl.openTileIntent(mActivity, tile); 567 568 verify(mActivity, never()) 569 .startActivity(any(Intent.class)); 570 verify(mActivity).getSupportFragmentManager(); 571 } 572 573 @Test openTileIntent_profileSelectionDialog_explicitMetadataShouldShow()574 public void openTileIntent_profileSelectionDialog_explicitMetadataShouldShow() { 575 ShadowUserManager.getShadow().addUser(10, "Someone", 0); 576 577 mActivityInfo.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_ALL); 578 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 579 final ArrayList<UserHandle> handles = new ArrayList<>(); 580 handles.add(new UserHandle(0)); 581 handles.add(new UserHandle(10)); 582 tile.userHandle = handles; 583 mImpl.openTileIntent(mActivity, tile); 584 585 verify(mActivity, never()) 586 .startActivity(any(Intent.class)); 587 verify(mActivity).getSupportFragmentManager(); 588 } 589 590 @Test openTileIntent_profileSelectionDialog_shouldNotShow()591 public void openTileIntent_profileSelectionDialog_shouldNotShow() { 592 ShadowUserManager.getShadow().addUser(10, "Someone", 0); 593 594 mActivityInfo.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_PRIMARY); 595 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 596 final ArrayList<UserHandle> handles = new ArrayList<>(); 597 handles.add(new UserHandle(0)); 598 handles.add(new UserHandle(10)); 599 tile.userHandle = handles; 600 mImpl.openTileIntent(mActivity, tile); 601 602 verify(mActivity) 603 .startActivity(any(Intent.class)); 604 verify(mActivity, never()).getSupportFragmentManager(); 605 } 606 607 @Test openTileIntent_profileSelectionDialog_validUserHandleShouldNotShow()608 public void openTileIntent_profileSelectionDialog_validUserHandleShouldNotShow() { 609 final int userId = 10; 610 ShadowUserManager.getShadow().addUser(userId, "Someone", 0); 611 612 final UserHandle userHandle = new UserHandle(userId); 613 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 614 tile.getIntent().putExtra(EXTRA_USER, userHandle); 615 final ArrayList<UserHandle> handles = new ArrayList<>(); 616 handles.add(new UserHandle(0)); 617 handles.add(userHandle); 618 tile.userHandle = handles; 619 620 mImpl.openTileIntent(mActivity, tile); 621 622 final ArgumentCaptor<UserHandle> argument = ArgumentCaptor.forClass(UserHandle.class); 623 verify(mActivity) 624 .startActivityAsUser(any(Intent.class), argument.capture()); 625 assertThat(argument.getValue().getIdentifier()).isEqualTo(userId); 626 verify(mActivity, never()).getSupportFragmentManager(); 627 } 628 629 @Test openTileIntent_profileSelectionDialog_invalidUserHandleShouldShow()630 public void openTileIntent_profileSelectionDialog_invalidUserHandleShouldShow() { 631 ShadowUserManager.getShadow().addUser(10, "Someone", 0); 632 633 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 634 tile.getIntent().putExtra(EXTRA_USER, new UserHandle(30)); 635 final ArrayList<UserHandle> handles = new ArrayList<>(); 636 handles.add(new UserHandle(0)); 637 handles.add(new UserHandle(10)); 638 tile.userHandle = handles; 639 640 mImpl.openTileIntent(mActivity, tile); 641 642 verify(mActivity, never()) 643 .startActivityAsUser(any(Intent.class), any(UserHandle.class)); 644 verify(mActivity).getSupportFragmentManager(); 645 } 646 647 @Test openTileIntent_profileSelectionDialog_unresolvableWorkProfileIntentShouldNotShow()648 public void openTileIntent_profileSelectionDialog_unresolvableWorkProfileIntentShouldNotShow() { 649 final int userId = 10; 650 ShadowUserManager.getShadow().addUser(userId, "Someone", 0); 651 final UserHandle userHandle = new UserHandle(userId); 652 final Tile tile = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE); 653 final ArrayList<UserHandle> handles = new ArrayList<>(); 654 handles.add(new UserHandle(0)); 655 handles.add(userHandle); 656 tile.userHandle = handles; 657 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), eq(0))) 658 .thenReturn(new ResolveInfo()); 659 when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), eq(userId))) 660 .thenReturn(null); 661 662 mImpl.openTileIntent(mActivity, tile); 663 664 final ArgumentCaptor<UserHandle> argument = ArgumentCaptor.forClass(UserHandle.class); 665 verify(mActivity) 666 .startActivityAsUser(any(Intent.class), argument.capture()); 667 assertThat(argument.getValue().getIdentifier()).isEqualTo(0); 668 verify(mActivity, never()).getSupportFragmentManager(); 669 } 670 671 private static class TestFragment extends DashboardFragment { 672 673 @Override getMetricsCategory()674 public int getMetricsCategory() { 675 return MetricsEvent.SETTINGS_GESTURES; 676 } 677 678 @Override getPreferenceScreenResId()679 protected int getPreferenceScreenResId() { 680 return R.xml.gestures; 681 } 682 683 @Override getLogTag()684 protected String getLogTag() { 685 return "TestFragment"; 686 } 687 } 688 } 689