1/* 2 * Copyright (C) 2017 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 */ 16package com.android.settingslib; 17 18import static android.Manifest.permission.WRITE_SECURE_SETTINGS; 19 20import static com.android.settingslib.Utils.STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY; 21 22import static com.google.common.truth.Truth.assertThat; 23import static org.mockito.ArgumentMatchers.argThat; 24import static org.mockito.Matchers.eq; 25import static org.mockito.Mockito.mock; 26import static org.mockito.Mockito.spy; 27import static org.mockito.Mockito.verify; 28import static org.mockito.Mockito.when; 29import static org.robolectric.Shadows.shadowOf; 30 31import android.app.ActivityManager; 32import android.content.ContentResolver; 33import android.content.Context; 34import android.content.Intent; 35import android.content.res.Resources; 36import android.location.LocationManager; 37import android.media.AudioManager; 38import android.os.SystemProperties; 39import android.os.UserHandle; 40import android.provider.Settings; 41import android.provider.Settings.Secure; 42import android.text.TextUtils; 43 44import com.android.settingslib.wrapper.LocationManagerWrapper; 45 46import org.junit.Before; 47import org.junit.Test; 48import org.junit.runner.RunWith; 49import org.mockito.ArgumentMatcher; 50import org.mockito.ArgumentMatchers; 51import org.mockito.Mock; 52import org.mockito.MockitoAnnotations; 53import org.robolectric.RuntimeEnvironment; 54import org.robolectric.annotation.Config; 55import org.robolectric.annotation.Implementation; 56import org.robolectric.annotation.Implements; 57import org.robolectric.shadows.ShadowAudioManager; 58import org.robolectric.shadows.ShadowSettings; 59 60import java.util.HashMap; 61import java.util.Map; 62 63@RunWith(SettingsLibRobolectricTestRunner.class) 64@Config(shadows = { 65 UtilsTest.ShadowSecure.class, 66 UtilsTest.ShadowLocationManagerWrapper.class}) 67public class UtilsTest { 68 private static final double[] TEST_PERCENTAGES = {0, 0.4, 0.5, 0.6, 49, 49.3, 49.8, 50, 100}; 69 private static final String PERCENTAGE_0 = "0%"; 70 private static final String PERCENTAGE_1 = "1%"; 71 private static final String PERCENTAGE_49 = "49%"; 72 private static final String PERCENTAGE_50 = "50%"; 73 private static final String PERCENTAGE_100 = "100%"; 74 75 private ShadowAudioManager mShadowAudioManager; 76 private Context mContext; 77 @Mock 78 private LocationManager mLocationManager; 79 80 @Before 81 public void setUp() { 82 MockitoAnnotations.initMocks(this); 83 mContext = spy(RuntimeEnvironment.application); 84 when(mContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); 85 ShadowSecure.reset(); 86 mShadowAudioManager = shadowOf(mContext.getSystemService(AudioManager.class)); 87 } 88 89 @Test 90 public void testUpdateLocationMode_sendBroadcast() { 91 int currentUserId = ActivityManager.getCurrentUser(); 92 Utils.updateLocationMode( 93 mContext, 94 Secure.LOCATION_MODE_OFF, 95 Secure.LOCATION_MODE_HIGH_ACCURACY, 96 currentUserId, 97 Settings.Secure.LOCATION_CHANGER_QUICK_SETTINGS); 98 99 verify(mContext).sendBroadcastAsUser( 100 argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)), 101 ArgumentMatchers.eq(UserHandle.of(currentUserId)), 102 ArgumentMatchers.eq(WRITE_SECURE_SETTINGS)); 103 assertThat(Settings.Secure.getInt(mContext.getContentResolver(), 104 Settings.Secure.LOCATION_CHANGER, Settings.Secure.LOCATION_CHANGER_UNKNOWN)) 105 .isEqualTo(Settings.Secure.LOCATION_CHANGER_QUICK_SETTINGS); 106 } 107 108 @Test 109 public void testUpdateLocationEnabled_sendBroadcast() { 110 int currentUserId = ActivityManager.getCurrentUser(); 111 Utils.updateLocationEnabled(mContext, true, currentUserId, 112 Settings.Secure.LOCATION_CHANGER_QUICK_SETTINGS); 113 114 verify(mContext).sendBroadcastAsUser( 115 argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)), 116 ArgumentMatchers.eq(UserHandle.of(currentUserId)), 117 ArgumentMatchers.eq(WRITE_SECURE_SETTINGS)); 118 assertThat(Settings.Secure.getInt(mContext.getContentResolver(), 119 Settings.Secure.LOCATION_CHANGER, Settings.Secure.LOCATION_CHANGER_UNKNOWN)) 120 .isEqualTo(Settings.Secure.LOCATION_CHANGER_QUICK_SETTINGS); 121 } 122 123 @Test 124 public void testFormatPercentage_RoundTrue_RoundUpIfPossible() { 125 final String[] expectedPercentages = {PERCENTAGE_0, PERCENTAGE_0, PERCENTAGE_1, 126 PERCENTAGE_1, PERCENTAGE_49, PERCENTAGE_49, PERCENTAGE_50, PERCENTAGE_50, 127 PERCENTAGE_100}; 128 129 for (int i = 0, size = TEST_PERCENTAGES.length; i < size; i++) { 130 final String percentage = Utils.formatPercentage(TEST_PERCENTAGES[i], true); 131 assertThat(percentage).isEqualTo(expectedPercentages[i]); 132 } 133 } 134 135 @Test 136 public void testFormatPercentage_RoundFalse_NoRound() { 137 final String[] expectedPercentages = {PERCENTAGE_0, PERCENTAGE_0, PERCENTAGE_0, 138 PERCENTAGE_0, PERCENTAGE_49, PERCENTAGE_49, PERCENTAGE_49, PERCENTAGE_50, 139 PERCENTAGE_100}; 140 141 for (int i = 0, size = TEST_PERCENTAGES.length; i < size; i++) { 142 final String percentage = Utils.formatPercentage(TEST_PERCENTAGES[i], false); 143 assertThat(percentage).isEqualTo(expectedPercentages[i]); 144 } 145 } 146 147 @Test 148 public void testGetDefaultStorageManagerDaysToRetain_storageManagerDaysToRetainUsesResources() { 149 Resources resources = mock(Resources.class); 150 when(resources.getInteger( 151 eq( 152 com.android 153 .internal 154 .R 155 .integer 156 .config_storageManagerDaystoRetainDefault))) 157 .thenReturn(60); 158 assertThat(Utils.getDefaultStorageManagerDaysToRetain(resources)).isEqualTo(60); 159 } 160 161 @Test 162 public void testIsStorageManagerEnabled_UsesSystemProperties() { 163 SystemProperties.set(STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY, "false"); 164 assertThat(Utils.isStorageManagerEnabled(mContext)).isTrue(); 165 } 166 167 private static ArgumentMatcher<Intent> actionMatches(String expected) { 168 return intent -> TextUtils.equals(expected, intent.getAction()); 169 } 170 171 @Implements(value = Settings.Secure.class) 172 public static class ShadowSecure extends ShadowSettings.ShadowSecure { 173 private static Map<String, Integer> map = new HashMap<>(); 174 175 @Implementation 176 public static boolean putIntForUser(ContentResolver cr, String name, int value, int userHandle) { 177 map.put(name, value); 178 return true; 179 } 180 181 @Implementation 182 public static int getIntForUser(ContentResolver cr, String name, int def, int userHandle) { 183 if (map.containsKey(name)) { 184 return map.get(name); 185 } else { 186 return def; 187 } 188 } 189 190 public static void reset() { 191 map.clear(); 192 } 193 } 194 195 @Implements(value = LocationManagerWrapper.class) 196 public static class ShadowLocationManagerWrapper { 197 198 @Implementation 199 public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) { 200 // Do nothing 201 } 202 } 203 204 @Test 205 public void isAudioModeOngoingCall_modeInCommunication_returnTrue() { 206 mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); 207 208 assertThat(Utils.isAudioModeOngoingCall(mContext)).isTrue(); 209 } 210 211 @Test 212 public void isAudioModeOngoingCall_modeInCall_returnTrue() { 213 mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL); 214 215 assertThat(Utils.isAudioModeOngoingCall(mContext)).isTrue(); 216 } 217 218 @Test 219 public void isAudioModeOngoingCall_modeRingtone_returnTrue() { 220 mShadowAudioManager.setMode(AudioManager.MODE_RINGTONE); 221 222 assertThat(Utils.isAudioModeOngoingCall(mContext)).isTrue(); 223 } 224 225 @Test 226 public void isAudioModeOngoingCall_modeNormal_returnFalse() { 227 mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); 228 229 assertThat(Utils.isAudioModeOngoingCall(mContext)).isFalse(); 230 } 231} 232