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.content.ComponentName;
30 import android.content.Context;
31 import android.os.UserHandle;
32 import android.os.UserManager;
33 import android.provider.Settings;
34 import android.util.ArrayMap;
35 
36 import androidx.lifecycle.LifecycleOwner;
37 import androidx.preference.Preference;
38 import androidx.preference.PreferenceCategory;
39 import androidx.preference.PreferenceScreen;
40 
41 import com.android.settings.testutils.shadow.ShadowUserManager;
42 import com.android.settings.widget.RestrictedAppPreference;
43 import com.android.settingslib.core.lifecycle.Lifecycle;
44 
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.mockito.Answers;
49 import org.mockito.Mock;
50 import org.mockito.MockitoAnnotations;
51 import org.robolectric.RobolectricTestRunner;
52 import org.robolectric.RuntimeEnvironment;
53 import org.robolectric.annotation.Config;
54 
55 import java.util.ArrayList;
56 import java.util.List;
57 import java.util.Map;
58 
59 @RunWith(RobolectricTestRunner.class)
60 @Config(shadows = ShadowUserManager.class)
61 public class LocationInjectedServicesPreferenceControllerTest {
62 
63     private static final String KEY_LOCATION_SERVICES = "location_service";
64 
65     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
66     private LocationSettings mFragment;
67     @Mock
68     private PreferenceCategory mCategoryPrimary;
69     @Mock
70     private PreferenceScreen mScreen;
71     @Mock
72     private AppSettingsInjector mSettingsInjector;
73     @Mock
74     private DevicePolicyManager mDevicePolicyManager;
75 
76     private Context mContext;
77     private LocationInjectedServicesPreferenceController mController;
78     private LifecycleOwner mLifecycleOwner;
79     private Lifecycle mLifecycle;
80 
81     @Before
setUp()82     public void setUp() {
83         MockitoAnnotations.initMocks(this);
84         mContext = spy(RuntimeEnvironment.application);
85         mLifecycleOwner = () -> mLifecycle;
86         mLifecycle = new Lifecycle(mLifecycleOwner);
87         mController = spy(
88                 new LocationInjectedServicesPreferenceController(mContext, KEY_LOCATION_SERVICES));
89         when(mFragment.getSettingsLifecycle()).thenReturn(mLifecycle);
90         mController.init(mFragment);
91         mController.mInjector = mSettingsInjector;
92         final String key = mController.getPreferenceKey();
93         when(mScreen.findPreference(key)).thenReturn(mCategoryPrimary);
94         when(mCategoryPrimary.getKey()).thenReturn(key);
95         when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
96                 .thenReturn(mDevicePolicyManager);
97     }
98 
99     @Test
onResume_shouldRegisterListener()100     public void onResume_shouldRegisterListener() {
101         mController.onResume();
102 
103         verify(mContext).registerReceiver(eq(mController.mInjectedSettingsReceiver),
104                 eq(mController.INTENT_FILTER_INJECTED_SETTING_CHANGED));
105     }
106 
107     @Test
onPause_shouldUnregisterListener()108     public void onPause_shouldUnregisterListener() {
109         mController.onResume();
110         mController.onPause();
111 
112         verify(mContext).unregisterReceiver(mController.mInjectedSettingsReceiver);
113     }
114 
115     @Test
workProfileDisallowShareLocationOn_getParentUserLocationServicesOnly()116     public void workProfileDisallowShareLocationOn_getParentUserLocationServicesOnly() {
117         final int fakeWorkProfileId = 123;
118         ShadowUserManager.getShadow().setProfileIdsWithDisabled(
119                 new int[]{UserHandle.myUserId(), fakeWorkProfileId});
120 
121         // Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return non-null.
122         final List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
123         enforcingUsers.add(new UserManager.EnforcingUser(fakeWorkProfileId,
124                 UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
125         final ComponentName componentName = new ComponentName("test", "test");
126         // Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null.
127         ShadowUserManager.getShadow().setUserRestrictionSources(
128                 UserManager.DISALLOW_SHARE_LOCATION,
129                 UserHandle.of(fakeWorkProfileId),
130                 enforcingUsers);
131         when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
132 
133         mController.displayPreference(mScreen);
134         verify(mSettingsInjector).getInjectedSettings(
135                 any(Context.class), eq(UserHandle.myUserId()));
136     }
137 
138     @Test
workProfileDisallowShareLocationOff_getAllUserLocationServices()139     public void workProfileDisallowShareLocationOff_getAllUserLocationServices() {
140         final int fakeWorkProfileId = 123;
141         ShadowUserManager.getShadow().setProfileIdsWithDisabled(
142                 new int[]{UserHandle.myUserId(), fakeWorkProfileId});
143 
144         // Mock RestrictedLockUtils.checkIfRestrictionEnforced and let it return null.
145         // Empty enforcing users.
146         final List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
147         ShadowUserManager.getShadow().setUserRestrictionSources(
148                 UserManager.DISALLOW_SHARE_LOCATION,
149                 UserHandle.of(fakeWorkProfileId),
150                 enforcingUsers);
151 
152         mController.displayPreference(mScreen);
153         verify(mSettingsInjector).getInjectedSettings(
154                 any(Context.class), eq(UserHandle.USER_CURRENT));
155     }
156 
157     @Test
onLocationModeChanged_shouldRequestReloadInjectedSettigns()158     public void onLocationModeChanged_shouldRequestReloadInjectedSettigns() {
159         mController.onLocationModeChanged(Settings.Secure.LOCATION_MODE_BATTERY_SAVING, false);
160 
161         verify(mSettingsInjector).reloadStatusMessages();
162     }
163 
164     @Test
withUserRestriction_shouldDisableLocationAccuracy()165     public void withUserRestriction_shouldDisableLocationAccuracy() {
166         final List<Preference> preferences = new ArrayList<>();
167         final RestrictedAppPreference pref = new RestrictedAppPreference(mContext,
168                 UserManager.DISALLOW_CONFIG_LOCATION);
169         pref.setTitle("Location Accuracy");
170         preferences.add(pref);
171         final Map<Integer, List<Preference>> map = new ArrayMap<>();
172         map.put(UserHandle.myUserId(), preferences);
173         doReturn(map).when(mSettingsInjector)
174                 .getInjectedSettings(any(Context.class), anyInt());
175         ShadowUserManager.getShadow().setProfileIdsWithDisabled(new int[]{UserHandle.myUserId()});
176 
177         final int userId = UserHandle.myUserId();
178         List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
179         enforcingUsers.add(new UserManager.EnforcingUser(userId,
180                 UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
181         ComponentName componentName = new ComponentName("test", "test");
182         // Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null.
183         ShadowUserManager.getShadow().setUserRestrictionSources(
184                 UserManager.DISALLOW_CONFIG_LOCATION,
185                 UserHandle.of(userId),
186                 enforcingUsers);
187         when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
188 
189         mController.displayPreference(mScreen);
190 
191         assertThat(pref.isEnabled()).isFalse();
192         assertThat(pref.isDisabledByAdmin()).isTrue();
193     }
194 }
195