summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Lee <rgl@google.com>2016-07-27 14:46:13 +0100
committerRobin Lee <rgl@google.com>2016-07-28 12:45:03 +0000
commit490849b391a4dc915bc3c624e966b677663ecb77 (patch)
treefd7b46759b9345584484d6ac2b8cd5b3931b0c49
parent0dc7a13a5e4aea5ba648d2405024239327216206 (diff)
downloadpackages_apps_Settings-490849b391a4dc915bc3c624e966b677663ecb77.tar.gz
packages_apps_Settings-490849b391a4dc915bc3c624e966b677663ecb77.tar.bz2
packages_apps_Settings-490849b391a4dc915bc3c624e966b677663ecb77.zip
VpnSettings stub unit tests
For: - enforcing minimum target SDK - enforcing that only actual vpn apps are shown Bug: 30355704 Change-Id: I4fcbea8ce0d0417c089a637d999ea83299cea5d0
-rw-r--r--src/com/android/settings/vpn2/AppManagementFragment.java50
-rw-r--r--tests/unit/src/com/android/settings/vpn2/AppSettingsTest.java104
2 files changed, 131 insertions, 23 deletions
diff --git a/src/com/android/settings/vpn2/AppManagementFragment.java b/src/com/android/settings/vpn2/AppManagementFragment.java
index b306577f8f..d69d6193e1 100644
--- a/src/com/android/settings/vpn2/AppManagementFragment.java
+++ b/src/com/android/settings/vpn2/AppManagementFragment.java
@@ -15,12 +15,14 @@
*/
package com.android.settings.vpn2;
+import android.annotation.NonNull;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -33,12 +35,13 @@ import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.net.VpnConfig;
+import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
-import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.RestrictedPreference;
@@ -57,13 +60,11 @@ public class AppManagementFragment extends SettingsPreferenceFragment
private static final String KEY_ALWAYS_ON_VPN = "always_on_vpn";
private static final String KEY_FORGET_VPN = "forget_vpn";
- private AppOpsManager mAppOpsManager;
private PackageManager mPackageManager;
private ConnectivityManager mConnectivityManager;
// VPN app info
private final int mUserId = UserHandle.myUserId();
- private int mPackageUid;
private String mPackageName;
private PackageInfo mPackageInfo;
private String mVpnLabel;
@@ -105,7 +106,6 @@ public class AppManagementFragment extends SettingsPreferenceFragment
addPreferencesFromResource(R.xml.vpn_app_management);
mPackageManager = getContext().getPackageManager();
- mAppOpsManager = getContext().getSystemService(AppOpsManager.class);
mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
mPreferenceVersion = findPreference(KEY_VERSION);
@@ -199,19 +199,17 @@ public class AppManagementFragment extends SettingsPreferenceFragment
isEnabled ? mPackageName : null, /* lockdownEnabled */ false);
}
- private boolean checkTargetVersion() {
- if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
- return true;
- }
- final int targetSdk = mPackageInfo.applicationInfo.targetSdkVersion;
- if (targetSdk >= Build.VERSION_CODES.N) {
- return true;
- }
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Package " + mPackageName + " targets SDK version " + targetSdk + "; must"
- + " target at least " + Build.VERSION_CODES.N + " to use always-on.");
+ @VisibleForTesting
+ static boolean isAlwaysOnSupportedByApp(@NonNull ApplicationInfo appInfo) {
+ final int targetSdk = appInfo.targetSdkVersion;
+ if (targetSdk < Build.VERSION_CODES.N) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Package " + appInfo.packageName + " targets SDK version: " + targetSdk
+ + "; must target at least " + Build.VERSION_CODES.N + " to use always-on.");
+ }
+ return false;
}
- return false;
+ return true;
}
private void updateUI() {
@@ -228,7 +226,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
mPreferenceForget.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN,
mUserId);
- if (checkTargetVersion()) {
+ if (isAlwaysOnSupportedByApp(mPackageInfo.applicationInfo)) {
// setSummary doesn't override the admin message when user restriction is applied
mPreferenceAlwaysOn.setSummary(null);
// setEnabled is not required here, as checkRestrictionAndSetDisabled
@@ -266,7 +264,6 @@ public class AppManagementFragment extends SettingsPreferenceFragment
}
try {
- mPackageUid = mPackageManager.getPackageUid(mPackageName, /* PackageInfoFlags */ 0);
mPackageInfo = mPackageManager.getPackageInfo(mPackageName, /* PackageInfoFlags */ 0);
mVpnLabel = VpnConfig.getVpnLabel(getPrefContext(), mPackageName).toString();
} catch (NameNotFoundException nnfe) {
@@ -274,7 +271,11 @@ public class AppManagementFragment extends SettingsPreferenceFragment
return false;
}
- if (!isVpnActivated()) {
+ if (mPackageInfo.applicationInfo == null) {
+ Log.e(TAG, "package does not include an application");
+ return false;
+ }
+ if (!appHasVpnPermission(getContext(), mPackageInfo.applicationInfo)) {
Log.e(TAG, "package didn't register VPN profile");
return false;
}
@@ -282,10 +283,13 @@ public class AppManagementFragment extends SettingsPreferenceFragment
return true;
}
- private boolean isVpnActivated() {
- final List<AppOpsManager.PackageOps> apps = mAppOpsManager.getOpsForPackage(mPackageUid,
- mPackageName, new int[]{OP_ACTIVATE_VPN});
- return apps != null && apps.size() > 0 && apps.get(0) != null;
+ @VisibleForTesting
+ static boolean appHasVpnPermission(Context context, @NonNull ApplicationInfo application) {
+ final AppOpsManager service =
+ (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ final List<AppOpsManager.PackageOps> ops = service.getOpsForPackage(application.uid,
+ application.packageName, new int[]{OP_ACTIVATE_VPN});
+ return !ArrayUtils.isEmpty(ops);
}
private boolean isLegacyVpnLockDownOrAnotherPackageAlwaysOn() {
diff --git a/tests/unit/src/com/android/settings/vpn2/AppSettingsTest.java b/tests/unit/src/com/android/settings/vpn2/AppSettingsTest.java
new file mode 100644
index 0000000000..fe437a6a12
--- /dev/null
+++ b/tests/unit/src/com/android/settings/vpn2/AppSettingsTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 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.android.settings.vpn2.AppManagementFragment.isAlwaysOnSupportedByApp;
+import static com.android.settings.vpn2.AppManagementFragment.appHasVpnPermission;
+import static org.mockito.Mockito.*;
+
+import android.app.AppOpsManager;
+import android.content.pm.ApplicationInfo;
+import android.os.Build;
+import android.os.Process;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.content.Context;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class AppSettingsTest extends AndroidTestCase {
+ private static final String TAG = AppSettingsTest.class.getSimpleName();
+
+ @Mock private Context mContext;
+ @Mock private AppOpsManager mAppOps;
+
+ @Override
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
+ }
+
+ @SmallTest
+ public void testAlwaysOnVersionRestriction() {
+ ApplicationInfo mockApp = createMockApp();
+
+ // API 23 (MNC) = not supported
+ mockApp.targetSdkVersion = Build.VERSION_CODES.M;
+ assertFalse(isAlwaysOnSupportedByApp(mockApp));
+
+ // API 24 (NYC) = supported
+ mockApp.targetSdkVersion = Build.VERSION_CODES.N;
+ assertTrue(isAlwaysOnSupportedByApp(mockApp));
+
+ // API 25 (NYC MR1) = supported
+ mockApp.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+ assertTrue(isAlwaysOnSupportedByApp(mockApp));
+ }
+
+ @SmallTest
+ public void testAppOpsRequiredToOpenFragment() {
+ ApplicationInfo mockApp = createMockApp();
+
+ final AppOpsManager.PackageOps[] blankOps = {
+ new AppOpsManager.PackageOps(mockApp.packageName, mockApp.uid, new ArrayList<>()),
+ new AppOpsManager.PackageOps(mockApp.packageName, mockApp.uid, new ArrayList<>())
+ };
+
+ // List with one package op
+ when(mAppOps.getOpsForPackage(eq(mockApp.uid), eq(mockApp.packageName), any()))
+ .thenReturn(Arrays.asList(new AppOpsManager.PackageOps[] {blankOps[0]}));
+ assertTrue(appHasVpnPermission(mContext, mockApp));
+
+ // List with more than one package op
+ when(mAppOps.getOpsForPackage(eq(mockApp.uid), eq(mockApp.packageName), any()))
+ .thenReturn(Arrays.asList(blankOps));
+ assertTrue(appHasVpnPermission(mContext, mockApp));
+
+ // Empty list
+ when(mAppOps.getOpsForPackage(eq(mockApp.uid), eq(mockApp.packageName), any()))
+ .thenReturn(Collections.emptyList());
+ assertFalse(appHasVpnPermission(mContext, mockApp));
+
+ // Null list (may be returned in place of an empty list)
+ when(mAppOps.getOpsForPackage(eq(mockApp.uid), eq(mockApp.packageName), any()))
+ .thenReturn(null);
+ assertFalse(appHasVpnPermission(mContext, mockApp));
+ }
+
+ private static ApplicationInfo createMockApp() {
+ final ApplicationInfo app = new ApplicationInfo();
+ app.packageName = "com.example.mockvpn";
+ app.uid = Process.FIRST_APPLICATION_UID;
+ return app;
+ }
+}