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 */ 16 package com.android.settings.location; 17 18 import static android.Manifest.permission.WRITE_SECURE_SETTINGS; 19 20 import static com.google.common.truth.Truth.assertThat; 21 22 import static org.mockito.ArgumentMatchers.anyBoolean; 23 import static org.mockito.ArgumentMatchers.anyInt; 24 import static org.mockito.ArgumentMatchers.anyString; 25 import static org.mockito.ArgumentMatchers.argThat; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.Mockito.doReturn; 28 import static org.mockito.Mockito.mock; 29 import static org.mockito.Mockito.reset; 30 import static org.mockito.Mockito.spy; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 34 import android.app.ActivityManager; 35 import android.content.Context; 36 import android.content.Intent; 37 import android.content.pm.UserInfo; 38 import android.location.LocationManager; 39 import android.os.UserHandle; 40 import android.os.UserManager; 41 import android.provider.Settings; 42 import android.text.TextUtils; 43 44 import androidx.lifecycle.LifecycleOwner; 45 46 import com.android.settings.testutils.shadow.ShadowSecureSettings; 47 import com.android.settingslib.core.lifecycle.Lifecycle; 48 49 import org.junit.Before; 50 import org.junit.Test; 51 import org.junit.runner.RunWith; 52 import org.mockito.ArgumentMatcher; 53 import org.mockito.Mock; 54 import org.mockito.MockitoAnnotations; 55 import org.robolectric.RobolectricTestRunner; 56 import org.robolectric.RuntimeEnvironment; 57 import org.robolectric.annotation.Config; 58 59 import java.util.ArrayList; 60 import java.util.List; 61 62 @RunWith(RobolectricTestRunner.class) 63 @Config(shadows = ShadowSecureSettings.class) 64 public class LocationEnablerTest { 65 66 @Mock 67 private UserManager mUserManager; 68 @Mock 69 private LocationEnabler.LocationModeChangeListener mListener; 70 71 private Context mContext; 72 private LocationEnabler mEnabler; 73 private LifecycleOwner mLifecycleOwner; 74 private Lifecycle mLifecycle; 75 76 @Before setUp()77 public void setUp() { 78 MockitoAnnotations.initMocks(this); 79 mContext = spy(RuntimeEnvironment.application); 80 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 81 mLifecycleOwner = () -> mLifecycle; 82 mLifecycle = new Lifecycle(mLifecycleOwner); 83 mEnabler = spy(new LocationEnabler(mContext, mListener, mLifecycle)); 84 } 85 86 @Test onStart_shouldSetActiveAndRegisterListener()87 public void onStart_shouldSetActiveAndRegisterListener() { 88 mEnabler.onStart(); 89 90 verify(mContext).registerReceiver(eq(mEnabler.mReceiver), 91 eq(LocationEnabler.INTENT_FILTER_LOCATION_MODE_CHANGED)); 92 } 93 94 @Test onStart_shouldRefreshLocationMode()95 public void onStart_shouldRefreshLocationMode() { 96 mEnabler.onStart(); 97 98 verify(mEnabler).refreshLocationMode(); 99 } 100 101 @Test onStop_shouldUnregisterListener()102 public void onStop_shouldUnregisterListener() { 103 mEnabler.onStart(); 104 mEnabler.onStop(); 105 106 verify(mContext).unregisterReceiver(mEnabler.mReceiver); 107 } 108 109 @Test onReceive_shouldRefreshLocationMode()110 public void onReceive_shouldRefreshLocationMode() { 111 mEnabler.onStart(); 112 reset(mListener); 113 mEnabler.mReceiver.onReceive(mContext, new Intent()); 114 115 verify(mListener).onLocationModeChanged(anyInt(), anyBoolean()); 116 } 117 118 @Test isEnabled_locationOff_shouldReturnFalse()119 public void isEnabled_locationOff_shouldReturnFalse() { 120 assertThat(mEnabler.isEnabled(Settings.Secure.LOCATION_MODE_OFF)).isFalse(); 121 } 122 123 @Test isEnabled_restricted_shouldReturnFalse()124 public void isEnabled_restricted_shouldReturnFalse() { 125 when(mUserManager.hasUserRestriction(anyString())).thenReturn(true); 126 127 assertThat(mEnabler.isEnabled(Settings.Secure.LOCATION_MODE_OFF)).isFalse(); 128 } 129 130 @Test isEnabled_locationNotRestricted_shouldReturnTrue()131 public void isEnabled_locationNotRestricted_shouldReturnTrue() { 132 when(mUserManager.hasUserRestriction(anyString())).thenReturn(false); 133 134 assertThat(mEnabler.isEnabled(Settings.Secure.LOCATION_MODE_BATTERY_SAVING)).isTrue(); 135 } 136 137 @Test refreshLocationMode_shouldCallOnLocationModeChanged()138 public void refreshLocationMode_shouldCallOnLocationModeChanged() { 139 mEnabler.refreshLocationMode(); 140 141 verify(mListener).onLocationModeChanged(anyInt(), anyBoolean()); 142 } 143 144 @Test setLocationEnabled_notRestricted_shouldRefreshLocation()145 public void setLocationEnabled_notRestricted_shouldRefreshLocation() { 146 when(mUserManager.hasUserRestriction(anyString())).thenReturn(false); 147 Settings.Secure.putInt(mContext.getContentResolver(), 148 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 149 mEnabler.setLocationEnabled(true); 150 151 verify(mEnabler).refreshLocationMode(); 152 } 153 154 @Test setLocationEnabled_notRestricted_shouldBroadcastUpdateAndSetChanger()155 public void setLocationEnabled_notRestricted_shouldBroadcastUpdateAndSetChanger() { 156 when(mUserManager.hasUserRestriction(anyString())).thenReturn(false); 157 Settings.Secure.putInt(mContext.getContentResolver(), 158 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 159 mEnabler.setLocationEnabled(true); 160 161 verify(mContext).sendBroadcastAsUser( 162 argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)), 163 eq(UserHandle.of(ActivityManager.getCurrentUser())), 164 eq(WRITE_SECURE_SETTINGS)); 165 assertThat(Settings.Secure.getInt(mContext.getContentResolver(), 166 Settings.Secure.LOCATION_CHANGER, Settings.Secure.LOCATION_CHANGER_UNKNOWN)) 167 .isEqualTo(Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS); 168 } 169 170 @Test isManagedProfileRestrictedByBase_notManagedProfile_shouldReturnFalse()171 public void isManagedProfileRestrictedByBase_notManagedProfile_shouldReturnFalse() { 172 assertThat(mEnabler.isManagedProfileRestrictedByBase()).isFalse(); 173 } 174 175 @Test isManagedProfileRestrictedByBase_notRestricted_shouldReturnFalse()176 public void isManagedProfileRestrictedByBase_notRestricted_shouldReturnFalse() { 177 mockManagedProfile(); 178 doReturn(false).when(mEnabler).hasShareLocationRestriction(anyInt()); 179 180 assertThat(mEnabler.isManagedProfileRestrictedByBase()).isFalse(); 181 } 182 183 @Test isManagedProfileRestrictedByBase_hasManagedProfile_shouldReturnFalse()184 public void isManagedProfileRestrictedByBase_hasManagedProfile_shouldReturnFalse() { 185 mockManagedProfile(); 186 doReturn(true).when(mEnabler).hasShareLocationRestriction(anyInt()); 187 188 assertThat(mEnabler.isManagedProfileRestrictedByBase()).isTrue(); 189 } 190 191 @Test setRestriction_getShareLocationEnforcedAdmin_shouldReturnEnforcedAdmin()192 public void setRestriction_getShareLocationEnforcedAdmin_shouldReturnEnforcedAdmin() { 193 int userId = UserHandle.myUserId(); 194 List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); 195 // Add two enforcing users so that RestrictedLockUtils.checkIfRestrictionEnforced returns 196 // non-null. 197 enforcingUsers.add(new UserManager.EnforcingUser(userId, 198 UserManager.RESTRICTION_SOURCE_DEVICE_OWNER)); 199 enforcingUsers.add(new UserManager.EnforcingUser(userId, 200 UserManager.RESTRICTION_SOURCE_PROFILE_OWNER)); 201 when(mUserManager.getUserRestrictionSources( 202 UserManager.DISALLOW_CONFIG_LOCATION, UserHandle.of(userId))) 203 .thenReturn(enforcingUsers); 204 205 assertThat(mEnabler.getShareLocationEnforcedAdmin(userId) != null).isTrue(); 206 } 207 mockManagedProfile()208 private void mockManagedProfile() { 209 final List<UserHandle> userProfiles = new ArrayList<>(); 210 final UserHandle userHandle = mock(UserHandle.class); 211 when(userHandle.getIdentifier()).thenReturn(5); 212 userProfiles.add(userHandle); 213 when(mUserManager.getUserProfiles()).thenReturn(userProfiles); 214 when(mUserManager.getUserHandle()).thenReturn(1); 215 when(mUserManager.getUserInfo(5)) 216 .thenReturn(new UserInfo(5, "user 5", UserInfo.FLAG_MANAGED_PROFILE)); 217 } 218 actionMatches(String expected)219 private static ArgumentMatcher<Intent> actionMatches(String expected) { 220 return intent -> TextUtils.equals(expected, intent.getAction()); 221 } 222 } 223