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