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 com.android.settings.R;
27 
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.mockito.Mock;
32 import org.mockito.MockitoAnnotations;
33 import org.robolectric.RobolectricTestRunner;
34 import org.robolectric.RuntimeEnvironment;
35 import org.robolectric.util.ReflectionHelpers;
36 
37 import java.util.Collections;
38 
39 @RunWith(RobolectricTestRunner.class)
40 public class MockLocationAppPreferenceControllerTest {
41 
42     @Mock
43     private DevelopmentSettingsDashboardFragment mFragment;
44     @Mock
45     private AppOpsManager mAppOpsManager;
46     @Mock
47     private PackageManager mPackageManager;
48     @Mock
49     private Preference mPreference;
50     @Mock
51     private PreferenceScreen mScreen;
52 
53     @Mock
54     private ApplicationInfo mApplicationInfo;
55 
56     private Context mContext;
57     private MockLocationAppPreferenceController mController;
58 
59     @Before
setup()60     public void setup() {
61         MockitoAnnotations.initMocks(this);
62         mContext = RuntimeEnvironment.application;
63         mController = spy(new MockLocationAppPreferenceController(mContext, mFragment));
64         ReflectionHelpers.setField(mController, "mAppsOpsManager", mAppOpsManager);
65         ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
66         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
67         mController.displayPreference(mScreen);
68     }
69 
70     @Test
updateState_foobarAppSelected_shouldSetSummaryToFoobar()71     public void updateState_foobarAppSelected_shouldSetSummaryToFoobar() {
72         final String appName = "foobar";
73 
74         final AppOpsManager.PackageOps packageOps =
75                 new AppOpsManager.PackageOps(appName, 0,
76                         Collections.singletonList(createOpEntry(AppOpsManager.MODE_ALLOWED)));
77         when(mAppOpsManager.getPackagesForOps(any(int[].class))).thenReturn(
78                 Collections.singletonList(packageOps));
79 
80         mController.updateState(mPreference);
81 
82         verify(mPreference).setSummary(mContext.getString(R.string.mock_location_app_set, appName));
83     }
84 
85     @Test
updateState_noAppSelected_shouldSetSummaryToDefault()86     public void updateState_noAppSelected_shouldSetSummaryToDefault() {
87         when(mAppOpsManager.getPackagesForOps(any(int[].class)))
88                 .thenReturn(Collections.emptyList());
89 
90         mController.updateState(mPreference);
91 
92         verify(mPreference).setSummary(mContext.getString(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