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.settings.location;
17
18import static com.google.common.truth.Truth.assertThat;
19import static org.mockito.ArgumentMatchers.any;
20import static org.mockito.ArgumentMatchers.anyInt;
21import static org.mockito.ArgumentMatchers.eq;
22import static org.mockito.Mockito.doReturn;
23import static org.mockito.Mockito.spy;
24import static org.mockito.Mockito.verify;
25import static org.mockito.Mockito.when;
26
27import android.app.admin.DevicePolicyManager;
28import android.arch.lifecycle.LifecycleOwner;
29import android.content.ComponentName;
30import android.content.Context;
31import android.os.UserHandle;
32import android.os.UserManager;
33import android.provider.Settings;
34import android.support.v7.preference.Preference;
35import android.support.v7.preference.PreferenceCategory;
36import android.support.v7.preference.PreferenceScreen;
37
38import com.android.settings.testutils.SettingsRobolectricTestRunner;
39import com.android.settings.testutils.shadow.ShadowUserManager;
40import com.android.settings.widget.RestrictedAppPreference;
41import com.android.settingslib.core.lifecycle.Lifecycle;
42
43import java.util.ArrayList;
44import java.util.List;
45
46import org.junit.Before;
47import org.junit.Test;
48import org.junit.runner.RunWith;
49import org.mockito.Answers;
50import org.mockito.Mock;
51import org.mockito.MockitoAnnotations;
52import org.robolectric.RuntimeEnvironment;
53import org.robolectric.annotation.Config;
54
55@RunWith(SettingsRobolectricTestRunner.class)
56@Config(
57        shadows = {
58                ShadowUserManager.class
59        })
60public class LocationServicePreferenceControllerTest {
61
62    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
63    private LocationSettings mFragment;
64    @Mock
65    private PreferenceCategory mCategory;
66    @Mock
67    private PreferenceScreen mScreen;
68    @Mock
69    private SettingsInjector mSettingsInjector;
70    @Mock
71    private DevicePolicyManager mDevicePolicyManager;
72
73    private Context mContext;
74    private LocationServicePreferenceController mController;
75    private LifecycleOwner mLifecycleOwner;
76    private Lifecycle mLifecycle;
77
78    @Before
79    public void setUp() {
80        MockitoAnnotations.initMocks(this);
81        mContext = spy(RuntimeEnvironment.application);
82        mLifecycleOwner = () -> mLifecycle;
83        mLifecycle = new Lifecycle(mLifecycleOwner);
84        mController = spy(new LocationServicePreferenceController(
85                mContext, mFragment, mLifecycle, mSettingsInjector));
86        final String key = mController.getPreferenceKey();
87        when(mScreen.findPreference(key)).thenReturn(mCategory);
88        when(mCategory.getKey()).thenReturn(key);
89        when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
90                .thenReturn(mDevicePolicyManager);
91
92    }
93
94    @Test
95    public void isAvailable_noInjectedSettings_shouldReturnFalse() {
96        doReturn(false).when(mSettingsInjector).hasInjectedSettings(anyInt());
97
98        assertThat(mController.isAvailable()).isFalse();
99    }
100
101    @Test
102    public void isAvailable_hasInjectedSettings_shouldReturnFalse() {
103        doReturn(true).when(mSettingsInjector).hasInjectedSettings(anyInt());
104
105        assertThat(mController.isAvailable()).isTrue();
106    }
107
108    @Test
109    public void onResume_shouldRegisterListener() {
110        mController.onResume();
111
112        verify(mContext).registerReceiver(eq(mController.mInjectedSettingsReceiver),
113                eq(mController.INTENT_FILTER_INJECTED_SETTING_CHANGED));
114    }
115
116    @Test
117    public void onPause_shouldUnregisterListener() {
118        mController.onResume();
119        mController.onPause();
120
121        verify(mContext).unregisterReceiver(mController.mInjectedSettingsReceiver);
122    }
123
124    @Test
125    public void updateState_shouldRemoveAllAndAddInjectedSettings() {
126        final List<Preference> preferences = new ArrayList<>();
127        final Preference pref1 = new Preference(mContext);
128        pref1.setTitle("Title1");
129        final Preference pref2 = new Preference(mContext);
130        pref2.setTitle("Title2");
131        preferences.add(pref1);
132        preferences.add(pref2);
133        doReturn(preferences)
134            .when(mSettingsInjector).getInjectedSettings(any(Context.class), anyInt());
135        when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
136        mController.displayPreference(mScreen);
137
138        mController.updateState(mCategory);
139
140        verify(mCategory).removeAll();
141        verify(mCategory).addPreference(pref1);
142        verify(mCategory).addPreference(pref2);
143    }
144
145    @Test
146    public void onLocationModeChanged_shouldRequestReloadInjectedSettigns() {
147        mController.onLocationModeChanged(Settings.Secure.LOCATION_MODE_BATTERY_SAVING, false);
148
149        verify(mSettingsInjector).reloadStatusMessages();
150    }
151
152    @Test
153    public void withUserRestriction_shouldDisableLocationAccuracy() {
154        final List<Preference> preferences = new ArrayList<>();
155        final RestrictedAppPreference pref = new RestrictedAppPreference(mContext,
156                UserManager.DISALLOW_CONFIG_LOCATION);
157        pref.setTitle("Location Accuracy");
158        preferences.add(pref);
159        doReturn(preferences).when(mSettingsInjector)
160                .getInjectedSettings(any(Context.class), anyInt());
161
162        int userId = UserHandle.myUserId();
163        List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
164        enforcingUsers.add(new UserManager.EnforcingUser(userId,
165                UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
166        ComponentName componentName = new ComponentName("test", "test");
167        // Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null.
168        ShadowUserManager.getShadow().setUserRestrictionSources(
169                UserManager.DISALLOW_CONFIG_LOCATION,
170                UserHandle.of(userId),
171                enforcingUsers);
172        when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
173
174        mController.displayPreference(mScreen);
175        mController.updateState(mCategory);
176
177        assertThat(pref.isEnabled()).isFalse();
178        assertThat(pref.isDisabledByAdmin()).isTrue();
179    }
180}
181