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.security; 18 19 import android.content.Context; 20 import android.content.IContentProvider; 21 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.content.res.Resources; 24 import android.graphics.drawable.Drawable; 25 import android.os.Bundle; 26 import android.support.v7.preference.Preference; 27 import android.support.v7.preference.PreferenceScreen; 28 import android.util.Pair; 29 30 import com.android.settings.testutils.SettingsRobolectricTestRunner; 31 import com.android.settings.R; 32 import com.android.settings.TestConfig; 33 import com.android.settingslib.drawer.DashboardCategory; 34 import com.android.settingslib.drawer.Tile; 35 import com.android.settingslib.drawer.TileUtils; 36 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 import org.mockito.Mock; 41 import org.mockito.MockitoAnnotations; 42 import org.robolectric.RuntimeEnvironment; 43 import org.robolectric.annotation.Config; 44 import org.robolectric.annotation.Implementation; 45 import org.robolectric.annotation.Implements; 46 import org.robolectric.shadows.ShadowLooper; 47 48 import java.util.Map; 49 50 import static org.mockito.Matchers.any; 51 import static org.mockito.Matchers.anyInt; 52 import static org.mockito.Matchers.anyString; 53 import static org.mockito.Mockito.mock; 54 import static org.mockito.Mockito.never; 55 import static org.mockito.Mockito.spy; 56 import static org.mockito.Mockito.verify; 57 import static org.mockito.Mockito.verifyNoMoreInteractions; 58 import static org.mockito.Mockito.when; 59 60 @RunWith(SettingsRobolectricTestRunner.class) 61 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) 62 public class SecurityFeatureProviderImplTest { 63 64 private static final String MOCK_KEY = "key"; 65 private static final String MOCK_SUMMARY = "summary"; 66 private static final String URI_GET_SUMMARY = "content://package/text/summary"; 67 private static final String URI_GET_ICON = "content://package/icon/my_icon"; 68 69 @Mock 70 private Drawable mMockDrawable; 71 @Mock 72 private Context mContext; 73 @Mock 74 private PackageManager mPackageManager; 75 @Mock 76 private Resources mResources; 77 78 private SecurityFeatureProviderImpl mImpl; 79 80 @Implements(com.android.settingslib.drawer.TileUtils.class) 81 public static class ShadowTileUtils { 82 @Implementation getIconFromUri(Context context, String packageName, String uriString, Map<String, IContentProvider> providerMap)83 public static Pair getIconFromUri(Context context, String packageName, String uriString, 84 Map<String, IContentProvider> providerMap) { 85 return Pair.create("package", 161803); 86 } 87 88 @Implementation getTextFromUri(Context context, String uriString, Map<String, IContentProvider> providerMap, String key)89 public static String getTextFromUri(Context context, String uriString, 90 Map<String, IContentProvider> providerMap, String key) { 91 return MOCK_SUMMARY; 92 } 93 } 94 95 @Before setUp()96 public void setUp() throws PackageManager.NameNotFoundException { 97 MockitoAnnotations.initMocks(this); 98 mContext = spy(RuntimeEnvironment.application); 99 mImpl = new SecurityFeatureProviderImpl(); 100 when(mContext.getPackageManager()).thenReturn(mPackageManager); 101 when(mPackageManager.getResourcesForApplication(anyString())).thenReturn(mResources); 102 when(mResources.getDrawable(anyInt(), any())).thenReturn(mMockDrawable); 103 } 104 105 @Test updateTilesData_shouldNotProcessEmptyScreenOrTiles()106 public void updateTilesData_shouldNotProcessEmptyScreenOrTiles() { 107 mImpl.updatePreferencesToRunOnWorkerThread(mContext, null, null); 108 ShadowLooper.runUiThreadTasks(); 109 mImpl.updatePreferencesToRunOnWorkerThread( 110 mContext, new PreferenceScreen(mContext, null), null); 111 ShadowLooper.runUiThreadTasks(); 112 verifyNoMoreInteractions(mPackageManager); 113 } 114 115 @Test updateTilesData_shouldNotProcessNonMatchingPreference()116 public void updateTilesData_shouldNotProcessNonMatchingPreference() { 117 DashboardCategory dashboardCategory = new DashboardCategory(); 118 dashboardCategory.addTile(new Tile()); 119 mImpl.updatePreferencesToRunOnWorkerThread( 120 mContext, getPreferenceScreen(), dashboardCategory); 121 ShadowLooper.runUiThreadTasks(); 122 verifyNoMoreInteractions(mPackageManager); 123 } 124 125 @Test updateTilesData_shouldNotProcessMatchingPreferenceWithNoData()126 public void updateTilesData_shouldNotProcessMatchingPreferenceWithNoData() { 127 mImpl.updatePreferencesToRunOnWorkerThread( 128 mContext, getPreferenceScreen(), getDashboardCategory()); 129 ShadowLooper.runUiThreadTasks(); 130 verifyNoMoreInteractions(mPackageManager); 131 } 132 133 @Test 134 @Config(shadows = { 135 ShadowTileUtils.class, 136 }) updateTilesData_shouldUpdateMatchingPreference()137 public void updateTilesData_shouldUpdateMatchingPreference() { 138 Bundle bundle = new Bundle(); 139 bundle.putString(TileUtils.META_DATA_PREFERENCE_ICON_URI, URI_GET_ICON); 140 bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, URI_GET_SUMMARY); 141 142 PreferenceScreen screen = getPreferenceScreen(); 143 DashboardCategory dashboardCategory = getDashboardCategory(); 144 dashboardCategory.getTile(0).intent = new Intent().setPackage("package"); 145 dashboardCategory.getTile(0).metaData = bundle; 146 147 mImpl.updatePreferencesToRunOnWorkerThread(mContext, screen, dashboardCategory); 148 ShadowLooper.runUiThreadTasks(); 149 verify(screen.findPreference(MOCK_KEY)).setIcon(mMockDrawable); 150 verify(screen.findPreference(MOCK_KEY)).setSummary(MOCK_SUMMARY); 151 } 152 153 @Test 154 @Config(shadows = { 155 ShadowTileUtils.class, 156 }) updateTilesData_shouldNotUpdateAlreadyUpdatedPreference()157 public void updateTilesData_shouldNotUpdateAlreadyUpdatedPreference() { 158 Bundle bundle = new Bundle(); 159 bundle.putString(TileUtils.META_DATA_PREFERENCE_ICON_URI, URI_GET_ICON); 160 bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, URI_GET_SUMMARY); 161 162 PreferenceScreen screen = getPreferenceScreen(); 163 when(screen.findPreference(MOCK_KEY).getSummary()).thenReturn(MOCK_SUMMARY); 164 when(screen.findPreference(MOCK_KEY).getIcon()).thenReturn(mMockDrawable); 165 166 DashboardCategory dashboardCategory = getDashboardCategory(); 167 dashboardCategory.getTile(0).intent = new Intent().setPackage("package"); 168 dashboardCategory.getTile(0).metaData = bundle; 169 170 mImpl.updatePreferencesToRunOnWorkerThread(mContext, screen, dashboardCategory); 171 ShadowLooper.runUiThreadTasks(); 172 verify(screen.findPreference(MOCK_KEY), never()).setSummary(anyString()); 173 } 174 175 @Test initPreferences_shouldLoadDefaults()176 public void initPreferences_shouldLoadDefaults() { 177 PreferenceScreen screen = getPreferenceScreen(); 178 DashboardCategory dashboardCategory = getDashboardCategory(); 179 dashboardCategory.getTile(0).metaData = new Bundle(); 180 181 mImpl.initPreferences(mContext, screen, dashboardCategory); 182 verify(screen.findPreference(MOCK_KEY)).setIcon(SecurityFeatureProviderImpl.DEFAULT_ICON); 183 verify(screen.findPreference(MOCK_KEY)) 184 .setSummary(mContext.getString(R.string.summary_placeholder)); 185 } 186 187 @Test 188 @Config(shadows = { 189 ShadowTileUtils.class, 190 }) initPreferences_shouldLoadCached()191 public void initPreferences_shouldLoadCached() { 192 Bundle bundle = new Bundle(); 193 bundle.putString(TileUtils.META_DATA_PREFERENCE_ICON_URI, URI_GET_ICON); 194 bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, URI_GET_SUMMARY); 195 196 PreferenceScreen screen = getPreferenceScreen(); 197 DashboardCategory dashboardCategory = getDashboardCategory(); 198 dashboardCategory.getTile(0).metaData = bundle; 199 200 SecurityFeatureProviderImpl.sIconCache.put( 201 URI_GET_ICON, 202 ShadowTileUtils.getIconFromUri(null, null, null, null)); 203 SecurityFeatureProviderImpl.sSummaryCache.put( 204 URI_GET_SUMMARY, 205 MOCK_SUMMARY); 206 207 mImpl.initPreferences(mContext, screen, dashboardCategory); 208 verify(screen.findPreference(MOCK_KEY)).setIcon(mMockDrawable); 209 verify(screen.findPreference(MOCK_KEY)).setSummary(MOCK_SUMMARY); 210 } 211 getPreferenceScreen()212 private PreferenceScreen getPreferenceScreen() { 213 final PreferenceScreen screen = mock(PreferenceScreen.class); 214 final Preference pref = mock(Preference.class); 215 when(screen.findPreference(MOCK_KEY)).thenReturn(pref); 216 when(pref.getKey()).thenReturn(MOCK_KEY); 217 return screen; 218 } 219 getDashboardCategory()220 private static DashboardCategory getDashboardCategory() { 221 DashboardCategory dashboardCategory = new DashboardCategory(); 222 Tile tile = new Tile(); 223 tile.key = MOCK_KEY; 224 dashboardCategory.addTile(tile); 225 return dashboardCategory; 226 } 227 } 228