Loading src/com/android/settings/vpn2/AdvancedVpnFeatureProvider.java +5 −0 Original line number Diff line number Diff line Loading @@ -42,4 +42,9 @@ public interface AdvancedVpnFeatureProvider { * Returns the title of vpn preference group. */ String getVpnPreferenceGroupTitle(Context context); /** * Returns {@code true} advanced vpn is removable. */ boolean isAdvancedVpnRemovable(); } src/com/android/settings/vpn2/AdvancedVpnFeatureProviderImpl.java +5 −0 Original line number Diff line number Diff line Loading @@ -41,4 +41,9 @@ public class AdvancedVpnFeatureProviderImpl implements AdvancedVpnFeatureProvide public String getVpnPreferenceGroupTitle(Context context) { return null; } @Override public boolean isAdvancedVpnRemovable() { return true; } } src/com/android/settings/vpn2/AppManagementFragment.java +21 −1 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedPreference; Loading @@ -71,6 +72,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment private PackageManager mPackageManager; private DevicePolicyManager mDevicePolicyManager; private VpnManager mVpnManager; private AdvancedVpnFeatureProvider mFeatureProvider; // VPN app info private final int mUserId = UserHandle.myUserId(); Loading Loading @@ -122,6 +124,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment mPackageManager = getContext().getPackageManager(); mDevicePolicyManager = getContext().getSystemService(DevicePolicyManager.class); mVpnManager = getContext().getSystemService(VpnManager.class); mFeatureProvider = FeatureFactory.getFactory(getContext()).getAdvancedVpnFeatureProvider(); mPreferenceAlwaysOn = (RestrictedSwitchPreference) findPreference(KEY_ALWAYS_ON_VPN); mPreferenceLockdown = (RestrictedSwitchPreference) findPreference(KEY_LOCKDOWN_VPN); Loading Loading @@ -283,7 +286,16 @@ public class AppManagementFragment extends SettingsPreferenceFragment } } private void updateRestrictedViews() { @VisibleForTesting void updateRestrictedViews() { if (mFeatureProvider.isAdvancedVpnSupported(getContext()) && !mFeatureProvider.isAdvancedVpnRemovable() && TextUtils.equals(mPackageName, mFeatureProvider.getAdvancedVpnPackageName())) { mPreferenceForget.setVisible(false); } else { mPreferenceForget.setVisible(true); } if (isAdded()) { mPreferenceAlwaysOn.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN, mUserId); Loading Loading @@ -314,6 +326,14 @@ public class AppManagementFragment extends SettingsPreferenceFragment } } @VisibleForTesting void init(String packageName, AdvancedVpnFeatureProvider featureProvider, RestrictedPreference preference) { mPackageName = packageName; mFeatureProvider = featureProvider; mPreferenceForget = preference; } private String getAlwaysOnVpnPackage() { return mVpnManager.getAlwaysOnVpnPackageForUser(mUserId); } Loading src/com/android/settings/vpn2/VpnSettings.java +18 −5 Original line number Diff line number Diff line Loading @@ -241,7 +241,8 @@ public class VpnSettings extends RestrictedSettingsFragment implements // Run heavy RPCs before switching to UI thread final List<VpnProfile> vpnProfiles = loadVpnProfiles(); final List<AppVpnInfo> vpnApps = getVpnApps(context, /* includeProfiles */ true); final List<AppVpnInfo> vpnApps = getVpnApps(context, /* includeProfiles */ true, mFeatureProvider); final Map<String, LegacyVpnInfo> connectedLegacyVpns = getConnectedLegacyVpns(); final Set<AppVpnInfo> connectedAppVpns = getConnectedAppVpns(); Loading Loading @@ -571,7 +572,15 @@ public class VpnSettings extends RestrictedSettingsFragment implements return result; } static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles) { static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles, AdvancedVpnFeatureProvider featureProvider) { return getVpnApps(context, includeProfiles, featureProvider, context.getSystemService(AppOpsManager.class)); } @VisibleForTesting static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles, AdvancedVpnFeatureProvider featureProvider, AppOpsManager aom) { List<AppVpnInfo> result = Lists.newArrayList(); final Set<Integer> profileIds; Loading @@ -584,8 +593,6 @@ public class VpnSettings extends RestrictedSettingsFragment implements profileIds = Collections.singleton(UserHandle.myUserId()); } // Fetch VPN-enabled apps from AppOps. AppOpsManager aom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); List<AppOpsManager.PackageOps> apps = aom.getPackagesForOps(new int[] {OP_ACTIVATE_VPN, OP_ACTIVATE_PLATFORM_VPN}); if (apps != null) { Loading @@ -603,7 +610,7 @@ public class VpnSettings extends RestrictedSettingsFragment implements allowed = true; } } if (allowed) { if (allowed || isAdvancedVpn(featureProvider, pkg.getPackageName(), context)) { result.add(new AppVpnInfo(userId, pkg.getPackageName())); } } Loading @@ -613,6 +620,12 @@ public class VpnSettings extends RestrictedSettingsFragment implements return result; } private static boolean isAdvancedVpn(AdvancedVpnFeatureProvider featureProvider, String packageName, Context context) { return featureProvider.isAdvancedVpnSupported(context) && TextUtils.equals(packageName, featureProvider.getAdvancedVpnPackageName()); } private static List<VpnProfile> loadVpnProfiles() { final ArrayList<VpnProfile> result = Lists.newArrayList(); Loading tests/unit/src/com/android/settings/vpn2/AppManagementFragmentTest.java 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.vpn2; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; import android.os.Looper; import androidx.test.annotation.UiThreadTest; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settingslib.RestrictedPreference; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @RunWith(AndroidJUnit4.class) public class AppManagementFragmentTest { private static final String FAKE_PACKAGE_NAME = "com.fake.package.name"; private static final String ADVANCED_VPN_GROUP_PACKAGE_NAME = "com.advanced.package.name"; @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); private AppManagementFragment mFragment; private Context mContext; private FakeFeatureFactory mFakeFeatureFactory; private RestrictedPreference mPreferenceForget; @Before @UiThreadTest public void setUp() { if (Looper.myLooper() == null) { Looper.prepare(); } mFragment = spy(new AppManagementFragment()); mContext = spy(ApplicationProvider.getApplicationContext()); mPreferenceForget = new RestrictedPreference(mContext); mFakeFeatureFactory = FakeFeatureFactory.setupForTest(); mFragment.init(ADVANCED_VPN_GROUP_PACKAGE_NAME, mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mPreferenceForget); when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getAdvancedVpnPackageName()) .thenReturn(ADVANCED_VPN_GROUP_PACKAGE_NAME); when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any())) .thenReturn(true); } @Test public void updateRestrictedViews_isAdvancedVpn_hidesForgetPreference() { when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnRemovable()) .thenReturn(false); mFragment.updateRestrictedViews(); assertThat(mPreferenceForget.isVisible()).isFalse(); } @Test public void updateRestrictedViews_isNotAdvancedVpn_showsForgetPreference() { when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnRemovable()) .thenReturn(false); mFragment.init(FAKE_PACKAGE_NAME, mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mPreferenceForget); mFragment.updateRestrictedViews(); assertThat(mPreferenceForget.isVisible()).isTrue(); } @Test public void updateRestrictedViews_isAdvancedVpnRemovable_showsForgetPreference() { when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnRemovable()) .thenReturn(true); mFragment.init(FAKE_PACKAGE_NAME, mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mPreferenceForget); mFragment.updateRestrictedViews(); assertThat(mPreferenceForget.isVisible()).isTrue(); } } Loading
src/com/android/settings/vpn2/AdvancedVpnFeatureProvider.java +5 −0 Original line number Diff line number Diff line Loading @@ -42,4 +42,9 @@ public interface AdvancedVpnFeatureProvider { * Returns the title of vpn preference group. */ String getVpnPreferenceGroupTitle(Context context); /** * Returns {@code true} advanced vpn is removable. */ boolean isAdvancedVpnRemovable(); }
src/com/android/settings/vpn2/AdvancedVpnFeatureProviderImpl.java +5 −0 Original line number Diff line number Diff line Loading @@ -41,4 +41,9 @@ public class AdvancedVpnFeatureProviderImpl implements AdvancedVpnFeatureProvide public String getVpnPreferenceGroupTitle(Context context) { return null; } @Override public boolean isAdvancedVpnRemovable() { return true; } }
src/com/android/settings/vpn2/AppManagementFragment.java +21 −1 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import com.android.settingslib.RestrictedPreference; Loading @@ -71,6 +72,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment private PackageManager mPackageManager; private DevicePolicyManager mDevicePolicyManager; private VpnManager mVpnManager; private AdvancedVpnFeatureProvider mFeatureProvider; // VPN app info private final int mUserId = UserHandle.myUserId(); Loading Loading @@ -122,6 +124,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment mPackageManager = getContext().getPackageManager(); mDevicePolicyManager = getContext().getSystemService(DevicePolicyManager.class); mVpnManager = getContext().getSystemService(VpnManager.class); mFeatureProvider = FeatureFactory.getFactory(getContext()).getAdvancedVpnFeatureProvider(); mPreferenceAlwaysOn = (RestrictedSwitchPreference) findPreference(KEY_ALWAYS_ON_VPN); mPreferenceLockdown = (RestrictedSwitchPreference) findPreference(KEY_LOCKDOWN_VPN); Loading Loading @@ -283,7 +286,16 @@ public class AppManagementFragment extends SettingsPreferenceFragment } } private void updateRestrictedViews() { @VisibleForTesting void updateRestrictedViews() { if (mFeatureProvider.isAdvancedVpnSupported(getContext()) && !mFeatureProvider.isAdvancedVpnRemovable() && TextUtils.equals(mPackageName, mFeatureProvider.getAdvancedVpnPackageName())) { mPreferenceForget.setVisible(false); } else { mPreferenceForget.setVisible(true); } if (isAdded()) { mPreferenceAlwaysOn.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN, mUserId); Loading Loading @@ -314,6 +326,14 @@ public class AppManagementFragment extends SettingsPreferenceFragment } } @VisibleForTesting void init(String packageName, AdvancedVpnFeatureProvider featureProvider, RestrictedPreference preference) { mPackageName = packageName; mFeatureProvider = featureProvider; mPreferenceForget = preference; } private String getAlwaysOnVpnPackage() { return mVpnManager.getAlwaysOnVpnPackageForUser(mUserId); } Loading
src/com/android/settings/vpn2/VpnSettings.java +18 −5 Original line number Diff line number Diff line Loading @@ -241,7 +241,8 @@ public class VpnSettings extends RestrictedSettingsFragment implements // Run heavy RPCs before switching to UI thread final List<VpnProfile> vpnProfiles = loadVpnProfiles(); final List<AppVpnInfo> vpnApps = getVpnApps(context, /* includeProfiles */ true); final List<AppVpnInfo> vpnApps = getVpnApps(context, /* includeProfiles */ true, mFeatureProvider); final Map<String, LegacyVpnInfo> connectedLegacyVpns = getConnectedLegacyVpns(); final Set<AppVpnInfo> connectedAppVpns = getConnectedAppVpns(); Loading Loading @@ -571,7 +572,15 @@ public class VpnSettings extends RestrictedSettingsFragment implements return result; } static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles) { static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles, AdvancedVpnFeatureProvider featureProvider) { return getVpnApps(context, includeProfiles, featureProvider, context.getSystemService(AppOpsManager.class)); } @VisibleForTesting static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles, AdvancedVpnFeatureProvider featureProvider, AppOpsManager aom) { List<AppVpnInfo> result = Lists.newArrayList(); final Set<Integer> profileIds; Loading @@ -584,8 +593,6 @@ public class VpnSettings extends RestrictedSettingsFragment implements profileIds = Collections.singleton(UserHandle.myUserId()); } // Fetch VPN-enabled apps from AppOps. AppOpsManager aom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); List<AppOpsManager.PackageOps> apps = aom.getPackagesForOps(new int[] {OP_ACTIVATE_VPN, OP_ACTIVATE_PLATFORM_VPN}); if (apps != null) { Loading @@ -603,7 +610,7 @@ public class VpnSettings extends RestrictedSettingsFragment implements allowed = true; } } if (allowed) { if (allowed || isAdvancedVpn(featureProvider, pkg.getPackageName(), context)) { result.add(new AppVpnInfo(userId, pkg.getPackageName())); } } Loading @@ -613,6 +620,12 @@ public class VpnSettings extends RestrictedSettingsFragment implements return result; } private static boolean isAdvancedVpn(AdvancedVpnFeatureProvider featureProvider, String packageName, Context context) { return featureProvider.isAdvancedVpnSupported(context) && TextUtils.equals(packageName, featureProvider.getAdvancedVpnPackageName()); } private static List<VpnProfile> loadVpnProfiles() { final ArrayList<VpnProfile> result = Lists.newArrayList(); Loading
tests/unit/src/com/android/settings/vpn2/AppManagementFragmentTest.java 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.vpn2; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; import android.os.Looper; import androidx.test.annotation.UiThreadTest; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settingslib.RestrictedPreference; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @RunWith(AndroidJUnit4.class) public class AppManagementFragmentTest { private static final String FAKE_PACKAGE_NAME = "com.fake.package.name"; private static final String ADVANCED_VPN_GROUP_PACKAGE_NAME = "com.advanced.package.name"; @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); private AppManagementFragment mFragment; private Context mContext; private FakeFeatureFactory mFakeFeatureFactory; private RestrictedPreference mPreferenceForget; @Before @UiThreadTest public void setUp() { if (Looper.myLooper() == null) { Looper.prepare(); } mFragment = spy(new AppManagementFragment()); mContext = spy(ApplicationProvider.getApplicationContext()); mPreferenceForget = new RestrictedPreference(mContext); mFakeFeatureFactory = FakeFeatureFactory.setupForTest(); mFragment.init(ADVANCED_VPN_GROUP_PACKAGE_NAME, mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mPreferenceForget); when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getAdvancedVpnPackageName()) .thenReturn(ADVANCED_VPN_GROUP_PACKAGE_NAME); when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any())) .thenReturn(true); } @Test public void updateRestrictedViews_isAdvancedVpn_hidesForgetPreference() { when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnRemovable()) .thenReturn(false); mFragment.updateRestrictedViews(); assertThat(mPreferenceForget.isVisible()).isFalse(); } @Test public void updateRestrictedViews_isNotAdvancedVpn_showsForgetPreference() { when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnRemovable()) .thenReturn(false); mFragment.init(FAKE_PACKAGE_NAME, mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mPreferenceForget); mFragment.updateRestrictedViews(); assertThat(mPreferenceForget.isVisible()).isTrue(); } @Test public void updateRestrictedViews_isAdvancedVpnRemovable_showsForgetPreference() { when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnRemovable()) .thenReturn(true); mFragment.init(FAKE_PACKAGE_NAME, mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mPreferenceForget); mFragment.updateRestrictedViews(); assertThat(mPreferenceForget.isVisible()).isTrue(); } }