Merge "Move some VPN logic out of ConnectivityService"
am: ec86462033
Change-Id: I212c2d6de1676ab65e6bbf34148d66e183d60c62
This commit is contained in:
@@ -3737,8 +3737,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
vpn.setAlwaysOnPackage(null, false);
|
vpn.setAlwaysOnPackage(null, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vpn.saveAlwaysOnPackage();
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3899,15 +3897,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId);
|
userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId);
|
||||||
mVpns.put(userId, userVpn);
|
mVpns.put(userId, userVpn);
|
||||||
|
|
||||||
final ContentResolver cr = mContext.getContentResolver();
|
|
||||||
String alwaysOnPackage = Settings.Secure.getStringForUser(cr,
|
|
||||||
Settings.Secure.ALWAYS_ON_VPN_APP, userId);
|
|
||||||
final boolean alwaysOnLockdown = Settings.Secure.getIntForUser(cr,
|
|
||||||
Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, /* default */ 0, userId) != 0;
|
|
||||||
if (alwaysOnPackage != null) {
|
|
||||||
userVpn.setAlwaysOnPackage(alwaysOnPackage, alwaysOnLockdown);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
|
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
|
||||||
updateLockdownVpn();
|
updateLockdownVpn();
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import android.app.NotificationManager;
|
|||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
@@ -132,6 +131,7 @@ public class Vpn {
|
|||||||
private NetworkAgent mNetworkAgent;
|
private NetworkAgent mNetworkAgent;
|
||||||
private final Looper mLooper;
|
private final Looper mLooper;
|
||||||
private final NetworkCapabilities mNetworkCapabilities;
|
private final NetworkCapabilities mNetworkCapabilities;
|
||||||
|
private final SystemServices mSystemServices;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
|
* Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
|
||||||
@@ -199,7 +199,7 @@ public class Vpn {
|
|||||||
final boolean isPackageRemoved = !intent.getBooleanExtra(
|
final boolean isPackageRemoved = !intent.getBooleanExtra(
|
||||||
Intent.EXTRA_REPLACING, false);
|
Intent.EXTRA_REPLACING, false);
|
||||||
if (isPackageRemoved) {
|
if (isPackageRemoved) {
|
||||||
setAndSaveAlwaysOnPackage(null, false);
|
setAlwaysOnPackage(null, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -210,11 +210,18 @@ public class Vpn {
|
|||||||
private boolean mIsPackageIntentReceiverRegistered = false;
|
private boolean mIsPackageIntentReceiverRegistered = false;
|
||||||
|
|
||||||
public Vpn(Looper looper, Context context, INetworkManagementService netService,
|
public Vpn(Looper looper, Context context, INetworkManagementService netService,
|
||||||
int userHandle) {
|
@UserIdInt int userHandle) {
|
||||||
|
this(looper, context, netService, userHandle, new SystemServices(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
protected Vpn(Looper looper, Context context, INetworkManagementService netService,
|
||||||
|
int userHandle, SystemServices systemServices) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mNetd = netService;
|
mNetd = netService;
|
||||||
mUserHandle = userHandle;
|
mUserHandle = userHandle;
|
||||||
mLooper = looper;
|
mLooper = looper;
|
||||||
|
mSystemServices = systemServices;
|
||||||
|
|
||||||
mPackage = VpnConfig.LEGACY_VPN;
|
mPackage = VpnConfig.LEGACY_VPN;
|
||||||
mOwnerUID = getAppUid(mPackage, mUserHandle);
|
mOwnerUID = getAppUid(mPackage, mUserHandle);
|
||||||
@@ -230,6 +237,8 @@ public class Vpn {
|
|||||||
mNetworkCapabilities = new NetworkCapabilities();
|
mNetworkCapabilities = new NetworkCapabilities();
|
||||||
mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
|
mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
|
||||||
mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
|
mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
|
||||||
|
|
||||||
|
loadAlwaysOnPackage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -268,6 +277,26 @@ public class Vpn {
|
|||||||
*/
|
*/
|
||||||
public synchronized boolean setAlwaysOnPackage(String packageName, boolean lockdown) {
|
public synchronized boolean setAlwaysOnPackage(String packageName, boolean lockdown) {
|
||||||
enforceControlPermissionOrInternalCaller();
|
enforceControlPermissionOrInternalCaller();
|
||||||
|
|
||||||
|
if (setAlwaysOnPackageInternal(packageName, lockdown)) {
|
||||||
|
saveAlwaysOnPackage();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures an always-on VPN connection through a specific application, the same as
|
||||||
|
* {@link #setAlwaysOnPackage}.
|
||||||
|
*
|
||||||
|
* Does not perform permission checks. Does not persist any of the changes to storage.
|
||||||
|
*
|
||||||
|
* @param packageName the package to designate as always-on VPN supplier.
|
||||||
|
* @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
|
||||||
|
* @return {@code true} if the package has been set as always-on, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
@GuardedBy("this")
|
||||||
|
private boolean setAlwaysOnPackageInternal(String packageName, boolean lockdown) {
|
||||||
if (VpnConfig.LEGACY_VPN.equals(packageName)) {
|
if (VpnConfig.LEGACY_VPN.equals(packageName)) {
|
||||||
Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on.");
|
Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on.");
|
||||||
return false;
|
return false;
|
||||||
@@ -340,13 +369,13 @@ public class Vpn {
|
|||||||
/**
|
/**
|
||||||
* Save the always-on package and lockdown config into Settings.Secure
|
* Save the always-on package and lockdown config into Settings.Secure
|
||||||
*/
|
*/
|
||||||
public synchronized void saveAlwaysOnPackage() {
|
@GuardedBy("this")
|
||||||
|
private void saveAlwaysOnPackage() {
|
||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
final ContentResolver cr = mContext.getContentResolver();
|
mSystemServices.settingsSecurePutStringForUser(Settings.Secure.ALWAYS_ON_VPN_APP,
|
||||||
Settings.Secure.putStringForUser(cr, Settings.Secure.ALWAYS_ON_VPN_APP,
|
|
||||||
getAlwaysOnPackage(), mUserHandle);
|
getAlwaysOnPackage(), mUserHandle);
|
||||||
Settings.Secure.putIntForUser(cr, Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
|
mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
|
||||||
(mLockdown ? 1 : 0), mUserHandle);
|
(mLockdown ? 1 : 0), mUserHandle);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(token);
|
Binder.restoreCallingIdentity(token);
|
||||||
@@ -354,18 +383,19 @@ public class Vpn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set and save always-on package and lockdown config
|
* Load the always-on package and lockdown config from Settings.Secure
|
||||||
* @see Vpn#setAlwaysOnPackage(String, boolean)
|
|
||||||
* @see Vpn#saveAlwaysOnPackage()
|
|
||||||
*
|
|
||||||
* @return result of Vpn#setAndSaveAlwaysOnPackage(String, boolean)
|
|
||||||
*/
|
*/
|
||||||
private synchronized boolean setAndSaveAlwaysOnPackage(String packageName, boolean lockdown) {
|
@GuardedBy("this")
|
||||||
if (setAlwaysOnPackage(packageName, lockdown)) {
|
private void loadAlwaysOnPackage() {
|
||||||
saveAlwaysOnPackage();
|
final long token = Binder.clearCallingIdentity();
|
||||||
return true;
|
try {
|
||||||
} else {
|
final String alwaysOnPackage = mSystemServices.settingsSecureGetStringForUser(
|
||||||
return false;
|
Settings.Secure.ALWAYS_ON_VPN_APP, mUserHandle);
|
||||||
|
final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser(
|
||||||
|
Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserHandle) != 0;
|
||||||
|
setAlwaysOnPackageInternal(alwaysOnPackage, alwaysOnLockdown);
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1257,11 +1287,7 @@ public class Vpn {
|
|||||||
|
|
||||||
private void updateAlwaysOnNotification(DetailedState networkState) {
|
private void updateAlwaysOnNotification(DetailedState networkState) {
|
||||||
final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
|
final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
|
||||||
updateAlwaysOnNotificationInternal(visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
protected void updateAlwaysOnNotificationInternal(boolean visible) {
|
|
||||||
final UserHandle user = UserHandle.of(mUserHandle);
|
final UserHandle user = UserHandle.of(mUserHandle);
|
||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1271,10 +1297,8 @@ public class Vpn {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
|
final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
|
||||||
final PendingIntent configIntent = PendingIntent.getActivityAsUser(
|
final PendingIntent configIntent = mSystemServices.pendingIntentGetActivityAsUser(
|
||||||
mContext, /* request */ 0, intent,
|
intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, user);
|
||||||
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT,
|
|
||||||
null, user);
|
|
||||||
final Notification.Builder builder = new Notification.Builder(mContext)
|
final Notification.Builder builder = new Notification.Builder(mContext)
|
||||||
.setDefaults(0)
|
.setDefaults(0)
|
||||||
.setSmallIcon(R.drawable.vpn_connected)
|
.setSmallIcon(R.drawable.vpn_connected)
|
||||||
@@ -1292,6 +1316,58 @@ public class Vpn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Facade for system service calls that change, or depend on, state outside of
|
||||||
|
* {@link ConnectivityService} and have hard-to-mock interfaces.
|
||||||
|
*
|
||||||
|
* @see com.android.server.connectivity.VpnTest
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static class SystemServices {
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
public SystemServices(@NonNull Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see PendingIntent#getActivityAsUser()
|
||||||
|
*/
|
||||||
|
public PendingIntent pendingIntentGetActivityAsUser(
|
||||||
|
Intent intent, int flags, UserHandle user) {
|
||||||
|
return PendingIntent.getActivityAsUser(mContext, 0 /*request*/, intent, flags,
|
||||||
|
null /*options*/, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Settings.Secure#putStringForUser
|
||||||
|
*/
|
||||||
|
public void settingsSecurePutStringForUser(String key, String value, int userId) {
|
||||||
|
Settings.Secure.putStringForUser(mContext.getContentResolver(), key, value, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Settings.Secure#putIntForUser
|
||||||
|
*/
|
||||||
|
public void settingsSecurePutIntForUser(String key, int value, int userId) {
|
||||||
|
Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Settings.Secure#getStringForUser
|
||||||
|
*/
|
||||||
|
public String settingsSecureGetStringForUser(String key, int userId) {
|
||||||
|
return Settings.Secure.getStringForUser(mContext.getContentResolver(), key, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Settings.Secure#getIntForUser
|
||||||
|
*/
|
||||||
|
public int settingsSecureGetIntForUser(String key, int def, int userId) {
|
||||||
|
return Settings.Secure.getIntForUser(mContext.getContentResolver(), key, def, userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private native int jniCreate(int mtu);
|
private native int jniCreate(int mtu);
|
||||||
private native String jniGetName(int tun);
|
private native String jniGetName(int tun);
|
||||||
private native int jniSetAddresses(String interfaze, String addresses);
|
private native int jniSetAddresses(String interfaze, String addresses);
|
||||||
|
|||||||
@@ -27,10 +27,12 @@ import android.annotation.UserIdInt;
|
|||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.net.NetworkInfo.DetailedState;
|
import android.net.NetworkInfo.DetailedState;
|
||||||
import android.net.UidRange;
|
import android.net.UidRange;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -45,6 +47,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mockito.Answers;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
@@ -87,12 +90,13 @@ public class VpnTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mock private Context mContext;
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
|
||||||
@Mock private UserManager mUserManager;
|
@Mock private UserManager mUserManager;
|
||||||
@Mock private PackageManager mPackageManager;
|
@Mock private PackageManager mPackageManager;
|
||||||
@Mock private INetworkManagementService mNetService;
|
@Mock private INetworkManagementService mNetService;
|
||||||
@Mock private AppOpsManager mAppOps;
|
@Mock private AppOpsManager mAppOps;
|
||||||
@Mock private NotificationManager mNotificationManager;
|
@Mock private NotificationManager mNotificationManager;
|
||||||
|
@Mock private Vpn.SystemServices mSystemServices;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
@@ -104,6 +108,12 @@ public class VpnTest extends AndroidTestCase {
|
|||||||
when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
|
when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
|
||||||
when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
|
when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
|
||||||
.thenReturn(mNotificationManager);
|
.thenReturn(mNotificationManager);
|
||||||
|
|
||||||
|
// Used by {@link Notification.Builder}
|
||||||
|
ApplicationInfo applicationInfo = new ApplicationInfo();
|
||||||
|
applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
|
||||||
|
when(mContext.getApplicationInfo()).thenReturn(applicationInfo);
|
||||||
|
|
||||||
doNothing().when(mNetService).registerObserver(any());
|
doNothing().when(mNetService).registerObserver(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +121,7 @@ public class VpnTest extends AndroidTestCase {
|
|||||||
public void testRestrictedProfilesAreAddedToVpn() {
|
public void testRestrictedProfilesAreAddedToVpn() {
|
||||||
setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB);
|
setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB);
|
||||||
|
|
||||||
final Vpn vpn = spyVpn(primaryUser.id);
|
final Vpn vpn = createVpn(primaryUser.id);
|
||||||
final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
|
final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
|
||||||
null, null);
|
null, null);
|
||||||
|
|
||||||
@@ -125,7 +135,7 @@ public class VpnTest extends AndroidTestCase {
|
|||||||
public void testManagedProfilesAreNotAddedToVpn() {
|
public void testManagedProfilesAreNotAddedToVpn() {
|
||||||
setMockedUsers(primaryUser, managedProfileA);
|
setMockedUsers(primaryUser, managedProfileA);
|
||||||
|
|
||||||
final Vpn vpn = spyVpn(primaryUser.id);
|
final Vpn vpn = createVpn(primaryUser.id);
|
||||||
final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
|
final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
|
||||||
null, null);
|
null, null);
|
||||||
|
|
||||||
@@ -138,7 +148,7 @@ public class VpnTest extends AndroidTestCase {
|
|||||||
public void testAddUserToVpnOnlyAddsOneUser() {
|
public void testAddUserToVpnOnlyAddsOneUser() {
|
||||||
setMockedUsers(primaryUser, restrictedProfileA, managedProfileA);
|
setMockedUsers(primaryUser, restrictedProfileA, managedProfileA);
|
||||||
|
|
||||||
final Vpn vpn = spyVpn(primaryUser.id);
|
final Vpn vpn = createVpn(primaryUser.id);
|
||||||
final Set<UidRange> ranges = new ArraySet<>();
|
final Set<UidRange> ranges = new ArraySet<>();
|
||||||
vpn.addUserToRanges(ranges, primaryUser.id, null, null);
|
vpn.addUserToRanges(ranges, primaryUser.id, null, null);
|
||||||
|
|
||||||
@@ -149,7 +159,7 @@ public class VpnTest extends AndroidTestCase {
|
|||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testUidWhiteAndBlacklist() throws Exception {
|
public void testUidWhiteAndBlacklist() throws Exception {
|
||||||
final Vpn vpn = spyVpn(primaryUser.id);
|
final Vpn vpn = createVpn(primaryUser.id);
|
||||||
final UidRange user = UidRange.createForUser(primaryUser.id);
|
final UidRange user = UidRange.createForUser(primaryUser.id);
|
||||||
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
|
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
|
||||||
|
|
||||||
@@ -174,7 +184,7 @@ public class VpnTest extends AndroidTestCase {
|
|||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testLockdownChangingPackage() throws Exception {
|
public void testLockdownChangingPackage() throws Exception {
|
||||||
final Vpn vpn = spyVpn(primaryUser.id);
|
final Vpn vpn = createVpn(primaryUser.id);
|
||||||
final UidRange user = UidRange.createForUser(primaryUser.id);
|
final UidRange user = UidRange.createForUser(primaryUser.id);
|
||||||
|
|
||||||
// Default state.
|
// Default state.
|
||||||
@@ -209,7 +219,7 @@ public class VpnTest extends AndroidTestCase {
|
|||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testLockdownAddingAProfile() throws Exception {
|
public void testLockdownAddingAProfile() throws Exception {
|
||||||
final Vpn vpn = spyVpn(primaryUser.id);
|
final Vpn vpn = createVpn(primaryUser.id);
|
||||||
setMockedUsers(primaryUser);
|
setMockedUsers(primaryUser);
|
||||||
|
|
||||||
// Make a copy of the restricted profile, as we're going to mark it deleted halfway through.
|
// Make a copy of the restricted profile, as we're going to mark it deleted halfway through.
|
||||||
@@ -249,40 +259,41 @@ public class VpnTest extends AndroidTestCase {
|
|||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testNotificationShownForAlwaysOnApp() {
|
public void testNotificationShownForAlwaysOnApp() {
|
||||||
final Vpn vpn = spyVpn(primaryUser.id);
|
final UserHandle userHandle = UserHandle.of(primaryUser.id);
|
||||||
final InOrder order = inOrder(vpn);
|
final Vpn vpn = createVpn(primaryUser.id);
|
||||||
setMockedUsers(primaryUser);
|
setMockedUsers(primaryUser);
|
||||||
|
|
||||||
|
final InOrder order = inOrder(mNotificationManager);
|
||||||
|
|
||||||
// Don't show a notification for regular disconnected states.
|
// Don't show a notification for regular disconnected states.
|
||||||
vpn.updateState(DetailedState.DISCONNECTED, TAG);
|
vpn.updateState(DetailedState.DISCONNECTED, TAG);
|
||||||
order.verify(vpn).updateAlwaysOnNotificationInternal(false);
|
order.verify(mNotificationManager, atLeastOnce())
|
||||||
|
.cancelAsUser(anyString(), anyInt(), eq(userHandle));
|
||||||
|
|
||||||
// Start showing a notification for disconnected once always-on.
|
// Start showing a notification for disconnected once always-on.
|
||||||
vpn.setAlwaysOnPackage(PKGS[0], false);
|
vpn.setAlwaysOnPackage(PKGS[0], false);
|
||||||
order.verify(vpn).updateAlwaysOnNotificationInternal(true);
|
order.verify(mNotificationManager)
|
||||||
|
.notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
|
||||||
|
|
||||||
// Stop showing the notification once connected.
|
// Stop showing the notification once connected.
|
||||||
vpn.updateState(DetailedState.CONNECTED, TAG);
|
vpn.updateState(DetailedState.CONNECTED, TAG);
|
||||||
order.verify(vpn).updateAlwaysOnNotificationInternal(false);
|
order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
|
||||||
|
|
||||||
// Show the notification if we disconnect again.
|
// Show the notification if we disconnect again.
|
||||||
vpn.updateState(DetailedState.DISCONNECTED, TAG);
|
vpn.updateState(DetailedState.DISCONNECTED, TAG);
|
||||||
order.verify(vpn).updateAlwaysOnNotificationInternal(true);
|
order.verify(mNotificationManager)
|
||||||
|
.notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
|
||||||
|
|
||||||
// Notification should be cleared after unsetting always-on package.
|
// Notification should be cleared after unsetting always-on package.
|
||||||
vpn.setAlwaysOnPackage(null, false);
|
vpn.setAlwaysOnPackage(null, false);
|
||||||
order.verify(vpn).updateAlwaysOnNotificationInternal(false);
|
order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock some methods of vpn object.
|
* Mock some methods of vpn object.
|
||||||
*/
|
*/
|
||||||
private Vpn spyVpn(@UserIdInt int userId) {
|
private Vpn createVpn(@UserIdInt int userId) {
|
||||||
final Vpn vpn = spy(new Vpn(Looper.myLooper(), mContext, mNetService, userId));
|
return new Vpn(Looper.myLooper(), mContext, mNetService, userId, mSystemServices);
|
||||||
|
|
||||||
// Block calls to the NotificationManager or PendingIntent#getActivity.
|
|
||||||
doNothing().when(vpn).updateAlwaysOnNotificationInternal(anyBoolean());
|
|
||||||
return vpn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertBlocked(Vpn vpn, int... uids) {
|
private static void assertBlocked(Vpn vpn, int... uids) {
|
||||||
|
|||||||
Reference in New Issue
Block a user