1 /* 2 * Copyright (C) 2022 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 17 package com.android.settings.vpn2; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.anyString; 24 import static org.mockito.Mockito.doNothing; 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.never; 27 import static org.mockito.Mockito.spy; 28 import static org.mockito.Mockito.verify; 29 import static org.mockito.Mockito.when; 30 31 import android.app.AppOpsManager; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.pm.ApplicationInfo; 35 import android.content.pm.PackageManager; 36 import android.os.Looper; 37 import android.os.UserHandle; 38 import android.text.TextUtils; 39 import android.util.ArraySet; 40 41 import androidx.preference.Preference; 42 import androidx.preference.PreferenceCategory; 43 import androidx.preference.PreferenceGroup; 44 import androidx.preference.PreferenceManager; 45 import androidx.preference.PreferenceScreen; 46 import androidx.test.annotation.UiThreadTest; 47 import androidx.test.core.app.ApplicationProvider; 48 import androidx.test.ext.junit.runners.AndroidJUnit4; 49 50 import com.android.settings.testutils.FakeFeatureFactory; 51 52 import org.junit.Before; 53 import org.junit.Rule; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 import org.mockito.ArgumentCaptor; 57 import org.mockito.Mock; 58 import org.mockito.junit.MockitoJUnit; 59 import org.mockito.junit.MockitoRule; 60 61 import java.util.ArrayList; 62 import java.util.List; 63 import java.util.Set; 64 65 @RunWith(AndroidJUnit4.class) 66 public class VpnSettingsTest { 67 private static final int USER_ID_1 = UserHandle.USER_NULL; 68 private static final String VPN_GROUP_KEY = "vpn_group"; 69 private static final String VPN_GROUP_TITLE = "vpn_group_title"; 70 private static final String VPN_PACKAGE_NAME = "vpn.package.name"; 71 private static final String VPN_LAUNCH_INTENT = "vpn.action"; 72 private static final String ADVANCED_VPN_GROUP_KEY = "advanced_vpn_group"; 73 private static final String ADVANCED_VPN_GROUP_TITLE = "advanced_vpn_group_title"; 74 private static final String ADVANCED_VPN_PACKAGE_NAME = "advanced.vpn.package.name"; 75 private static final String ADVANCED_VPN_LAUNCH_INTENT = "advanced.vpn.action"; 76 77 private final Intent mVpnIntent = new Intent().setAction(VPN_LAUNCH_INTENT); 78 private final Intent mAdvancedVpnIntent = new Intent().setAction(ADVANCED_VPN_LAUNCH_INTENT); 79 80 @Rule 81 public final MockitoRule mMockitoRule = MockitoJUnit.rule(); 82 83 @Mock 84 private AppOpsManager mAppOpsManager; 85 @Mock 86 private PackageManager mPackageManager; 87 88 private VpnSettings mVpnSettings; 89 private Context mContext; 90 private PreferenceManager mPreferenceManager; 91 private PreferenceScreen mPreferenceScreen; 92 private PreferenceGroup mAdvancedVpnGroup; 93 private PreferenceGroup mVpnGroup; 94 private FakeFeatureFactory mFakeFeatureFactory; 95 96 @Before 97 @UiThreadTest setUp()98 public void setUp() throws PackageManager.NameNotFoundException { 99 if (Looper.myLooper() == null) { 100 Looper.prepare(); 101 } 102 103 mVpnSettings = spy(new VpnSettings()); 104 mContext = spy(ApplicationProvider.getApplicationContext()); 105 mAdvancedVpnGroup = spy(new PreferenceCategory(mContext)); 106 mVpnGroup = spy(new PreferenceCategory(mContext)); 107 mAdvancedVpnGroup.setKey(ADVANCED_VPN_GROUP_KEY); 108 mVpnGroup.setKey(VPN_GROUP_KEY); 109 mPreferenceManager = new PreferenceManager(mContext); 110 mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext); 111 mPreferenceScreen.addPreference(mAdvancedVpnGroup); 112 mPreferenceScreen.addPreference(mVpnGroup); 113 mFakeFeatureFactory = FakeFeatureFactory.setupForTest(); 114 mVpnSettings.init(mPreferenceScreen, mFakeFeatureFactory.getAdvancedVpnFeatureProvider()); 115 116 when(mVpnSettings.getContext()).thenReturn(mContext); 117 when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider 118 .getAdvancedVpnPreferenceGroupTitle(mContext)).thenReturn(ADVANCED_VPN_GROUP_TITLE); 119 when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getVpnPreferenceGroupTitle(mContext)) 120 .thenReturn(VPN_GROUP_TITLE); 121 when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getAdvancedVpnPackageName()) 122 .thenReturn(ADVANCED_VPN_PACKAGE_NAME); 123 when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any())) 124 .thenReturn(true); 125 when(mContext.getPackageManager()).thenReturn(mPackageManager); 126 doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt()); 127 doReturn(mContext).when(mContext).createPackageContextAsUser(any(), anyInt(), any()); 128 doReturn(mPreferenceManager).when(mVpnGroup).getPreferenceManager(); 129 doReturn(mPreferenceManager).when(mAdvancedVpnGroup).getPreferenceManager(); 130 } 131 132 @Test 133 @UiThreadTest setShownAdvancedPreferences_hasGeneralVpn_returnsVpnCountAs1()134 public void setShownAdvancedPreferences_hasGeneralVpn_returnsVpnCountAs1() { 135 Set<Preference> updates = new ArraySet<>(); 136 AppPreference pref = 137 spy(new AppPreference(mContext, USER_ID_1, VPN_PACKAGE_NAME)); 138 updates.add(pref); 139 140 mVpnSettings.setShownAdvancedPreferences(updates); 141 142 assertThat(mVpnGroup.getPreferenceCount()).isEqualTo(1); 143 assertThat(mVpnGroup.isVisible()).isTrue(); 144 assertThat(mAdvancedVpnGroup.isVisible()).isFalse(); 145 } 146 147 @Test 148 @UiThreadTest setShownAdvancedPreferences_hasAdvancedVpn_returnsAdvancedVpnCountAs1()149 public void setShownAdvancedPreferences_hasAdvancedVpn_returnsAdvancedVpnCountAs1() { 150 Set<Preference> updates = new ArraySet<>(); 151 AppPreference pref = 152 spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_PACKAGE_NAME)); 153 updates.add(pref); 154 155 mVpnSettings.setShownAdvancedPreferences(updates); 156 157 assertThat(mAdvancedVpnGroup.getPreferenceCount()).isEqualTo(1); 158 assertThat(mAdvancedVpnGroup.isVisible()).isTrue(); 159 assertThat(mVpnGroup.isVisible()).isFalse(); 160 } 161 162 @Test 163 @UiThreadTest setShownAdvancedPreferences_noVpn_returnsEmpty()164 public void setShownAdvancedPreferences_noVpn_returnsEmpty() { 165 Set<Preference> updates = new ArraySet<>(); 166 167 mVpnSettings.setShownAdvancedPreferences(updates); 168 169 assertThat(mAdvancedVpnGroup.getPreferenceCount()).isEqualTo(0); 170 assertThat(mVpnGroup.getPreferenceCount()).isEqualTo(0); 171 assertThat(mAdvancedVpnGroup.isVisible()).isFalse(); 172 assertThat(mVpnGroup.isVisible()).isFalse(); 173 } 174 175 @Test 176 @UiThreadTest getVpnApps_isAdvancedVpn_returnsOne()177 public void getVpnApps_isAdvancedVpn_returnsOne() throws Exception { 178 ApplicationInfo info = new ApplicationInfo(); 179 info.uid = 1111; 180 when(mPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(info); 181 182 assertThat(VpnSettings.getVpnApps(mContext, /* includeProfiles= */ false, 183 mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), 184 mAppOpsManager).size()).isEqualTo(1); 185 } 186 187 @Test getVpnApps_isNotAdvancedVpn_returnsEmpty()188 public void getVpnApps_isNotAdvancedVpn_returnsEmpty() { 189 int uid = 1111; 190 List<AppOpsManager.OpEntry> opEntries = new ArrayList<>(); 191 List<AppOpsManager.PackageOps> apps = new ArrayList<>(); 192 AppOpsManager.PackageOps packageOps = 193 new AppOpsManager.PackageOps(VPN_PACKAGE_NAME, uid, opEntries); 194 apps.add(packageOps); 195 when(mAppOpsManager.getPackagesForOps((int[]) any())).thenReturn(apps); 196 when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any())) 197 .thenReturn(false); 198 199 assertThat(VpnSettings.getVpnApps(mContext, /* includeProfiles= */ false, 200 mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), 201 mAppOpsManager)).isEmpty(); 202 } 203 204 @Test 205 @UiThreadTest clickVpn_VpnConnected_doesNotStartVpnLaunchIntent()206 public void clickVpn_VpnConnected_doesNotStartVpnLaunchIntent() 207 throws PackageManager.NameNotFoundException { 208 Set<Preference> updates = new ArraySet<>(); 209 AppPreference pref = spy(new AppPreference(mContext, USER_ID_1, VPN_PACKAGE_NAME)); 210 pref.setState(AppPreference.STATE_CONNECTED); 211 updates.add(pref); 212 when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext); 213 when(mContext.getPackageManager()).thenReturn(mPackageManager); 214 when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mVpnIntent); 215 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 216 doNothing().when(mContext).startActivityAsUser(captor.capture(), any()); 217 mVpnSettings.setShownPreferences(updates); 218 219 mVpnSettings.onPreferenceClick(pref); 220 221 verify(mContext, never()).startActivityAsUser(any(), any()); 222 } 223 224 @Test 225 @UiThreadTest clickVpn_VpnDisconnected_startsVpnLaunchIntent()226 public void clickVpn_VpnDisconnected_startsVpnLaunchIntent() 227 throws PackageManager.NameNotFoundException { 228 Set<Preference> updates = new ArraySet<>(); 229 AppPreference pref = spy(new AppPreference(mContext, USER_ID_1, VPN_PACKAGE_NAME)); 230 pref.setState(AppPreference.STATE_DISCONNECTED); 231 updates.add(pref); 232 when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext); 233 when(mContext.getPackageManager()).thenReturn(mPackageManager); 234 when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mVpnIntent); 235 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 236 doNothing().when(mContext).startActivityAsUser(captor.capture(), any()); 237 mVpnSettings.setShownPreferences(updates); 238 239 mVpnSettings.onPreferenceClick(pref); 240 241 verify(mContext).startActivityAsUser(captor.capture(), any()); 242 assertThat(TextUtils.equals(captor.getValue().getAction(), 243 VPN_LAUNCH_INTENT)).isTrue(); 244 } 245 246 @Test 247 @UiThreadTest clickAdvancedVpn_VpnConnectedDisconnectDialogDisabled_startsAppLaunchIntent()248 public void clickAdvancedVpn_VpnConnectedDisconnectDialogDisabled_startsAppLaunchIntent() 249 throws PackageManager.NameNotFoundException { 250 Set<Preference> updates = new ArraySet<>(); 251 AppPreference pref = 252 spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_PACKAGE_NAME)); 253 pref.setState(AppPreference.STATE_CONNECTED); 254 updates.add(pref); 255 when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isDisconnectDialogEnabled()) 256 .thenReturn(false); 257 when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext); 258 when(mContext.getPackageManager()).thenReturn(mPackageManager); 259 when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mAdvancedVpnIntent); 260 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 261 doNothing().when(mContext).startActivityAsUser(captor.capture(), any()); 262 mVpnSettings.setShownAdvancedPreferences(updates); 263 264 mVpnSettings.onPreferenceClick(pref); 265 266 verify(mContext).startActivityAsUser(captor.capture(), any()); 267 assertThat(TextUtils.equals(captor.getValue().getAction(), 268 ADVANCED_VPN_LAUNCH_INTENT)).isTrue(); 269 } 270 271 @Test 272 @UiThreadTest clickAdvancedVpn_VpnConnectedDisconnectDialogEnabled_doesNotStartAppLaunchIntent()273 public void clickAdvancedVpn_VpnConnectedDisconnectDialogEnabled_doesNotStartAppLaunchIntent() 274 throws PackageManager.NameNotFoundException { 275 Set<Preference> updates = new ArraySet<>(); 276 AppPreference pref = 277 spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_PACKAGE_NAME)); 278 pref.setState(AppPreference.STATE_CONNECTED); 279 updates.add(pref); 280 when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isDisconnectDialogEnabled()) 281 .thenReturn(true); 282 when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext); 283 when(mContext.getPackageManager()).thenReturn(mPackageManager); 284 when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mAdvancedVpnIntent); 285 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 286 doNothing().when(mContext).startActivityAsUser(captor.capture(), any()); 287 mVpnSettings.setShownAdvancedPreferences(updates); 288 289 mVpnSettings.onPreferenceClick(pref); 290 291 verify(mContext, never()).startActivityAsUser(any(), any()); 292 } 293 } 294