Home | History | Annotate | Download | only in location
      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 import static com.google.common.truth.Truth.assertThat;
     20 import static org.mockito.ArgumentMatchers.anyBoolean;
     21 import static org.mockito.ArgumentMatchers.anyInt;
     22 import static org.mockito.ArgumentMatchers.anyString;
     23 import static org.mockito.ArgumentMatchers.argThat;
     24 import static org.mockito.ArgumentMatchers.eq;
     25 import static org.mockito.Mockito.doReturn;
     26 import static org.mockito.Mockito.mock;
     27 import static org.mockito.Mockito.reset;
     28 import static org.mockito.Mockito.spy;
     29 import static org.mockito.Mockito.verify;
     30 import static org.mockito.Mockito.when;
     31 
     32 import android.app.ActivityManager;
     33 import android.arch.lifecycle.LifecycleOwner;
     34 import android.content.Context;
     35 import android.content.Intent;
     36 import android.content.pm.UserInfo;
     37 import android.location.LocationManager;
     38 import android.os.UserHandle;
     39 import android.os.UserManager;
     40 import android.provider.Settings;
     41 import android.text.TextUtils;
     42 
     43 import com.android.settings.testutils.SettingsRobolectricTestRunner;
     44 import com.android.settings.testutils.shadow.ShadowSecureSettings;
     45 import com.android.settingslib.core.lifecycle.Lifecycle;
     46 import com.android.settingslib.wrapper.LocationManagerWrapper;
     47 
     48 import org.junit.Before;
     49 import org.junit.Test;
     50 import org.junit.runner.RunWith;
     51 import org.mockito.ArgumentMatcher;
     52 import org.mockito.Mock;
     53 import org.mockito.MockitoAnnotations;
     54 import org.robolectric.RuntimeEnvironment;
     55 import org.robolectric.annotation.Config;
     56 import org.robolectric.annotation.Implementation;
     57 import org.robolectric.annotation.Implements;
     58 
     59 import java.util.ArrayList;
     60 import java.util.List;
     61 
     62 @RunWith(SettingsRobolectricTestRunner.class)
     63 @Config(shadows = {
     64     ShadowSecureSettings.class,
     65     LocationEnablerTest.ShadowLocationManagerWrapper.class})
     66 public class LocationEnablerTest {
     67 
     68     @Mock
     69     private UserManager mUserManager;
     70     @Mock
     71     private LocationEnabler.LocationModeChangeListener mListener;
     72 
     73     private Context mContext;
     74     private LocationEnabler mEnabler;
     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         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
     83         mLifecycleOwner = () -> mLifecycle;
     84         mLifecycle = new Lifecycle(mLifecycleOwner);
     85         mEnabler = spy(new LocationEnabler(mContext, mListener, mLifecycle));
     86     }
     87 
     88     @Test
     89     public void onResume_shouldSetActiveAndRegisterListener() {
     90         mEnabler.onResume();
     91 
     92         verify(mContext).registerReceiver(eq(mEnabler.mReceiver),
     93                 eq(LocationEnabler.INTENT_FILTER_LOCATION_MODE_CHANGED));
     94     }
     95 
     96     @Test
     97     public void onResume_shouldRefreshLocationMode() {
     98         mEnabler.onResume();
     99 
    100         verify(mEnabler).refreshLocationMode();
    101     }
    102 
    103     @Test
    104     public void onPause_shouldUnregisterListener() {
    105         mEnabler.onPause();
    106 
    107         verify(mContext).unregisterReceiver(mEnabler.mReceiver);
    108     }
    109 
    110     @Test
    111     public void onReceive_shouldRefreshLocationMode() {
    112         mEnabler.onResume();
    113         reset(mListener);
    114         mEnabler.mReceiver.onReceive(mContext, new Intent());
    115 
    116         verify(mListener).onLocationModeChanged(anyInt(), anyBoolean());
    117     }
    118 
    119     @Test
    120     public void isEnabled_locationOff_shouldReturnFalse() {
    121         assertThat(mEnabler.isEnabled(Settings.Secure.LOCATION_MODE_OFF)).isFalse();
    122     }
    123 
    124     @Test
    125     public void isEnabled_restricted_shouldReturnFalse() {
    126         when(mUserManager.hasUserRestriction(anyString())).thenReturn(true);
    127 
    128         assertThat(mEnabler.isEnabled(Settings.Secure.LOCATION_MODE_OFF)).isFalse();
    129     }
    130 
    131     @Test
    132     public void isEnabled_locationNotRestricted_shouldReturnTrue() {
    133         when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
    134 
    135         assertThat(mEnabler.isEnabled(Settings.Secure.LOCATION_MODE_BATTERY_SAVING)).isTrue();
    136     }
    137 
    138     @Test
    139     public void refreshLocationMode_shouldCallOnLocationModeChanged() {
    140         mEnabler.refreshLocationMode();
    141 
    142         verify(mListener).onLocationModeChanged(anyInt(), anyBoolean());
    143     }
    144 
    145     @Test
    146     public void setLocationMode_restricted_shouldSetCurrentMode() {
    147         when(mUserManager.hasUserRestriction(anyString())).thenReturn(true);
    148         Settings.Secure.putInt(mContext.getContentResolver(),
    149                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_BATTERY_SAVING);
    150 
    151         mEnabler.setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
    152 
    153         verify(mListener).onLocationModeChanged(Settings.Secure.LOCATION_MODE_BATTERY_SAVING, true);
    154     }
    155 
    156     @Test
    157     public void setLocationMode_notRestricted_shouldUpdateSecureSettings() {
    158         when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
    159         Settings.Secure.putInt(mContext.getContentResolver(),
    160                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_BATTERY_SAVING);
    161 
    162         mEnabler.setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
    163 
    164         assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
    165                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_BATTERY_SAVING))
    166                 .isEqualTo(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
    167     }
    168 
    169     @Test
    170     public void setLocationMode_notRestricted_shouldRefreshLocation() {
    171         when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
    172         Settings.Secure.putInt(mContext.getContentResolver(),
    173                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_BATTERY_SAVING);
    174 
    175         mEnabler.setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
    176 
    177         verify(mEnabler).refreshLocationMode();
    178     }
    179 
    180     @Test
    181     public void setLocationMode_notRestricted_shouldBroadcastUpdateAndSetChanger() {
    182         when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
    183         Settings.Secure.putInt(mContext.getContentResolver(),
    184                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_BATTERY_SAVING);
    185         mEnabler.setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
    186 
    187         verify(mContext).sendBroadcastAsUser(
    188                 argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)),
    189                 eq(UserHandle.of(ActivityManager.getCurrentUser())),
    190                 eq(WRITE_SECURE_SETTINGS));
    191         assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
    192                 Settings.Secure.LOCATION_CHANGER, Settings.Secure.LOCATION_CHANGER_UNKNOWN))
    193                 .isEqualTo(Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
    194     }
    195 
    196     @Test
    197     public void setLocationEnabled_notRestricted_shouldRefreshLocation() {
    198         when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
    199         Settings.Secure.putInt(mContext.getContentResolver(),
    200             Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
    201         mEnabler.setLocationEnabled(true);
    202 
    203         verify(mEnabler).refreshLocationMode();
    204     }
    205 
    206     @Test
    207     public void setLocationEnabled_notRestricted_shouldBroadcastUpdateAndSetChanger() {
    208         when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
    209         Settings.Secure.putInt(mContext.getContentResolver(),
    210             Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
    211         mEnabler.setLocationEnabled(true);
    212 
    213         verify(mContext).sendBroadcastAsUser(
    214             argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)),
    215             eq(UserHandle.of(ActivityManager.getCurrentUser())),
    216             eq(WRITE_SECURE_SETTINGS));
    217         assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
    218                 Settings.Secure.LOCATION_CHANGER, Settings.Secure.LOCATION_CHANGER_UNKNOWN))
    219                 .isEqualTo(Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
    220     }
    221 
    222     @Test
    223     public void isManagedProfileRestrictedByBase_notManagedProfile_shouldReturnFalse() {
    224         assertThat(mEnabler.isManagedProfileRestrictedByBase()).isFalse();
    225     }
    226 
    227     @Test
    228     public void isManagedProfileRestrictedByBase_notRestricted_shouldReturnFalse() {
    229         mockManagedProfile();
    230         doReturn(false).when(mEnabler).hasShareLocationRestriction(anyInt());
    231 
    232         assertThat(mEnabler.isManagedProfileRestrictedByBase()).isFalse();
    233     }
    234 
    235     @Test
    236     public void isManagedProfileRestrictedByBase_hasManagedProfile_shouldReturnFalse() {
    237         mockManagedProfile();
    238         doReturn(true).when(mEnabler).hasShareLocationRestriction(anyInt());
    239 
    240         assertThat(mEnabler.isManagedProfileRestrictedByBase()).isTrue();
    241     }
    242 
    243     @Test
    244     public void setRestriction_getShareLocationEnforcedAdmin_shouldReturnEnforcedAdmin() {
    245         int userId = UserHandle.myUserId();
    246         List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
    247         // Add two enforcing users so that RestrictedLockUtils.checkIfRestrictionEnforced returns
    248         // non-null.
    249         enforcingUsers.add(new UserManager.EnforcingUser(userId,
    250                 UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
    251         enforcingUsers.add(new UserManager.EnforcingUser(userId,
    252                 UserManager.RESTRICTION_SOURCE_PROFILE_OWNER));
    253         when(mUserManager.getUserRestrictionSources(
    254                 UserManager.DISALLOW_CONFIG_LOCATION, UserHandle.of(userId)))
    255                 .thenReturn(enforcingUsers);
    256 
    257         assertThat(mEnabler.getShareLocationEnforcedAdmin(userId) != null).isTrue();
    258     }
    259 
    260     private void mockManagedProfile() {
    261         final List<UserHandle> userProfiles = new ArrayList<>();
    262         final UserHandle userHandle = mock(UserHandle.class);
    263         when(userHandle.getIdentifier()).thenReturn(5);
    264         userProfiles.add(userHandle);
    265         when(mUserManager.getUserProfiles()).thenReturn(userProfiles);
    266         when(mUserManager.getUserHandle()).thenReturn(1);
    267         when(mUserManager.getUserInfo(5))
    268                 .thenReturn(new UserInfo(5, "user 5", UserInfo.FLAG_MANAGED_PROFILE));
    269     }
    270 
    271     private static ArgumentMatcher<Intent> actionMatches(String expected) {
    272         return intent -> TextUtils.equals(expected, intent.getAction());
    273     }
    274 
    275     @Implements(value = LocationManagerWrapper.class)
    276     public static class ShadowLocationManagerWrapper {
    277 
    278         @Implementation
    279         public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
    280             // Do nothing
    281         }
    282     }
    283 }
    284