1 package com.android.settings.development;
2 
3 import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes.REQUEST_MOCK_LOCATION_APP;
4 
5 import static com.google.common.truth.Truth.assertThat;
6 
7 import static org.mockito.ArgumentMatchers.any;
8 import static org.mockito.ArgumentMatchers.anyInt;
9 import static org.mockito.ArgumentMatchers.anyString;
10 import static org.mockito.ArgumentMatchers.eq;
11 import static org.mockito.Mockito.spy;
12 import static org.mockito.Mockito.verify;
13 import static org.mockito.Mockito.when;
14 
15 import android.app.Activity;
16 import android.app.AppOpsManager;
17 import android.app.AppOpsManager.OpEntry;
18 import android.content.Context;
19 import android.content.Intent;
20 import android.content.pm.ApplicationInfo;
21 import android.content.pm.PackageManager;
22 
23 import androidx.preference.Preference;
24 import androidx.preference.PreferenceScreen;
25 
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.mockito.Mock;
30 import org.mockito.MockitoAnnotations;
31 import org.robolectric.RobolectricTestRunner;
32 import org.robolectric.RuntimeEnvironment;
33 import org.robolectric.util.ReflectionHelpers;
34 
35 import java.util.Collections;
36 
37 @RunWith(RobolectricTestRunner.class)
38 public class MockLocationAppPreferenceControllerTest {
39 
40     @Mock
41     private DevelopmentSettingsDashboardFragment mFragment;
42     @Mock
43     private AppOpsManager mAppOpsManager;
44     @Mock
45     private PackageManager mPackageManager;
46     @Mock
47     private Preference mPreference;
48     @Mock
49     private PreferenceScreen mScreen;
50 
51     @Mock
52     private ApplicationInfo mApplicationInfo;
53 
54     private Context mContext;
55     private MockLocationAppPreferenceController mController;
56 
57     @Before
setup()58     public void setup() {
59         MockitoAnnotations.initMocks(this);
60         mContext = RuntimeEnvironment.application;
61         mController = spy(new MockLocationAppPreferenceController(mContext, mFragment));
62         ReflectionHelpers.setField(mController, "mAppsOpsManager", mAppOpsManager);
63         ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
64         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
65         mController.displayPreference(mScreen);
66     }
67 
68     @Test
updateState_foobarAppSelected_shouldSetSummaryToFoobar()69     public void updateState_foobarAppSelected_shouldSetSummaryToFoobar() {
70         final String appName = "foobar";
71 
72         final AppOpsManager.PackageOps packageOps =
73                 new AppOpsManager.PackageOps(appName, 0,
74                         Collections.singletonList(createOpEntry(AppOpsManager.MODE_ALLOWED)));
75         when(mAppOpsManager.getPackagesForOps(any(int[].class))).thenReturn(
76                 Collections.singletonList(packageOps));
77 
78         mController.updateState(mPreference);
79 
80         verify(mPreference).setSummary(mContext.getString(
81                 com.android.settingslib.R.string.mock_location_app_set, appName));
82     }
83 
84     @Test
updateState_noAppSelected_shouldSetSummaryToDefault()85     public void updateState_noAppSelected_shouldSetSummaryToDefault() {
86         when(mAppOpsManager.getPackagesForOps(any(int[].class)))
87                 .thenReturn(Collections.emptyList());
88 
89         mController.updateState(mPreference);
90 
91         verify(mPreference).setSummary(mContext.getString(
92                 com.android.settingslib.R.string.mock_location_app_not_set));
93     }
94 
95     @Test
onActivityResult_fooPrevAppBarNewApp_shouldRemoveFooAndSetBarAsMockLocationApp()96     public void onActivityResult_fooPrevAppBarNewApp_shouldRemoveFooAndSetBarAsMockLocationApp()
97             throws PackageManager.NameNotFoundException {
98         final String prevAppName = "foo";
99         final String newAppName = "bar";
100         final Intent intent = new Intent();
101         intent.setAction(newAppName);
102         final AppOpsManager.PackageOps packageOps = new AppOpsManager.PackageOps(prevAppName, 0,
103                 Collections.singletonList(createOpEntry(AppOpsManager.MODE_ALLOWED)));
104 
105         when(mAppOpsManager.getPackagesForOps(any(int[].class)))
106                 .thenReturn(Collections.singletonList(packageOps));
107         when(mPackageManager.getApplicationInfo(anyString(),
108                 eq(PackageManager.MATCH_DISABLED_COMPONENTS))).thenReturn(mApplicationInfo);
109 
110         final boolean handled =
111                 mController.onActivityResult(REQUEST_MOCK_LOCATION_APP, Activity.RESULT_OK, intent);
112 
113         assertThat(handled).isTrue();
114         verify(mAppOpsManager).setMode(anyInt(), anyInt(), eq(newAppName),
115                 eq(AppOpsManager.MODE_ALLOWED));
116         verify(mAppOpsManager).setMode(anyInt(), anyInt(), eq(prevAppName),
117                 eq(AppOpsManager.MODE_ERRORED));
118     }
119 
120     @Test
onActivityResult_incorrectCode_shouldReturnFalse()121     public void onActivityResult_incorrectCode_shouldReturnFalse() {
122         final boolean handled = mController.onActivityResult(30983150 /* request code */,
123                 Activity.RESULT_OK, null /* intent */);
124 
125         assertThat(handled).isFalse();
126     }
127 
128     @Test
handlePreferenceTreeClick_samePreferenceKey_shouldLaunchActivity()129     public void handlePreferenceTreeClick_samePreferenceKey_shouldLaunchActivity() {
130         final String preferenceKey = mController.getPreferenceKey();
131         when(mPreference.getKey()).thenReturn(preferenceKey);
132 
133         final boolean handled = mController.handlePreferenceTreeClick(mPreference);
134 
135         assertThat(handled).isTrue();
136         verify(mFragment).startActivityForResult(any(), eq(REQUEST_MOCK_LOCATION_APP));
137     }
138 
139     @Test
handlePreferenceTreeClick_incorrectPreferenceKey_shouldReturnFalse()140     public void handlePreferenceTreeClick_incorrectPreferenceKey_shouldReturnFalse() {
141         when(mPreference.getKey()).thenReturn("SomeRandomKey");
142 
143         assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
144     }
145 
146     @Test
onDeveloperOptionsDisabled_currentMockLocationApp_shouldBeNull()147     public void onDeveloperOptionsDisabled_currentMockLocationApp_shouldBeNull() {
148         mController.onDeveloperOptionsDisabled();
149 
150         final String appName = mController.getCurrentMockLocationApp();
151 
152         assertThat(appName).isNull();
153     }
154 
createOpEntry(int opMode)155     private AppOpsManager.OpEntry createOpEntry(int opMode) {
156         return new OpEntry(0, opMode, Collections.emptyMap());
157     }
158 }
159