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 com.google.common.truth.Truth.assertThat; 19 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.ArgumentMatchers.anyInt; 22 import static org.mockito.ArgumentMatchers.eq; 23 import static org.mockito.Mockito.doReturn; 24 import static org.mockito.Mockito.spy; 25 import static org.mockito.Mockito.verify; 26 import static org.mockito.Mockito.when; 27 28 import android.app.admin.DevicePolicyManager; 29 import android.app.admin.DevicePolicyResourcesManager; 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.pm.UserInfo; 33 import android.os.UserHandle; 34 import android.os.UserManager; 35 import android.platform.test.flag.junit.SetFlagsRule; 36 import android.provider.Settings; 37 import android.util.ArrayMap; 38 import android.util.ArraySet; 39 40 import androidx.lifecycle.LifecycleOwner; 41 import androidx.preference.Preference; 42 import androidx.preference.PreferenceCategory; 43 import androidx.preference.PreferenceScreen; 44 import androidx.test.core.app.ApplicationProvider; 45 46 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; 47 import com.android.settings.testutils.shadow.ShadowUserManager; 48 import com.android.settings.widget.RestrictedAppPreference; 49 import com.android.settingslib.core.lifecycle.Lifecycle; 50 51 import org.junit.Before; 52 import org.junit.Rule; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.Answers; 56 import org.mockito.ArgumentCaptor; 57 import org.mockito.Mock; 58 import org.mockito.junit.MockitoJUnit; 59 import org.mockito.junit.MockitoRule; 60 import org.robolectric.RobolectricTestRunner; 61 import org.robolectric.annotation.Config; 62 63 import java.util.ArrayList; 64 import java.util.List; 65 import java.util.Map; 66 67 @RunWith(RobolectricTestRunner.class) 68 @Config(shadows = {ShadowUserManager.class, ShadowDevicePolicyManager.class}) 69 public class LocationInjectedServicesPreferenceControllerTest { 70 @Rule 71 public final MockitoRule mMockitoRule = MockitoJUnit.rule(); 72 @Rule 73 public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 74 75 private static final String KEY_LOCATION_SERVICES = "location_service"; 76 77 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 78 private LocationSettings mFragment; 79 @Mock 80 private PreferenceCategory mCategoryPrimary; 81 @Mock 82 private PreferenceScreen mScreen; 83 @Mock 84 private AppSettingsInjector mSettingsInjector; 85 @Mock 86 private DevicePolicyManager mDevicePolicyManager; 87 @Mock 88 private DevicePolicyResourcesManager mDevicePolicyResourcesManager; 89 90 private Context mContext; 91 private LocationInjectedServicesPreferenceController mController; 92 private LifecycleOwner mLifecycleOwner; 93 private Lifecycle mLifecycle; 94 95 @Before setUp()96 public void setUp() { 97 mContext = spy(ApplicationProvider.getApplicationContext()); 98 mLifecycleOwner = () -> mLifecycle; 99 mLifecycle = new Lifecycle(mLifecycleOwner); 100 mController = spy( 101 new LocationInjectedServicesPreferenceController(mContext, KEY_LOCATION_SERVICES)); 102 when(mFragment.getSettingsLifecycle()).thenReturn(mLifecycle); 103 mController.init(mFragment); 104 mController.mInjector = mSettingsInjector; 105 final String key = mController.getPreferenceKey(); 106 when(mScreen.findPreference(key)).thenReturn(mCategoryPrimary); 107 when(mCategoryPrimary.getKey()).thenReturn(key); 108 when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) 109 .thenReturn(mDevicePolicyManager); 110 when(mDevicePolicyManager.getResources()).thenReturn(mDevicePolicyResourcesManager); 111 } 112 113 @Test onResume_shouldRegisterListener()114 public void onResume_shouldRegisterListener() { 115 mController.onResume(); 116 117 verify(mContext).registerReceiver(eq(mController.mInjectedSettingsReceiver), 118 eq(mController.INTENT_FILTER_INJECTED_SETTING_CHANGED), 119 anyInt()); 120 } 121 122 @Test onPause_shouldUnregisterListener()123 public void onPause_shouldUnregisterListener() { 124 mController.onResume(); 125 mController.onPause(); 126 127 verify(mContext).unregisterReceiver(mController.mInjectedSettingsReceiver); 128 } 129 130 @Test workProfileDisallowShareLocationOn_getParentUserLocationServicesOnly()131 public void workProfileDisallowShareLocationOn_getParentUserLocationServicesOnly() { 132 final int fakeWorkProfileId = 123; 133 ShadowUserManager.getShadow().setProfileIdsWithDisabled( 134 new int[]{UserHandle.myUserId(), fakeWorkProfileId}); 135 ShadowUserManager.getShadow().addProfile(new UserInfo(UserHandle.myUserId(), "", 0)); 136 ShadowUserManager.getShadow().addProfile(new UserInfo(fakeWorkProfileId, "", 137 UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE)); 138 139 // Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return non-null. 140 final List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); 141 enforcingUsers.add(new UserManager.EnforcingUser(fakeWorkProfileId, 142 UserManager.RESTRICTION_SOURCE_DEVICE_OWNER)); 143 final ComponentName componentName = new ComponentName("test", "test"); 144 // Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null. 145 ShadowUserManager.getShadow().setUserRestrictionSources( 146 UserManager.DISALLOW_SHARE_LOCATION, 147 UserHandle.of(fakeWorkProfileId), 148 enforcingUsers); 149 when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName); 150 151 mController.displayPreference(mScreen); 152 153 ArgumentCaptor<ArraySet<UserHandle>> profilesArgumentCaptor = 154 ArgumentCaptor.forClass(ArraySet.class); 155 verify(mSettingsInjector).getInjectedSettings( 156 any(Context.class), profilesArgumentCaptor.capture()); 157 assertThat(profilesArgumentCaptor.getValue()) 158 .doesNotContain(UserHandle.of(fakeWorkProfileId)); 159 } 160 161 @Test workProfileDisallowShareLocationOff_getAllUserLocationServices()162 public void workProfileDisallowShareLocationOff_getAllUserLocationServices() { 163 final int fakeWorkProfileId = 123; 164 ShadowUserManager.getShadow().setProfileIdsWithDisabled( 165 new int[]{UserHandle.myUserId(), fakeWorkProfileId}); 166 ShadowUserManager.getShadow().addProfile(new UserInfo(UserHandle.myUserId(), "", 0)); 167 ShadowUserManager.getShadow().addProfile(new UserInfo(fakeWorkProfileId, "", 168 UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE)); 169 170 // Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return null. 171 // Empty enforcing users. 172 final List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); 173 ShadowUserManager.getShadow().setUserRestrictionSources( 174 UserManager.DISALLOW_SHARE_LOCATION, 175 UserHandle.of(fakeWorkProfileId), 176 enforcingUsers); 177 178 mController.displayPreference(mScreen); 179 180 ArgumentCaptor<ArraySet<UserHandle>> profilesArgumentCaptor = 181 ArgumentCaptor.forClass(ArraySet.class); 182 verify(mSettingsInjector).getInjectedSettings( 183 any(Context.class), profilesArgumentCaptor.capture()); 184 assertThat(profilesArgumentCaptor.getValue()).contains(UserHandle.of(fakeWorkProfileId)); 185 } 186 187 @Test privateProfileDisallowShareLocationOn_getParentUserLocationServicesOnly()188 public void privateProfileDisallowShareLocationOn_getParentUserLocationServicesOnly() { 189 mSetFlagsRule.enableFlags( 190 android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE, 191 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES, 192 android.multiuser.Flags.FLAG_HANDLE_INTERLEAVED_SETTINGS_FOR_PRIVATE_SPACE); 193 final int fakePrivateProfileId = 123; 194 ShadowUserManager.getShadow().setProfileIdsWithDisabled( 195 new int[]{UserHandle.myUserId(), fakePrivateProfileId}); 196 ShadowUserManager.getShadow().addProfile(new UserInfo(UserHandle.myUserId(), "", 0)); 197 ShadowUserManager.getShadow().setPrivateProfile(fakePrivateProfileId, "private", 0); 198 ShadowUserManager.getShadow().addUserProfile(UserHandle.of(fakePrivateProfileId)); 199 200 // Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return non-null. 201 final List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); 202 enforcingUsers.add(new UserManager.EnforcingUser(fakePrivateProfileId, 203 UserManager.RESTRICTION_SOURCE_DEVICE_OWNER)); 204 final ComponentName componentName = new ComponentName("test", "test"); 205 // Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null. 206 ShadowUserManager.getShadow().setUserRestrictionSources( 207 UserManager.DISALLOW_SHARE_LOCATION, 208 UserHandle.of(fakePrivateProfileId), 209 enforcingUsers); 210 when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName); 211 212 mController.displayPreference(mScreen); 213 214 ArgumentCaptor<ArraySet<UserHandle>> profilesArgumentCaptor = 215 ArgumentCaptor.forClass(ArraySet.class); 216 verify(mSettingsInjector).getInjectedSettings( 217 any(Context.class), profilesArgumentCaptor.capture()); 218 assertThat(profilesArgumentCaptor.getValue()) 219 .doesNotContain(UserHandle.of(fakePrivateProfileId)); 220 } 221 222 @Test privateProfileDisallowShareLocationOff_getAllUserLocationServices()223 public void privateProfileDisallowShareLocationOff_getAllUserLocationServices() { 224 mSetFlagsRule.enableFlags( 225 android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE, 226 android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES, 227 android.multiuser.Flags.FLAG_HANDLE_INTERLEAVED_SETTINGS_FOR_PRIVATE_SPACE); 228 final int fakePrivateProfileId = 123; 229 ShadowUserManager.getShadow().setProfileIdsWithDisabled( 230 new int[]{UserHandle.myUserId(), fakePrivateProfileId}); 231 ShadowUserManager.getShadow().addProfile(new UserInfo(UserHandle.myUserId(), "", 0)); 232 ShadowUserManager.getShadow().setPrivateProfile(fakePrivateProfileId, "private", 0); 233 ShadowUserManager.getShadow().addUserProfile(UserHandle.of(fakePrivateProfileId)); 234 235 // Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return null. 236 // Empty enforcing users. 237 final List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); 238 ShadowUserManager.getShadow().setUserRestrictionSources( 239 UserManager.DISALLOW_SHARE_LOCATION, 240 UserHandle.of(fakePrivateProfileId), 241 enforcingUsers); 242 243 mController.displayPreference(mScreen); 244 245 ArgumentCaptor<ArraySet<UserHandle>> profilesArgumentCaptor = 246 ArgumentCaptor.forClass(ArraySet.class); 247 verify(mSettingsInjector).getInjectedSettings( 248 any(Context.class), profilesArgumentCaptor.capture()); 249 assertThat(profilesArgumentCaptor.getValue()).contains(UserHandle.of(fakePrivateProfileId)); 250 } 251 252 @Test onLocationModeChanged_shouldRequestReloadInjectedSettigns()253 public void onLocationModeChanged_shouldRequestReloadInjectedSettigns() { 254 mController.onLocationModeChanged(Settings.Secure.LOCATION_MODE_BATTERY_SAVING, false); 255 256 verify(mSettingsInjector).reloadStatusMessages(); 257 } 258 259 @Test withUserRestriction_shouldDisableLocationAccuracy()260 public void withUserRestriction_shouldDisableLocationAccuracy() { 261 final List<Preference> preferences = new ArrayList<>(); 262 final RestrictedAppPreference pref = new RestrictedAppPreference(mContext, 263 UserManager.DISALLOW_CONFIG_LOCATION); 264 pref.setTitle("Location Accuracy"); 265 preferences.add(pref); 266 final Map<Integer, List<Preference>> map = new ArrayMap<>(); 267 map.put(UserHandle.myUserId(), preferences); 268 doReturn(map).when(mSettingsInjector) 269 .getInjectedSettings(any(Context.class), any(ArraySet.class)); 270 ShadowUserManager.getShadow().setProfileIdsWithDisabled(new int[]{UserHandle.myUserId()}); 271 272 final int userId = UserHandle.myUserId(); 273 List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); 274 enforcingUsers.add(new UserManager.EnforcingUser(userId, 275 UserManager.RESTRICTION_SOURCE_DEVICE_OWNER)); 276 ComponentName componentName = new ComponentName("test", "test"); 277 // Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null. 278 ShadowUserManager.getShadow().setUserRestrictionSources( 279 UserManager.DISALLOW_CONFIG_LOCATION, 280 UserHandle.of(userId), 281 enforcingUsers); 282 when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName); 283 when(mDevicePolicyResourcesManager.getString(any(), any())).thenReturn(any()); 284 285 mController.displayPreference(mScreen); 286 287 assertThat(pref.isEnabled()).isFalse(); 288 assertThat(pref.isDisabledByAdmin()).isTrue(); 289 } 290 } 291