Merge "Fix the DeviceAndProfileOwner CTS test around VPN disallowed apps."
diff --git a/apps/VpnApp/api23/AndroidManifest.xml b/apps/VpnApp/api23/AndroidManifest.xml
index b00e1a5..cf01d58 100644
--- a/apps/VpnApp/api23/AndroidManifest.xml
+++ b/apps/VpnApp/api23/AndroidManifest.xml
@@ -18,6 +18,7 @@
         package="com.android.cts.vpnfirewall">
 
     <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="23"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 
     <application android:label="@string/app">
         <activity android:name=".VpnClient">
diff --git a/apps/VpnApp/api24/AndroidManifest.xml b/apps/VpnApp/api24/AndroidManifest.xml
index c0c0df6..3161c15 100644
--- a/apps/VpnApp/api24/AndroidManifest.xml
+++ b/apps/VpnApp/api24/AndroidManifest.xml
@@ -18,6 +18,7 @@
         package="com.android.cts.vpnfirewall">
 
     <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="24"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 
     <application android:label="@string/app">
         <activity android:name=".VpnClient">
diff --git a/apps/VpnApp/latest/AndroidManifest.xml b/apps/VpnApp/latest/AndroidManifest.xml
index 6cc706f..30117ca 100644
--- a/apps/VpnApp/latest/AndroidManifest.xml
+++ b/apps/VpnApp/latest/AndroidManifest.xml
@@ -18,6 +18,7 @@
         package="com.android.cts.vpnfirewall">
 
     <uses-sdk android:minSdkVersion="22"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 
     <application android:label="@string/app">
         <activity android:name=".VpnClient">
diff --git a/apps/VpnApp/notalwayson/AndroidManifest.xml b/apps/VpnApp/notalwayson/AndroidManifest.xml
index fc250aa..58d2bf9 100644
--- a/apps/VpnApp/notalwayson/AndroidManifest.xml
+++ b/apps/VpnApp/notalwayson/AndroidManifest.xml
@@ -18,6 +18,7 @@
         package="com.android.cts.vpnfirewall">
 
     <uses-sdk android:minSdkVersion="22"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 
     <application android:label="@string/app">
         <activity android:name=".VpnClient">
diff --git a/apps/VpnApp/src/com/android/cts/vpnfirewall/ReflectorVpnService.java b/apps/VpnApp/src/com/android/cts/vpnfirewall/ReflectorVpnService.java
index edd9de6..bb8d9a04 100644
--- a/apps/VpnApp/src/com/android/cts/vpnfirewall/ReflectorVpnService.java
+++ b/apps/VpnApp/src/com/android/cts/vpnfirewall/ReflectorVpnService.java
@@ -23,6 +23,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
 import android.net.VpnService;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
@@ -36,13 +40,18 @@
 
 public class ReflectorVpnService extends VpnService {
 
-    private static String TAG = "ReflectorVpnService";
+    private static final String TAG = "ReflectorVpnService";
+    private static final String DEVICE_AND_PROFILE_OWNER_PACKAGE =
+        "com.android.cts.deviceandprofileowner";
+    private static final String ACTION_VPN_IS_UP = "com.android.cts.vpnfirewall.VPN_IS_UP";
     private static final int NOTIFICATION_ID = 1;
     private static final String NOTIFICATION_CHANNEL_ID = TAG;
     private static int MTU = 1799;
 
     private ParcelFileDescriptor mFd = null;
     private PingReflector mPingReflector = null;
+    private ConnectivityManager mConnectivityManager = null;
+    private ConnectivityManager.NetworkCallback mNetworkCallback = null;
 
     public static final String RESTRICTION_ADDRESSES = "vpn.addresses";
     public static final String RESTRICTION_ROUTES = "vpn.routes";
@@ -65,15 +74,45 @@
     }
 
     @Override
+    public void onCreate() {
+        mConnectivityManager = getSystemService(ConnectivityManager.class);
+    }
+
+    @Override
     public void onDestroy() {
         stop();
         NotificationManager notificationManager = getSystemService(NotificationManager.class);
         notificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
+        ensureNetworkCallbackUnregistered();
         super.onDestroy();
     }
 
+    private void ensureNetworkCallbackUnregistered() {
+        if (null == mConnectivityManager || null == mNetworkCallback) return;
+        mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+        mNetworkCallback = null;
+    }
+
     private void start() {
         VpnService.prepare(this);
+
+        ensureNetworkCallbackUnregistered();
+        final NetworkRequest request = new NetworkRequest.Builder()
+            .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
+            .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+            .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+            .build();
+        mNetworkCallback = new ConnectivityManager.NetworkCallback() {
+                @Override
+                public void onAvailable(final Network net) {
+                    final Intent vpnIsUpIntent = new Intent(ACTION_VPN_IS_UP);
+                    vpnIsUpIntent.setPackage(DEVICE_AND_PROFILE_OWNER_PACKAGE);
+                    sendBroadcast(vpnIsUpIntent);
+                    ensureNetworkCallbackUnregistered();
+                }
+            };
+        mConnectivityManager.registerNetworkCallback(request, mNetworkCallback);
+
         Builder builder = new Builder();
 
         final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java
index 6aeff7b..8c01884 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/vpn/VpnTestHelper.java
@@ -28,8 +28,11 @@
 
 import android.annotation.TargetApi;
 import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.net.ConnectivityManager;
 import android.net.Network;
@@ -59,6 +62,8 @@
 @TargetApi(VERSION_CODES.N)
 public class VpnTestHelper {
     public static final String VPN_PACKAGE = "com.android.cts.vpnfirewall";
+    private static final String MY_PACKAGE = "com.android.cts.deviceandprofileowner";
+    private static final String ACTION_VPN_IS_UP = VPN_PACKAGE + ".VPN_IS_UP";
 
     // IP address reserved for documentation by rfc5737
     public static final String TEST_ADDRESS = "192.0.2.4";
@@ -94,14 +99,16 @@
 
         ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
         final CountDownLatch vpnLatch = new CountDownLatch(1);
-        final ConnectivityManager.NetworkCallback callback =
-                new ConnectivityManager.NetworkCallback() {
-                    @Override
-                    public void onAvailable(Network net) {
-                        vpnLatch.countDown();
-                    }
-                };
-        cm.registerNetworkCallback(VPN_NETWORK_REQUEST, callback);
+        final IntentFilter intentFilter = new IntentFilter(ACTION_VPN_IS_UP);
+        final BroadcastReceiver receiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(final Context context, final Intent intent) {
+                    if (!intent.getPackage().equals(MY_PACKAGE)) return;
+                    vpnLatch.countDown();
+                    context.unregisterReceiver(this);
+                }
+            };
+        context.registerReceiver(receiver, intentFilter);
 
         try {
             if (packageName != null) {
@@ -116,8 +123,6 @@
             Thread.sleep(NETWORK_SETTLE_GRACE_MS);
         } catch (InterruptedException | PackageManager.NameNotFoundException e) {
             fail("Failed while waiting for VPN: " + e);
-        } finally {
-            cm.unregisterNetworkCallback(callback);
         }
 
         // Do we have a network?