Home | History | Annotate | Download | only in dashboard
      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 com.google.common.truth.Truth.assertThat;
     20 import static org.mockito.Matchers.any;
     21 import static org.mockito.Matchers.anyInt;
     22 import static org.mockito.Matchers.eq;
     23 import static org.mockito.Mockito.doReturn;
     24 import static org.mockito.Mockito.mock;
     25 import static org.mockito.Mockito.spy;
     26 import static org.mockito.Mockito.verify;
     27 import static org.mockito.Mockito.verifyZeroInteractions;
     28 import static org.mockito.Mockito.when;
     29 import static org.robolectric.Shadows.shadowOf;
     30 
     31 import android.app.Activity;
     32 import android.content.ComponentName;
     33 import android.content.Context;
     34 import android.content.Intent;
     35 import android.content.pm.PackageManager;
     36 import android.content.pm.ResolveInfo;
     37 import android.graphics.Bitmap;
     38 import android.graphics.drawable.Icon;
     39 import android.os.Bundle;
     40 import android.os.UserHandle;
     41 import android.os.UserManager;
     42 import android.support.v7.preference.Preference;
     43 
     44 import com.android.internal.logging.nano.MetricsProto;
     45 import com.android.settings.R;
     46 import com.android.settings.SettingsActivity;
     47 import com.android.settings.testutils.FakeFeatureFactory;
     48 import com.android.settings.testutils.SettingsRobolectricTestRunner;
     49 import com.android.settings.testutils.shadow.ShadowThreadUtils;
     50 import com.android.settings.testutils.shadow.ShadowTileUtils;
     51 import com.android.settings.testutils.shadow.ShadowUserManager;
     52 import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
     53 import com.android.settingslib.drawer.CategoryKey;
     54 import com.android.settingslib.drawer.CategoryManager;
     55 import com.android.settingslib.drawer.DashboardCategory;
     56 import com.android.settingslib.drawer.Tile;
     57 import com.android.settingslib.drawer.TileUtils;
     58 
     59 import org.junit.Before;
     60 import org.junit.Test;
     61 import org.junit.runner.RunWith;
     62 import org.mockito.Answers;
     63 import org.mockito.Mock;
     64 import org.mockito.MockitoAnnotations;
     65 import org.robolectric.Robolectric;
     66 import org.robolectric.RuntimeEnvironment;
     67 import org.robolectric.annotation.Config;
     68 import org.robolectric.shadows.ShadowActivity;
     69 import org.robolectric.shadows.ShadowApplication;
     70 import org.robolectric.util.ReflectionHelpers;
     71 
     72 import java.util.ArrayList;
     73 
     74 @RunWith(SettingsRobolectricTestRunner.class)
     75 @Config(shadows = ShadowUserManager.class)
     76 public class DashboardFeatureProviderImplTest {
     77 
     78     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     79     private Activity mActivity;
     80     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     81     private UserManager mUserManager;
     82     @Mock
     83     private CategoryManager mCategoryManager;
     84     @Mock
     85     private PackageManager mPackageManager;
     86     private FakeFeatureFactory mFeatureFactory;
     87 
     88     private Context mContext;
     89     private DashboardFeatureProviderImpl mImpl;
     90 
     91     @Before
     92     public void setUp() {
     93         MockitoAnnotations.initMocks(this);
     94         mContext = spy(RuntimeEnvironment.application);
     95         doReturn(mPackageManager).when(mContext).getPackageManager();
     96         when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
     97             .thenReturn(new ResolveInfo());
     98         mFeatureFactory = FakeFeatureFactory.setupForTest();
     99         mImpl = new DashboardFeatureProviderImpl(mContext);
    100     }
    101 
    102     @Test
    103     public void shouldHoldAppContext() {
    104         assertThat(mImpl.mContext).isEqualTo(mContext.getApplicationContext());
    105     }
    106 
    107     @Test
    108     public void bindPreference_shouldBindAllData() {
    109         final Preference preference = new Preference(RuntimeEnvironment.application);
    110         final Tile tile = new Tile();
    111         tile.title = "title";
    112         tile.summary = "summary";
    113         tile.icon = Icon.createWithBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565));
    114         tile.metaData = new Bundle();
    115         tile.metaData.putString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS, "HI");
    116         tile.priority = 10;
    117         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
    118                 preference, tile, "123", Preference.DEFAULT_ORDER);
    119 
    120         assertThat(preference.getTitle()).isEqualTo(tile.title);
    121         assertThat(preference.getSummary()).isEqualTo(tile.summary);
    122         assertThat(preference.getIcon()).isNotNull();
    123         assertThat(preference.getFragment())
    124                 .isEqualTo(tile.metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS));
    125         assertThat(preference.getOrder()).isEqualTo(-tile.priority);
    126     }
    127 
    128     @Test
    129     public void bindPreference_noFragmentMetadata_shouldBindIntent() {
    130         final Preference preference = new Preference(RuntimeEnvironment.application);
    131         final Tile tile = new Tile();
    132         tile.metaData = new Bundle();
    133         tile.priority = 10;
    134         tile.intent = new Intent();
    135         tile.intent.setComponent(new ComponentName("pkg", "class"));
    136 
    137         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
    138                 preference, tile, "123", Preference.DEFAULT_ORDER);
    139 
    140         assertThat(preference.getFragment()).isNull();
    141         assertThat(preference.getOnPreferenceClickListener()).isNotNull();
    142         assertThat(preference.getOrder()).isEqualTo(-tile.priority);
    143     }
    144 
    145     @Test
    146     public void bindPreference_noFragmentMetadata_shouldBindToProfileSelector() {
    147         final Preference preference = new Preference(RuntimeEnvironment.application);
    148         final Tile tile = new Tile();
    149         tile.metaData = new Bundle();
    150         tile.userHandle = new ArrayList<>();
    151         tile.userHandle.add(mock(UserHandle.class));
    152         tile.userHandle.add(mock(UserHandle.class));
    153         tile.intent = new Intent();
    154         tile.intent.setComponent(new ComponentName("pkg", "class"));
    155 
    156         when(mActivity.getApplicationContext().getSystemService(Context.USER_SERVICE))
    157                 .thenReturn(mUserManager);
    158 
    159         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
    160                 preference, tile, "123", Preference.DEFAULT_ORDER);
    161         preference.getOnPreferenceClickListener().onPreferenceClick(null);
    162 
    163         verify(mActivity).getFragmentManager();
    164     }
    165 
    166     @Test
    167     public void bindPreference_noFragmentMetadataSingleUser_shouldBindToDirectLaunchIntent() {
    168         final Preference preference = new Preference(RuntimeEnvironment.application);
    169         final Tile tile = new Tile();
    170         tile.metaData = new Bundle();
    171         tile.userHandle = new ArrayList<>();
    172         tile.userHandle.add(mock(UserHandle.class));
    173         tile.intent = new Intent();
    174         tile.intent.setComponent(new ComponentName("pkg", "class"));
    175 
    176         when(mActivity.getSystemService(Context.USER_SERVICE))
    177                 .thenReturn(mUserManager);
    178 
    179         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
    180                 preference, tile, "123", Preference.DEFAULT_ORDER);
    181         preference.getOnPreferenceClickListener().onPreferenceClick(null);
    182 
    183         verify(mFeatureFactory.metricsFeatureProvider).logDashboardStartIntent(
    184                 any(Context.class),
    185                 any(Intent.class),
    186                 eq(MetricsProto.MetricsEvent.SETTINGS_GESTURES));
    187         verify(mActivity)
    188                 .startActivityForResultAsUser(any(Intent.class), anyInt(), any(UserHandle.class));
    189     }
    190 
    191     @Test
    192     public void bindPreference_toInternalSettingActivity_shouldBindToDirectLaunchIntentAndNotLog() {
    193         final Preference preference = new Preference(RuntimeEnvironment.application);
    194         final Tile tile = new Tile();
    195         tile.metaData = new Bundle();
    196         tile.userHandle = new ArrayList<>();
    197         tile.userHandle.add(mock(UserHandle.class));
    198         tile.intent = new Intent();
    199         tile.intent.setComponent(
    200                 new ComponentName(RuntimeEnvironment.application.getPackageName(), "class"));
    201 
    202         when(mActivity.getSystemService(Context.USER_SERVICE))
    203                 .thenReturn(mUserManager);
    204         when(mActivity.getApplicationContext().getPackageName())
    205                 .thenReturn(RuntimeEnvironment.application.getPackageName());
    206 
    207         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
    208                 preference, tile, "123", Preference.DEFAULT_ORDER);
    209         preference.getOnPreferenceClickListener().onPreferenceClick(null);
    210         verify(mFeatureFactory.metricsFeatureProvider).logDashboardStartIntent(
    211                 any(Context.class),
    212                 any(Intent.class),
    213                 anyInt());
    214         verify(mActivity)
    215                 .startActivityForResultAsUser(any(Intent.class), anyInt(), any(UserHandle.class));
    216     }
    217 
    218     @Test
    219     public void bindPreference_nullPreference_shouldIgnore() {
    220         final Tile tile = mock(Tile.class);
    221         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
    222                 null, tile, "123", Preference.DEFAULT_ORDER);
    223 
    224         verifyZeroInteractions(tile);
    225     }
    226 
    227     @Test
    228     public void bindPreference_withNullKeyNullPriority_shouldGenerateKeyAndPriority() {
    229         final Preference preference = new Preference(RuntimeEnvironment.application);
    230         final Tile tile = new Tile();
    231         tile.intent = new Intent();
    232         tile.intent.setComponent(new ComponentName("pkg", "class"));
    233         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
    234                 preference, tile, null /*key */, Preference.DEFAULT_ORDER);
    235 
    236         assertThat(preference.getKey()).isNotNull();
    237         assertThat(preference.getOrder()).isEqualTo(Preference.DEFAULT_ORDER);
    238     }
    239 
    240     @Test
    241     public void bindPreference_noSummary_shouldSetSummaryToPlaceholder() {
    242         final Preference preference = new Preference(RuntimeEnvironment.application);
    243         final Tile tile = new Tile();
    244         tile.intent = new Intent();
    245         tile.intent.setComponent(new ComponentName("pkg", "class"));
    246         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
    247                 preference, tile, null /*key */, Preference.DEFAULT_ORDER);
    248 
    249         assertThat(preference.getSummary())
    250                 .isEqualTo(RuntimeEnvironment.application.getString(R.string.summary_placeholder));
    251     }
    252 
    253     @Test
    254     public void bindPreference_hasSummary_shouldSetSummary() {
    255         final Preference preference = new Preference(RuntimeEnvironment.application);
    256         final Tile tile = new Tile();
    257         tile.summary = "test";
    258         tile.intent = new Intent();
    259         tile.intent.setComponent(new ComponentName("pkg", "class"));
    260         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
    261                 preference, tile, null /*key */, Preference.DEFAULT_ORDER);
    262 
    263         assertThat(preference.getSummary()).isEqualTo(tile.summary);
    264     }
    265 
    266     @Test
    267     @Config(shadows = {ShadowTileUtils.class, ShadowThreadUtils.class})
    268     public void bindPreference_hasSummaryUri_shouldLoadSummaryFromContentProvider() {
    269         final Preference preference = new Preference(RuntimeEnvironment.application);
    270         final Tile tile = new Tile();
    271         tile.intent = new Intent();
    272         tile.intent.setComponent(new ComponentName("pkg", "class"));
    273         tile.metaData = new Bundle();
    274         tile.metaData.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI,
    275                 "content://com.android.settings/tile_summary");
    276 
    277         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
    278                 preference, tile, null /*key */, Preference.DEFAULT_ORDER);
    279 
    280         assertThat(preference.getSummary()).isEqualTo(ShadowTileUtils.MOCK_SUMMARY);
    281     }
    282 
    283     @Test
    284     public void bindPreference_withNullKeyTileKey_shouldUseTileKey() {
    285         final Preference preference = new Preference(RuntimeEnvironment.application);
    286         final Tile tile = new Tile();
    287         tile.key = "key";
    288         tile.intent = new Intent();
    289         tile.intent.setComponent(new ComponentName("pkg", "class"));
    290         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
    291                 preference, tile, null /* key */, Preference.DEFAULT_ORDER);
    292 
    293         assertThat(preference.getKey()).isEqualTo(tile.key);
    294     }
    295 
    296     @Test
    297     @Config(shadows = {ShadowTileUtils.class, ShadowThreadUtils.class})
    298     public void bindPreference_withIconUri_shouldLoadIconFromContentProvider() {
    299         final Preference preference = new Preference(RuntimeEnvironment.application);
    300         final Tile tile = new Tile();
    301         tile.key = "key";
    302         tile.intent = new Intent();
    303         tile.intent.setComponent(
    304                 new ComponentName(RuntimeEnvironment.application.getPackageName(), "class"));
    305         tile.metaData = new Bundle();
    306         tile.metaData.putString(TileUtils.META_DATA_PREFERENCE_ICON_URI,
    307                 "content://com.android.settings/tile_icon");
    308         mImpl.bindIcon(preference, tile);
    309 
    310         assertThat(preference.getIcon()).isNotNull();
    311     }
    312 
    313     @Test
    314     public void bindPreference_withBaseOrder_shouldOffsetPriority() {
    315         final int baseOrder = 100;
    316         final Preference preference = new Preference(RuntimeEnvironment.application);
    317         final Tile tile = new Tile();
    318         tile.metaData = new Bundle();
    319         tile.priority = 10;
    320         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
    321                 preference, tile, "123", baseOrder);
    322 
    323         assertThat(preference.getOrder()).isEqualTo(-tile.priority + baseOrder);
    324     }
    325 
    326     @Test
    327     public void bindPreference_withOrderMetadata_shouldUseOrderInMetadata() {
    328         final Preference preference = new Preference(RuntimeEnvironment.application);
    329         final int testOrder = -30;
    330         final Tile tile = new Tile();
    331         tile.metaData = new Bundle();
    332         tile.metaData.putInt(mImpl.META_DATA_KEY_ORDER, testOrder);
    333         tile.priority = 10;
    334         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
    335                 preference, tile, "123", Preference.DEFAULT_ORDER);
    336 
    337         assertThat(preference.getOrder()).isEqualTo(testOrder);
    338     }
    339 
    340     @Test
    341     public void bindPreference_invalidOrderMetadata_shouldIgnore() {
    342         final Preference preference = new Preference(RuntimeEnvironment.application);
    343         final Tile tile = new Tile();
    344         tile.metaData = new Bundle();
    345         tile.metaData.putString(mImpl.META_DATA_KEY_ORDER, "hello");
    346         tile.priority = 10;
    347         mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.VIEW_UNKNOWN,
    348                 preference, tile, "123", Preference.DEFAULT_ORDER);
    349 
    350         assertThat(preference.getOrder()).isEqualTo(-tile.priority);
    351     }
    352 
    353     @Test
    354     public void bindPreference_withIntentActionMetadata_shouldSetLaunchAction() {
    355         Activity activity = Robolectric.buildActivity(Activity.class).get();
    356         final Preference preference = new Preference(RuntimeEnvironment.application);
    357         final Tile tile = new Tile();
    358         tile.key = "key";
    359         tile.intent = new Intent();
    360         tile.intent.setComponent(new ComponentName("pkg", "class"));
    361         tile.metaData = new Bundle();
    362         tile.metaData.putString("com.android.settings.intent.action", "TestAction");
    363         tile.userHandle = null;
    364         mImpl.bindPreferenceToTile(activity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
    365                 preference, tile, "123", Preference.DEFAULT_ORDER);
    366         preference.performClick();
    367         ShadowActivity shadowActivity = shadowOf(activity);
    368 
    369         final Intent launchIntent = shadowActivity.getNextStartedActivityForResult().intent;
    370         assertThat(launchIntent.getAction())
    371                 .isEqualTo("TestAction");
    372         assertThat(launchIntent.getIntExtra(VisibilityLoggerMixin.EXTRA_SOURCE_METRICS_CATEGORY, 0))
    373                 .isEqualTo(MetricsProto.MetricsEvent.SETTINGS_GESTURES);
    374     }
    375 
    376     @Test
    377     public void clickPreference_withUnresolvableIntent_shouldNotLaunchAnything() {
    378         ReflectionHelpers.setField(
    379                 mImpl, "mPackageManager", RuntimeEnvironment.application.getPackageManager());
    380         Activity activity = Robolectric.buildActivity(Activity.class).get();
    381         final ShadowApplication application = ShadowApplication.getInstance();
    382         final Preference preference = new Preference(application.getApplicationContext());
    383         final Tile tile = new Tile();
    384         tile.key = "key";
    385         tile.intent = new Intent();
    386         tile.intent.setComponent(new ComponentName("pkg", "class"));
    387         tile.metaData = new Bundle();
    388         tile.metaData.putString("com.android.settings.intent.action", "TestAction");
    389         tile.userHandle = null;
    390 
    391         mImpl.bindPreferenceToTile(activity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
    392                 preference, tile, "123", Preference.DEFAULT_ORDER);
    393         preference.performClick();
    394 
    395         final ShadowActivity.IntentForResult launchIntent =
    396                 shadowOf(activity).getNextStartedActivityForResult();
    397 
    398         assertThat(launchIntent).isNull();
    399     }
    400 
    401     @Test
    402     public void getPreferences_noCategory_shouldReturnNull() {
    403         mImpl = new DashboardFeatureProviderImpl(mActivity);
    404         ReflectionHelpers.setField(mImpl, "mCategoryManager", mCategoryManager);
    405         when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE))
    406                 .thenReturn(null);
    407 
    408         assertThat(mImpl.getPreferencesForCategory(null, null,
    409                 MetricsProto.MetricsEvent.SETTINGS_GESTURES, CategoryKey.CATEGORY_HOMEPAGE))
    410                 .isNull();
    411     }
    412 
    413     @Test
    414     public void getPreferences_noTileForCategory_shouldReturnNull() {
    415         mImpl = new DashboardFeatureProviderImpl(mActivity);
    416         ReflectionHelpers.setField(mImpl, "mCategoryManager", mCategoryManager);
    417         when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE))
    418                 .thenReturn(new DashboardCategory());
    419 
    420         assertThat(mImpl.getPreferencesForCategory(null, null,
    421                 MetricsProto.MetricsEvent.SETTINGS_GESTURES, CategoryKey.CATEGORY_HOMEPAGE))
    422                 .isNull();
    423     }
    424 
    425     @Test
    426     public void getPreferences_hasTileForCategory_shouldReturnPrefList() {
    427         mImpl = new DashboardFeatureProviderImpl(mActivity);
    428         ReflectionHelpers.setField(mImpl, "mCategoryManager", mCategoryManager);
    429         final DashboardCategory category = new DashboardCategory();
    430         category.addTile(new Tile());
    431         when(mCategoryManager
    432                 .getTilesByCategory(any(Context.class), eq(CategoryKey.CATEGORY_HOMEPAGE)))
    433                 .thenReturn(category);
    434 
    435         assertThat(mImpl.getPreferencesForCategory(mActivity,
    436                 ShadowApplication.getInstance().getApplicationContext(),
    437                 MetricsProto.MetricsEvent.SETTINGS_GESTURES,
    438                 CategoryKey.CATEGORY_HOMEPAGE).isEmpty())
    439                 .isFalse();
    440     }
    441 
    442     @Test
    443     public void testGetExtraIntentAction_shouldReturnNull() {
    444         assertThat(mImpl.getExtraIntentAction()).isNull();
    445     }
    446 
    447     @Test
    448     public void testShouldTintIcon_enabledInResources_shouldBeTrue() {
    449         assertThat(mImpl.shouldTintIcon()).isTrue();
    450     }
    451 
    452     @Test
    453     @Config(qualifiers = "mcc999")
    454     public void testShouldTintIcon_disabledInResources_shouldBeFalse() {
    455         assertThat(mImpl.shouldTintIcon()).isFalse();
    456     }
    457 }
    458