Merge "Update CTS tests to reflect ConnectivityManager API changes." am: 54a417d822 am: 1fd5b6b9a3
am: c0411a3a52

Change-Id: I8d3f5479bb4a4a8fabe45974898ff2dac0e76332
diff --git a/tests/cts/hostside/Android.mk b/tests/cts/hostside/Android.mk
index ad97ecd..1c3f053 100644
--- a/tests/cts/hostside/Android.mk
+++ b/tests/cts/hostside/Android.mk
@@ -21,9 +21,7 @@
 
 LOCAL_MODULE := CtsHostsideNetworkTests
 
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
-
-LOCAL_STATIC_JAVA_LIBRARIES := cts-migration-lib
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed
 
 LOCAL_CTS_TEST_PACKAGE := android.net.hostsidenetwork
 
diff --git a/tests/cts/hostside/aidl/Android.mk b/tests/cts/hostside/aidl/Android.mk
index 4aa55b6..85f71c3 100644
--- a/tests/cts/hostside/aidl/Android.mk
+++ b/tests/cts/hostside/aidl/Android.mk
@@ -17,6 +17,9 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE_TAGS := tests
 LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := com/android/cts/net/hostside/IRemoteSocketFactory.aidl
+LOCAL_SRC_FILES := \
+        com/android/cts/net/hostside/IMyService.aidl \
+        com/android/cts/net/hostside/INetworkStateObserver.aidl \
+        com/android/cts/net/hostside/IRemoteSocketFactory.aidl
 LOCAL_MODULE := CtsHostsideNetworkTestsAidl
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl
new file mode 100644
index 0000000..72d1059
--- /dev/null
+++ b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.cts.net.hostside;
+
+interface IMyService {
+    void registerBroadcastReceiver();
+    int getCounters(String receiverName, String action);
+    String checkNetworkStatus();
+    String getRestrictBackgroundStatus();
+    void sendNotification(int notificationId, String notificationType);
+}
diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl
new file mode 100644
index 0000000..09f3120
--- /dev/null
+++ b/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl
@@ -0,0 +1,21 @@
+/*
+ * 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.cts.net.hostside;
+
+oneway interface INetworkStateObserver {
+    void onNetworkStateChecked(String resultData);
+}
\ No newline at end of file
diff --git a/tests/cts/hostside/app/Android.mk b/tests/cts/hostside/app/Android.mk
index 9519ec5..1c1a798 100644
--- a/tests/cts/hostside/app/Android.mk
+++ b/tests/cts/hostside/app/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ub-uiautomator \
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util ctstestrunner ub-uiautomator \
         CtsHostsideNetworkTestsAidl
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
index 831b387..d2c0873 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
@@ -32,6 +32,7 @@
 
         // Set initial state.
         removePowerSaveModeWhitelist(TEST_APP2_PKG);
+        removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
         setAppIdle(false);
         turnBatteryOff();
 
@@ -82,9 +83,7 @@
 
         // Make sure foreground app doesn't lose access upon enabling it.
         setAppIdle(true);
-        launchActivity();
-        assertAppIdle(false); // Sanity check - not idle anymore, since activity was launched...
-        assertForegroundNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
         finishActivity();
         assertAppIdle(false); // Sanity check - not idle anymore, since activity was launched...
         assertBackgroundNetworkAccess(true);
@@ -93,9 +92,7 @@
 
         // Same for foreground service.
         setAppIdle(true);
-        startForegroundService();
-        assertAppIdle(true); // Sanity check - still idle
-        assertForegroundServiceNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE);
         stopForegroundService();
         assertAppIdle(true);
         assertBackgroundNetworkAccess(false);
@@ -115,6 +112,14 @@
         assertAppIdle(true); // Sanity check - idle again, once whitelisted was removed
         assertBackgroundNetworkAccess(false);
 
+        addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+        assertAppIdle(false); // Sanity check - not idle anymore, since whitelisted
+        assertBackgroundNetworkAccess(true);
+
+        removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+        assertAppIdle(true); // Sanity check - idle again, once whitelisted was removed
+        assertBackgroundNetworkAccess(false);
+
         assertsForegroundAlwaysHasNetworkAccess();
 
         // Sanity check - no whitelist, no access!
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java
index b5637be..28175b8 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java
@@ -31,6 +31,7 @@
 
         // Set initial state.
         removePowerSaveModeWhitelist(TEST_APP2_PKG);
+        removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
         setBatterySaverMode(false);
 
         registerBroadcastReceiver();
@@ -86,8 +87,7 @@
 
         // Make sure foreground app doesn't lose access upon Battery Saver.
         setBatterySaverMode(false);
-        launchActivity();
-        assertForegroundNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
         setBatterySaverMode(true);
         assertForegroundNetworkAccess();
 
@@ -103,8 +103,7 @@
 
         // Make sure foreground service doesn't lose access upon enabling Battery Saver.
         setBatterySaverMode(false);
-        startForegroundService();
-        assertForegroundNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE);
         setBatterySaverMode(true);
         assertForegroundNetworkAccess();
         stopForegroundService();
@@ -123,6 +122,12 @@
         removePowerSaveModeWhitelist(TEST_APP2_PKG);
         assertBackgroundNetworkAccess(false);
 
+        addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+        assertBackgroundNetworkAccess(true);
+
+        removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+        assertBackgroundNetworkAccess(false);
+
         assertsForegroundAlwaysHasNetworkAccess();
         assertBackgroundNetworkAccess(false);
     }
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java
index fc674a7..c2dce38 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java
@@ -32,6 +32,7 @@
 
         // Set initial state.
         removePowerSaveModeWhitelist(TEST_APP2_PKG);
+        removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
         setDozeMode(false);
 
         registerBroadcastReceiver();
@@ -87,8 +88,7 @@
 
         // Make sure foreground service doesn't lose network access upon enabling doze.
         setDozeMode(false);
-        startForegroundService();
-        assertForegroundNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE);
         setDozeMode(true);
         assertForegroundNetworkAccess();
         stopForegroundService();
@@ -108,6 +108,12 @@
         removePowerSaveModeWhitelist(TEST_APP2_PKG);
         assertBackgroundNetworkAccess(false);
 
+        addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+        assertBackgroundNetworkAccess(false);
+
+        removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+        assertBackgroundNetworkAccess(false);
+
         assertsForegroundAlwaysHasNetworkAccess();
         assertBackgroundNetworkAccess(false);
     }
@@ -158,8 +164,7 @@
     // leaves Doze Mode.
     @Override
     protected void assertsForegroundAlwaysHasNetworkAccess() throws Exception {
-        startForegroundService();
-        assertForegroundServiceNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE);
         stopForegroundService();
         assertBackgroundState();
     }
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index a500348..f994169 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -16,17 +16,19 @@
 
 package com.android.cts.net.hostside;
 
-import static android.cts.util.SystemUtil.runShellCommand;
 import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
 
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 
 import android.app.Instrumentation;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -35,11 +37,15 @@
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkInfo.State;
 import android.net.wifi.WifiManager;
+import android.os.Binder;
+import android.os.Bundle;
 import android.os.SystemClock;
 import android.service.notification.NotificationListenerService;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
+import com.android.cts.net.hostside.INetworkStateObserver;
+
 /**
  * Superclass for tests related to background network restrictions.
  */
@@ -49,31 +55,20 @@
     protected static final String TEST_PKG = "com.android.cts.net.hostside";
     protected static final String TEST_APP2_PKG = "com.android.cts.net.hostside.app2";
 
+    private static final String TEST_APP2_ACTIVITY_CLASS = TEST_APP2_PKG + ".MyActivity";
+    private static final String TEST_APP2_SERVICE_CLASS = TEST_APP2_PKG + ".MyForegroundService";
+
     private static final int SLEEP_TIME_SEC = 1;
     private static final boolean DEBUG = true;
 
     // Constants below must match values defined on app2's Common.java
     private static final String MANIFEST_RECEIVER = "ManifestReceiver";
     private static final String DYNAMIC_RECEIVER = "DynamicReceiver";
-    private static final String ACTION_GET_COUNTERS =
-            "com.android.cts.net.hostside.app2.action.GET_COUNTERS";
-    private static final String ACTION_GET_RESTRICT_BACKGROUND_STATUS =
-            "com.android.cts.net.hostside.app2.action.GET_RESTRICT_BACKGROUND_STATUS";
-    private static final String ACTION_CHECK_NETWORK =
-            "com.android.cts.net.hostside.app2.action.CHECK_NETWORK";
+
     private static final String ACTION_RECEIVER_READY =
             "com.android.cts.net.hostside.app2.action.RECEIVER_READY";
-    static final String ACTION_SEND_NOTIFICATION =
-            "com.android.cts.net.hostside.app2.action.SEND_NOTIFICATION";
     static final String ACTION_SHOW_TOAST =
             "com.android.cts.net.hostside.app2.action.SHOW_TOAST";
-    private static final String EXTRA_ACTION = "com.android.cts.net.hostside.app2.extra.ACTION";
-    private static final String EXTRA_RECEIVER_NAME =
-            "com.android.cts.net.hostside.app2.extra.RECEIVER_NAME";
-    private static final String EXTRA_NOTIFICATION_ID =
-            "com.android.cts.net.hostside.app2.extra.NOTIFICATION_ID";
-    private static final String EXTRA_NOTIFICATION_TYPE =
-            "com.android.cts.net.hostside.app2.extra.NOTIFICATION_TYPE";
 
     protected static final String NOTIFICATION_TYPE_CONTENT = "CONTENT";
     protected static final String NOTIFICATION_TYPE_DELETE = "DELETE";
@@ -90,6 +85,12 @@
     private static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;
     private static final int PROCESS_STATE_TOP = 2;
 
+    private static final String KEY_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
+
+    protected static final int TYPE_COMPONENT_ACTIVTIY = 0;
+    protected static final int TYPE_COMPONENT_FOREGROUND_SERVICE = 1;
+
+    private static final int FOREGROUND_PROC_NETWORK_TIMEOUT_MS = 6000;
 
     // Must be higher than NETWORK_TIMEOUT_MS
     private static final int ORDERED_BROADCAST_TIMEOUT_MS = NETWORK_TIMEOUT_MS * 4;
@@ -99,7 +100,9 @@
     protected ConnectivityManager mCm;
     protected WifiManager mWfm;
     protected int mUid;
+    private int mMyUid;
     private String mMeteredWifi;
+    private MyServiceClient mServiceClient;
     private boolean mHasWatch;
     private String mDeviceIdleConstantsSetting;
     private boolean mSupported;
@@ -113,7 +116,9 @@
         mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         mWfm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mUid = getUid(TEST_APP2_PKG);
-        final int myUid = getUid(mContext.getPackageName());
+        mMyUid = getUid(mContext.getPackageName());
+        mServiceClient = new MyServiceClient(mContext);
+        mServiceClient.bind();
         mHasWatch = mContext.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_WATCH);
         if (mHasWatch) {
@@ -124,10 +129,17 @@
         mSupported = setUpActiveNetworkMeteringState();
 
         Log.i(TAG, "Apps status on " + getName() + ":\n"
-                + "\ttest app: uid=" + myUid + ", state=" + getProcessStateByUid(myUid) + "\n"
+                + "\ttest app: uid=" + mMyUid + ", state=" + getProcessStateByUid(mMyUid) + "\n"
                 + "\tapp2: uid=" + mUid + ", state=" + getProcessStateByUid(mUid));
    }
 
+    @Override
+    protected void tearDown() throws Exception {
+        mServiceClient.unbind();
+
+        super.tearDown();
+    }
+
     protected int getUid(String packageName) throws Exception {
         return mContext.getPackageManager().getPackageUid(packageName, 0);
     }
@@ -183,22 +195,31 @@
     }
 
     protected int getNumberBroadcastsReceived(String receiverName, String action) throws Exception {
-        final Intent intent = new Intent(ACTION_GET_COUNTERS);
-        intent.putExtra(EXTRA_ACTION, ACTION_RESTRICT_BACKGROUND_CHANGED);
-        intent.putExtra(EXTRA_RECEIVER_NAME, receiverName);
-        final String resultData = sendOrderedBroadcast(intent);
-        assertNotNull("timeout waiting for ordered broadcast result", resultData);
-        return Integer.valueOf(resultData);
+        return mServiceClient.getCounters(receiverName, action);
     }
 
     protected void assertRestrictBackgroundStatus(int expectedStatus) throws Exception {
-        final Intent intent = new Intent(ACTION_GET_RESTRICT_BACKGROUND_STATUS);
-        final String resultData = sendOrderedBroadcast(intent);
-        assertNotNull("timeout waiting for ordered broadcast result", resultData);
-        final String actualStatus = toString(Integer.parseInt(resultData));
+        final String status = mServiceClient.getRestrictBackgroundStatus();
+        assertNotNull("didn't get API status from app2", status);
+        final String actualStatus = toString(Integer.parseInt(status));
         assertEquals("wrong status", toString(expectedStatus), actualStatus);
     }
 
+    protected void assertMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
+        final int actualStatus = mCm.getRestrictBackgroundStatus();
+        assertEquals("Wrong status", toString(expectedStatus), toString(actualStatus));
+    }
+
+    protected boolean isMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
+        final int actualStatus = mCm.getRestrictBackgroundStatus();
+        if (expectedStatus != actualStatus) {
+            Log.d(TAG, "Expected: " + toString(expectedStatus)
+                    + " but actual: " + toString(actualStatus));
+            return false;
+        }
+        return true;
+    }
+
     protected void assertBackgroundNetworkAccess(boolean expectAllowed) throws Exception {
         assertBackgroundState(); // Sanity check.
         assertNetworkAccess(expectAllowed);
@@ -240,13 +261,11 @@
      */
     protected void assertsForegroundAlwaysHasNetworkAccess() throws Exception{
         // Checks foreground first.
-        launchActivity();
-        assertForegroundNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
         finishActivity();
 
         // Then foreground service
-        startForegroundService();
-        assertForegroundServiceNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE);
         stopForegroundService();
     }
 
@@ -343,15 +362,20 @@
      * @return error message with the mismatch (or empty if assertion passed).
      */
     private String checkNetworkAccess(boolean expectAvailable) throws Exception {
-        String resultData = sendOrderedBroadcast(new Intent(ACTION_CHECK_NETWORK));
+        final String resultData = mServiceClient.checkNetworkStatus();
+        return checkForAvailabilityInResultData(resultData, expectAvailable);
+    }
+
+    private String checkForAvailabilityInResultData(String resultData, boolean expectAvailable) {
         if (resultData == null) {
-            return "timeout waiting for ordered broadcast";
+            assertNotNull("Network status from app2 is null", resultData);
         }
         // Network status format is described on MyBroadcastReceiver.checkNetworkStatus()
         final String[] parts = resultData.split(NETWORK_STATUS_SEPARATOR);
         assertEquals("Wrong network status: " + resultData, 5, parts.length); // Sanity check
-        final State state = State.valueOf(parts[0]);
-        final DetailedState detailedState = DetailedState.valueOf(parts[1]);
+        final State state = parts[0].equals("null") ? null : State.valueOf(parts[0]);
+        final DetailedState detailedState = parts[1].equals("null")
+                ? null : DetailedState.valueOf(parts[1]);
         final boolean connected = Boolean.valueOf(parts[2]);
         final String connectionCheckDetails = parts[3];
         final String networkInfo = parts[4];
@@ -593,6 +617,9 @@
     protected void addRestrictBackgroundWhitelist(int uid) throws Exception {
         executeShellCommand("cmd netpolicy add restrict-background-whitelist " + uid);
         assertRestrictBackgroundWhitelist(uid, true);
+        // UID policies live by the Highlander rule: "There can be only one".
+        // Hence, if app is whitelisted, it should not be blacklisted.
+        assertRestrictBackgroundBlacklist(uid, false);
     }
 
     protected void removeRestrictBackgroundWhitelist(int uid) throws Exception {
@@ -607,6 +634,9 @@
     protected void addRestrictBackgroundBlacklist(int uid) throws Exception {
         executeShellCommand("cmd netpolicy add restrict-background-blacklist " + uid);
         assertRestrictBackgroundBlacklist(uid, true);
+        // UID policies live by the Highlander rule: "There can be only one".
+        // Hence, if app is blacklisted, it should not be whitelisted.
+        assertRestrictBackgroundWhitelist(uid, false);
     }
 
     protected void removeRestrictBackgroundBlacklist(int uid) throws Exception {
@@ -665,6 +695,31 @@
         assertPowerSaveModeWhitelist(packageName, false); // Sanity check
     }
 
+    protected void assertPowerSaveModeExceptIdleWhitelist(String packageName, boolean expected)
+            throws Exception {
+        // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll
+        // need to use netpolicy for whitelisting
+        assertDelayedShellCommand("dumpsys deviceidle except-idle-whitelist =" + packageName,
+                Boolean.toString(expected));
+    }
+
+    protected void addPowerSaveModeExceptIdleWhitelist(String packageName) throws Exception {
+        Log.i(TAG, "Adding package " + packageName + " to power-save-mode-except-idle whitelist");
+        // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll
+        // need to use netpolicy for whitelisting
+        executeShellCommand("dumpsys deviceidle except-idle-whitelist +" + packageName);
+        assertPowerSaveModeExceptIdleWhitelist(packageName, true); // Sanity check
+    }
+
+    protected void removePowerSaveModeExceptIdleWhitelist(String packageName) throws Exception {
+        Log.i(TAG, "Removing package " + packageName
+                + " from power-save-mode-except-idle whitelist");
+        // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll
+        // need to use netpolicy for whitelisting
+        executeShellCommand("dumpsys deviceidle except-idle-whitelist reset");
+        assertPowerSaveModeExceptIdleWhitelist(packageName, false); // Sanity check
+    }
+
     protected void turnBatteryOff() throws Exception {
         executeSilentShellCommand("cmd battery unplug");
     }
@@ -686,10 +741,9 @@
         Log.i(TAG, "Setting Battery Saver Mode to " + enabled);
         if (enabled) {
             turnBatteryOff();
-            executeSilentShellCommand("cmd battery unplug");
-            executeSilentShellCommand("settings put global low_power 1");
+            executeSilentShellCommand("cmd power set-mode 1");
         } else {
-            executeSilentShellCommand("settings put global low_power 0");
+            executeSilentShellCommand("cmd power set-mode 0");
             turnBatteryOn();
         }
     }
@@ -739,9 +793,10 @@
      * {@link #runDeviceTests(String, String)} is executed.
      */
     protected void registerBroadcastReceiver() throws Exception {
-        executeShellCommand("am startservice com.android.cts.net.hostside.app2/.MyService");
+        mServiceClient.registerBroadcastReceiver();
+
         // Wait until receiver is ready.
-        final int maxTries = 5;
+        final int maxTries = 10;
         for (int i = 1; i <= maxTries; i++) {
             final String message =
                     sendOrderedBroadcast(new Intent(ACTION_RECEIVER_READY), SECOND_IN_MS);
@@ -786,35 +841,66 @@
                 mDeviceIdleConstantsSetting));
     }
 
-    protected void startForegroundService() throws Exception {
-        executeShellCommand(
-                "am startservice -f 1 com.android.cts.net.hostside.app2/.MyForegroundService");
+    protected void launchComponentAndAssertNetworkAccess(int type) throws Exception {
+        if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) {
+            startForegroundService();
+            assertForegroundServiceNetworkAccess();
+            return;
+        } else if (type == TYPE_COMPONENT_ACTIVTIY) {
+            turnScreenOn();
+            final CountDownLatch latch = new CountDownLatch(1);
+            final Intent launchIntent = getIntentForComponent(type);
+            final Bundle extras = new Bundle();
+            final String[] errors = new String[]{null};
+            extras.putBinder(KEY_NETWORK_STATE_OBSERVER, getNewNetworkStateObserver(latch, errors));
+            launchIntent.putExtras(extras);
+            mContext.startActivity(launchIntent);
+            if (latch.await(FOREGROUND_PROC_NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                if (!errors[0].isEmpty()) {
+                    fail("Network is not available for app2 (" + mUid + "): " + errors[0]);
+                }
+            } else {
+                fail("Timed out waiting for network availability status from app2 (" + mUid + ")");
+            }
+        } else {
+            throw new IllegalArgumentException("Unknown type: " + type);
+        }
+    }
+
+    private void startForegroundService() throws Exception {
+        final Intent launchIntent = getIntentForComponent(TYPE_COMPONENT_FOREGROUND_SERVICE);
+        mContext.startForegroundService(launchIntent);
         assertForegroundServiceState();
     }
 
+    private Intent getIntentForComponent(int type) {
+        final Intent intent = new Intent();
+        if (type == TYPE_COMPONENT_ACTIVTIY) {
+            intent.setComponent(new ComponentName(TEST_APP2_PKG, TEST_APP2_ACTIVITY_CLASS));
+        } else if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) {
+            intent.setComponent(new ComponentName(TEST_APP2_PKG, TEST_APP2_SERVICE_CLASS))
+                    .setFlags(1);
+        } else {
+            fail("Unknown type: " + type);
+        }
+        return intent;
+    }
+
     protected void stopForegroundService() throws Exception {
-        executeShellCommand(
-                "am startservice -f 2 com.android.cts.net.hostside.app2/.MyForegroundService");
+        executeShellCommand(String.format("am startservice -f 2 %s/%s",
+                TEST_APP2_PKG, TEST_APP2_SERVICE_CLASS));
         // NOTE: cannot assert state because it depends on whether activity was on top before.
     }
 
-    /**
-     * Launches an activity on app2 so its process is elevated to foreground status.
-     */
-    protected void launchActivity() throws Exception {
-        turnScreenOn();
-        executeShellCommand("am start com.android.cts.net.hostside.app2/.MyActivity");
-        final int maxTries = 30;
-        ProcessState state = null;
-        for (int i = 1; i <= maxTries; i++) {
-            state = getProcessStateByUid(mUid);
-            if (state.state == PROCESS_STATE_TOP) return;
-            Log.w(TAG, "launchActivity(): uid " + mUid + " not on TOP state on attempt #" + i
-                    + "; turning screen on and sleeping 1s before checking again");
-            turnScreenOn();
-            SystemClock.sleep(SECOND_IN_MS);
-        }
-        fail("App2 is not on foreground state after " + maxTries + " attempts: " + state);
+    private Binder getNewNetworkStateObserver(final CountDownLatch latch,
+            final String[] errors) {
+        return new INetworkStateObserver.Stub() {
+            @Override
+            public void onNetworkStateChecked(String resultData) {
+                errors[0] = checkForAvailabilityInResultData(resultData, true);
+                latch.countDown();
+            }
+        };
     }
 
     /**
@@ -826,13 +912,10 @@
                 + "--receiver-foreground --receiver-registered-only");
     }
 
-    protected void sendNotification(int notificationId, String notificationType) {
-        final Intent intent = new Intent(ACTION_SEND_NOTIFICATION);
-        intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
-        intent.putExtra(EXTRA_NOTIFICATION_TYPE, notificationType);
-        Log.d(TAG, "Sending notification broadcast (id=" + notificationId + ", type="
-                + notificationType + ": " + intent);
-        mContext.sendBroadcast(intent);
+    protected void sendNotification(int notificationId, String notificationType) throws Exception {
+        Log.d(TAG, "Sending notification broadcast (id=" + notificationId
+                + ", type=" + notificationType);
+        mServiceClient.sendNotification(notificationId, notificationType);
     }
 
     protected String showToast() {
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index 9e4b0c1..599a31c 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -20,16 +20,21 @@
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
 
+import android.util.Log;
+
 public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
 
     private static final String[] REQUIRED_WHITELISTED_PACKAGES = {
         "com.android.providers.downloads"
     };
 
+    private boolean mIsDataSaverSupported;
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
 
+        mIsDataSaverSupported = isDataSaverSupported();
         if (!isSupported()) return;
 
         // Set initial state.
@@ -59,6 +64,32 @@
         return setMeteredNetwork();
     }
 
+    @Override
+    protected boolean isSupported() throws Exception {
+        if (!mIsDataSaverSupported) {
+            Log.i(TAG, "Skipping " + getClass() + "." + getName()
+                    + "() because device does not support Data Saver Mode");
+        }
+        return mIsDataSaverSupported && super.isSupported();
+    }
+
+    /**
+     * As per CDD requirements, if the device doesn't support data saver mode then
+     * ConnectivityManager.getRestrictBackgroundStatus() will always return
+     * RESTRICT_BACKGROUND_STATUS_DISABLED. So, enable the data saver mode and check if
+     * ConnectivityManager.getRestrictBackgroundStatus() for an app in background returns
+     * RESTRICT_BACKGROUND_STATUS_DISABLED or not.
+     */
+    private boolean isDataSaverSupported() throws Exception {
+        assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
+        try {
+            setRestrictBackground(true);
+            return !isMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
+        } finally {
+            setRestrictBackground(false);
+        }
+    }
+
     public void testGetRestrictBackgroundStatus_disabled() throws Exception {
         if (!isSupported()) return;
 
@@ -104,8 +135,7 @@
 
         // Make sure foreground app doesn't lose access upon enabling Data Saver.
         setRestrictBackground(false);
-        launchActivity();
-        assertForegroundNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
         setRestrictBackground(true);
         assertForegroundNetworkAccess();
 
@@ -121,8 +151,7 @@
 
         // Make sure foreground service doesn't lose access upon enabling Data Saver.
         setRestrictBackground(false);
-        startForegroundService();
-        assertForegroundNetworkAccess();
+        launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE);
         setRestrictBackground(true);
         assertForegroundNetworkAccess();
         stopForegroundService();
@@ -137,26 +166,34 @@
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
         assertsForegroundAlwaysHasNetworkAccess();
+        assertRestrictBackgroundChangedReceived(1);
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
-        // Make sure blacklist prevails over whitelist.
+        // UID policies live by the Highlander rule: "There can be only one".
+        // Hence, if app is whitelisted, it should not be blacklisted anymore.
         setRestrictBackground(true);
         assertRestrictBackgroundChangedReceived(2);
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
         addRestrictBackgroundWhitelist(mUid);
         assertRestrictBackgroundChangedReceived(3);
-        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
+        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_WHITELISTED);
 
         // Check status after removing blacklist.
+        // ...re-enables first
+        addRestrictBackgroundBlacklist(mUid);
+        assertRestrictBackgroundChangedReceived(4);
+        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
+        assertsForegroundAlwaysHasNetworkAccess();
+        // ... remove blacklist - access's still rejected because Data Saver is on
         removeRestrictBackgroundBlacklist(mUid);
         assertRestrictBackgroundChangedReceived(4);
-        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_WHITELISTED);
+        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
+        assertsForegroundAlwaysHasNetworkAccess();
+        // ... finally, disable Data Saver
         setRestrictBackground(false);
         assertRestrictBackgroundChangedReceived(5);
         assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
-
         assertsForegroundAlwaysHasNetworkAccess();
-        assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
     }
 
     public void testGetRestrictBackgroundStatus_requiredWhitelistedPackages() throws Exception {
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java
index ec49eee..5248255 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java
@@ -38,6 +38,7 @@
         removeRestrictBackgroundWhitelist(mUid);
         removeRestrictBackgroundBlacklist(mUid);
         removePowerSaveModeWhitelist(TEST_APP2_PKG);
+        removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
 
         registerBroadcastReceiver();
     }
@@ -200,4 +201,74 @@
         removeRestrictBackgroundBlacklist(mUid);
         removePowerSaveModeWhitelist(TEST_APP2_PKG);
     }
+
+    /**
+     * Tests that powersave whitelists works as expected when doze and battery saver modes
+     * are enabled.
+     */
+    public void testDozeAndBatterySaverMode_powerSaveWhitelists() throws Exception {
+        if (!isSupported()) {
+            return;
+        }
+        if (!isDozeModeEnabled()) {
+            Log.i(TAG, "Skipping " + getClass() + "." + getName()
+                    + "() because device does not support Doze Mode");
+            return;
+        }
+
+        setBatterySaverMode(true);
+        setDozeMode(true);
+
+        try {
+            addPowerSaveModeWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(true);
+
+            removePowerSaveModeWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+
+            addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+
+            removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+        } finally {
+            setBatterySaverMode(false);
+            setDozeMode(false);
+        }
+    }
+
+    /**
+     * Tests that powersave whitelists works as expected when doze and appIdle modes
+     * are enabled.
+     */
+    public void testDozeAndAppIdle_powerSaveWhitelists() throws Exception {
+        if (!isSupported()) {
+            return;
+        }
+        if (!isDozeModeEnabled()) {
+            Log.i(TAG, "Skipping " + getClass() + "." + getName()
+                    + "() because device does not support Doze Mode");
+            return;
+        }
+
+        setDozeMode(true);
+        setAppIdle(true);
+
+        try {
+            addPowerSaveModeWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(true);
+
+            removePowerSaveModeWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+
+            addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+
+            removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG);
+            assertBackgroundNetworkAccess(false);
+        } finally {
+            setAppIdle(false);
+            setDozeMode(false);
+        }
+    }
 }
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java
new file mode 100644
index 0000000..ff05d8c
--- /dev/null
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java
@@ -0,0 +1,101 @@
+/*
+ * 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.cts.net.hostside;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.ConditionVariable;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.cts.net.hostside.IMyService;
+
+import java.io.FileDescriptor;
+
+public class MyServiceClient {
+    private static final int TIMEOUT_MS = 5000;
+    private static final String PACKAGE = MyServiceClient.class.getPackage().getName();
+    private static final String APP2_PACKAGE = PACKAGE + ".app2";
+    private static final String SERVICE_NAME = APP2_PACKAGE + ".MyService";
+
+    private Context mContext;
+    private ServiceConnection mServiceConnection;
+    private IMyService mService;
+
+    public MyServiceClient(Context context) {
+        mContext = context;
+    }
+
+    public void bind() {
+        if (mService != null) {
+            throw new IllegalStateException("Already bound");
+        }
+
+        final ConditionVariable cv = new ConditionVariable();
+        mServiceConnection = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                mService = IMyService.Stub.asInterface(service);
+                cv.open();
+            }
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                mService = null;
+            }
+        };
+
+        final Intent intent = new Intent();
+        intent.setComponent(new ComponentName(APP2_PACKAGE, SERVICE_NAME));
+        // Needs to use BIND_ALLOW_OOM_MANAGEMENT and BIND_NOT_FOREGROUND so app2 does not run in
+        // the same process state as app
+        mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE
+                | Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_FOREGROUND);
+        cv.block(TIMEOUT_MS);
+        if (mService == null) {
+            throw new IllegalStateException(
+                    "Could not bind to MyService service after " + TIMEOUT_MS + "ms");
+        }
+    }
+
+    public void unbind() {
+        if (mService != null) {
+            mContext.unbindService(mServiceConnection);
+        }
+    }
+
+    public void registerBroadcastReceiver() throws RemoteException {
+        mService.registerBroadcastReceiver();
+    }
+
+    public int getCounters(String receiverName, String action) throws RemoteException {
+        return mService.getCounters(receiverName, action);
+    }
+
+    public String checkNetworkStatus() throws RemoteException {
+        return mService.checkNetworkStatus();
+    }
+
+    public String getRestrictBackgroundStatus() throws RemoteException {
+        return mService.getRestrictBackgroundStatus();
+    }
+
+    public void sendNotification(int notificationId, String notificationType) throws RemoteException {
+        mService.sendNotification(notificationId, notificationType);
+    }
+}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
index 2bd3c39..bc982ce 100755
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
@@ -110,8 +110,7 @@
 
     private boolean supportedHardware() {
         final PackageManager pm = getInstrumentation().getContext().getPackageManager();
-        return !pm.hasSystemFeature("android.hardware.type.television") &&
-               !pm.hasSystemFeature("android.hardware.type.watch");
+        return !pm.hasSystemFeature("android.hardware.type.watch");
     }
 
     @Override
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java
index e07c0f5..20bbd5a 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java
@@ -16,7 +16,14 @@
 package com.android.cts.net.hostside.app2;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.cts.net.hostside.INetworkStateObserver;
 
 public final class Common {
 
@@ -26,27 +33,13 @@
     // AbstractRestrictBackgroundNetworkTestCase.java
     static final String MANIFEST_RECEIVER = "ManifestReceiver";
     static final String DYNAMIC_RECEIVER = "DynamicReceiver";
-    static final String ACTION_GET_COUNTERS =
-            "com.android.cts.net.hostside.app2.action.GET_COUNTERS";
-    static final String ACTION_GET_RESTRICT_BACKGROUND_STATUS =
-            "com.android.cts.net.hostside.app2.action.GET_RESTRICT_BACKGROUND_STATUS";
-    static final String ACTION_CHECK_NETWORK =
-            "com.android.cts.net.hostside.app2.action.CHECK_NETWORK";
+
     static final String ACTION_RECEIVER_READY =
             "com.android.cts.net.hostside.app2.action.RECEIVER_READY";
     static final String ACTION_FINISH_ACTIVITY =
             "com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY";
-    static final String ACTION_SEND_NOTIFICATION =
-            "com.android.cts.net.hostside.app2.action.SEND_NOTIFICATION";
     static final String ACTION_SHOW_TOAST =
             "com.android.cts.net.hostside.app2.action.SHOW_TOAST";
-    static final String EXTRA_ACTION = "com.android.cts.net.hostside.app2.extra.ACTION";
-    static final String EXTRA_RECEIVER_NAME =
-            "com.android.cts.net.hostside.app2.extra.RECEIVER_NAME";
-    static final String EXTRA_NOTIFICATION_ID =
-            "com.android.cts.net.hostside.app2.extra.NOTIFICATION_ID";
-    static final String EXTRA_NOTIFICATION_TYPE =
-            "com.android.cts.net.hostside.app2.extra.NOTIFICATION_TYPE";
 
     static final String NOTIFICATION_TYPE_CONTENT = "CONTENT";
     static final String NOTIFICATION_TYPE_DELETE = "DELETE";
@@ -56,6 +49,9 @@
     static final String NOTIFICATION_TYPE_ACTION_BUNDLE = "ACTION_BUNDLE";
     static final String NOTIFICATION_TYPE_ACTION_REMOTE_INPUT = "ACTION_REMOTE_INPUT";
 
+    static final String TEST_PKG = "com.android.cts.net.hostside";
+    static final String KEY_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
+
     static int getUid(Context context) {
         final String packageName = context.getPackageName();
         try {
@@ -64,4 +60,26 @@
             throw new IllegalStateException("Could not get UID for " + packageName, e);
         }
     }
+
+    static void notifyNetworkStateObserver(Context context, Intent intent) {
+        if (intent == null) {
+            return;
+        }
+        final Bundle extras = intent.getExtras();
+        if (extras == null) {
+            return;
+        }
+        final INetworkStateObserver observer = INetworkStateObserver.Stub.asInterface(
+                extras.getBinder(KEY_NETWORK_STATE_OBSERVER));
+        if (observer != null) {
+            AsyncTask.execute(() -> {
+                try {
+                    observer.onNetworkStateChecked(
+                            MyBroadcastReceiver.checkNetworkStatus(context));
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error occured while notifying the observer: " + e);
+                }
+            });
+        }
+    }
 }
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
index 444b696..da7e704 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
@@ -17,30 +17,47 @@
 
 import static com.android.cts.net.hostside.app2.Common.ACTION_FINISH_ACTIVITY;
 import static com.android.cts.net.hostside.app2.Common.TAG;
+import static com.android.cts.net.hostside.app2.Common.TEST_PKG;
 
 import android.app.Activity;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.cts.net.hostside.INetworkStateObserver;
+
 /**
  * Activity used to bring process to foreground.
  */
 public class MyActivity extends Activity {
 
+    private BroadcastReceiver finishCommandReceiver = null;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        registerReceiver(new BroadcastReceiver() {
-
+        Common.notifyNetworkStateObserver(this, getIntent());
+        finishCommandReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 Log.d(TAG, "Finishing MyActivity");
                 MyActivity.this.finish();
-            }}, new IntentFilter(ACTION_FINISH_ACTIVITY));
+            }
+        };
+        registerReceiver(finishCommandReceiver, new IntentFilter(ACTION_FINISH_ACTIVITY));
+    }
+
+    @Override
+    public void finish() {
+        if (finishCommandReceiver != null) {
+            unregisterReceiver(finishCommandReceiver);
+        }
+        super.finish();
     }
 
     @Override
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
index 733c3aa..aa54075 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java
@@ -18,16 +18,8 @@
 
 import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
 
-import static com.android.cts.net.hostside.app2.Common.ACTION_CHECK_NETWORK;
-import static com.android.cts.net.hostside.app2.Common.ACTION_GET_COUNTERS;
-import static com.android.cts.net.hostside.app2.Common.ACTION_GET_RESTRICT_BACKGROUND_STATUS;
 import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY;
-import static com.android.cts.net.hostside.app2.Common.ACTION_SEND_NOTIFICATION;
 import static com.android.cts.net.hostside.app2.Common.ACTION_SHOW_TOAST;
-import static com.android.cts.net.hostside.app2.Common.EXTRA_ACTION;
-import static com.android.cts.net.hostside.app2.Common.EXTRA_NOTIFICATION_ID;
-import static com.android.cts.net.hostside.app2.Common.EXTRA_NOTIFICATION_TYPE;
-import static com.android.cts.net.hostside.app2.Common.EXTRA_RECEIVER_NAME;
 import static com.android.cts.net.hostside.app2.Common.MANIFEST_RECEIVER;
 import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION;
 import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION_BUNDLE;
@@ -56,14 +48,12 @@
 
 import java.net.HttpURLConnection;
 import java.net.URL;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
 
 /**
  * Receiver used to:
  * <ol>
- * <li>Stored received RESTRICT_BACKGROUND_CHANGED broadcasts in a shared preference.
- * <li>Returned the number of RESTRICT_BACKGROUND_CHANGED broadcasts in an ordered broadcast.
+ *   <li>Count number of {@code RESTRICT_BACKGROUND_CHANGED} broadcasts received.
+ *   <li>Show a toast.
  * </ol>
  */
 public class MyBroadcastReceiver extends BroadcastReceiver {
@@ -89,23 +79,11 @@
             case ACTION_RESTRICT_BACKGROUND_CHANGED:
                 increaseCounter(context, action);
                 break;
-            case ACTION_GET_COUNTERS:
-                setResultDataFromCounter(context, intent);
-                break;
-            case ACTION_GET_RESTRICT_BACKGROUND_STATUS:
-                getRestrictBackgroundStatus(context, intent);
-                break;
-            case ACTION_CHECK_NETWORK:
-                checkNetwork(context, intent);
-                break;
             case ACTION_RECEIVER_READY:
                 final String message = mName + " is ready to rumble";
                 Log.d(TAG, message);
                 setResultData(message);
                 break;
-            case ACTION_SEND_NOTIFICATION:
-                sendNotification(context, intent);
-                break;
             case ACTION_SHOW_TOAST:
                 showToast(context);
                 break;
@@ -114,14 +92,20 @@
         }
     }
 
+    @Override
+    public String toString() {
+        return "[MyBroadcastReceiver: mName=" + mName + "]";
+    }
+
     private void increaseCounter(Context context, String action) {
-        final SharedPreferences prefs = context.getSharedPreferences(mName, Context.MODE_PRIVATE);
+        final SharedPreferences prefs = context.getApplicationContext()
+                .getSharedPreferences(mName, Context.MODE_PRIVATE);
         final int value = prefs.getInt(action, 0) + 1;
         Log.d(TAG, "increaseCounter('" + action + "'): setting '" + mName + "' to " + value);
         prefs.edit().putInt(action, value).apply();
     }
 
-    private int getCounter(Context context, String action, String receiverName) {
+    static int getCounter(Context context, String action, String receiverName) {
         final SharedPreferences prefs = context.getSharedPreferences(receiverName,
                 Context.MODE_PRIVATE);
         final int value = prefs.getInt(action, 0);
@@ -129,29 +113,14 @@
         return value;
     }
 
-    private void getRestrictBackgroundStatus(Context context, Intent intent) {
+    static String getRestrictBackgroundStatus(Context context) {
         final ConnectivityManager cm = (ConnectivityManager) context
                 .getSystemService(Context.CONNECTIVITY_SERVICE);
         final int apiStatus = cm.getRestrictBackgroundStatus();
         Log.d(TAG, "getRestrictBackgroundStatus: returning " + apiStatus);
-        setResultData(Integer.toString(apiStatus));
+        return String.valueOf(apiStatus);
     }
 
-    private void checkNetwork(final Context context, Intent intent) {
-        final ConnectivityManager cm = (ConnectivityManager) context
-                .getSystemService(Context.CONNECTIVITY_SERVICE);
-
-        String netStatus = null;
-        try {
-            netStatus = checkNetworkStatus(context, cm);
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Timeout checking network status");
-        }
-        Log.d(TAG, "checkNetwork(): returning " + netStatus);
-        setResultData(netStatus);
-    }
-
-
     private static final String NETWORK_STATUS_TEMPLATE = "%s|%s|%s|%s|%s";
     /**
      * Checks whether the network is available and return a string which can then be send as a
@@ -182,78 +151,61 @@
      * </code></pre>
      *
      */
-    private String checkNetworkStatus(final Context context, final ConnectivityManager cm)
-            throws InterruptedException {
-        final LinkedBlockingQueue<String> result = new LinkedBlockingQueue<>(1);
-        new Thread(new Runnable() {
-
-            @Override
-            public void run() {
-                // TODO: connect to a hostside server instead
-                final String address = "http://example.com";
-                final NetworkInfo networkInfo = cm.getActiveNetworkInfo();
-                Log.d(TAG, "Running checkNetworkStatus() on thread "
-                        + Thread.currentThread().getName() + " for UID " + getUid(context)
-                        + "\n\tactiveNetworkInfo: " + networkInfo + "\n\tURL: " + address);
-                boolean checkStatus = false;
-                String checkDetails = "N/A";
-                try {
-                    final URL url = new URL(address);
-                    final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-                    conn.setReadTimeout(NETWORK_TIMEOUT_MS);
-                    conn.setConnectTimeout(NETWORK_TIMEOUT_MS / 2);
-                    conn.setRequestMethod("GET");
-                    conn.setDoInput(true);
-                    conn.connect();
-                    final int response = conn.getResponseCode();
-                    checkStatus = true;
-                    checkDetails = "HTTP response for " + address + ": " + response;
-                } catch (Exception e) {
-                    checkStatus = false;
-                    checkDetails = "Exception getting " + address + ": " + e;
-                }
-                Log.d(TAG, checkDetails);
-                final String status = String.format(NETWORK_STATUS_TEMPLATE,
-                        networkInfo.getState().name(), networkInfo.getDetailedState().name(),
-                        Boolean.toString(checkStatus), checkDetails, networkInfo);
-                Log.d(TAG, "Offering " + status);
-                result.offer(status);
-            }
-        }, mName).start();
-        return result.poll(NETWORK_TIMEOUT_MS * 2, TimeUnit.MILLISECONDS);
-    }
-
-    private void setResultDataFromCounter(Context context, Intent intent) {
-        final String action = intent.getStringExtra(EXTRA_ACTION);
-        if (action == null) {
-            Log.e(TAG, "Missing extra '" + EXTRA_ACTION + "' on " + intent);
-            return;
+    // TODO: now that it uses Binder, it counl return a Bundle with the data parts instead...
+    static String checkNetworkStatus(Context context) {
+        final ConnectivityManager cm =
+                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        // TODO: connect to a hostside server instead
+        final String address = "http://example.com";
+        final NetworkInfo networkInfo = cm.getActiveNetworkInfo();
+        Log.d(TAG, "Running checkNetworkStatus() on thread "
+                + Thread.currentThread().getName() + " for UID " + getUid(context)
+                + "\n\tactiveNetworkInfo: " + networkInfo + "\n\tURL: " + address);
+        boolean checkStatus = false;
+        String checkDetails = "N/A";
+        try {
+            final URL url = new URL(address);
+            final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            conn.setReadTimeout(NETWORK_TIMEOUT_MS);
+            conn.setConnectTimeout(NETWORK_TIMEOUT_MS / 2);
+            conn.setRequestMethod("GET");
+            conn.setDoInput(true);
+            conn.connect();
+            final int response = conn.getResponseCode();
+            checkStatus = true;
+            checkDetails = "HTTP response for " + address + ": " + response;
+        } catch (Exception e) {
+            checkStatus = false;
+            checkDetails = "Exception getting " + address + ": " + e;
         }
-        final String receiverName = intent.getStringExtra(EXTRA_RECEIVER_NAME);
-        if (receiverName == null) {
-            Log.e(TAG, "Missing extra '" + EXTRA_RECEIVER_NAME + "' on " + intent);
-            return;
+        Log.d(TAG, checkDetails);
+        final String state, detailedState;
+        if (networkInfo != null) {
+            state = networkInfo.getState().name();
+            detailedState = networkInfo.getDetailedState().name();
+        } else {
+            state = detailedState = "null";
         }
-        final int counter = getCounter(context, action, receiverName);
-        setResultData(String.valueOf(counter));
+        final String status = String.format(NETWORK_STATUS_TEMPLATE, state, detailedState,
+                Boolean.valueOf(checkStatus), checkDetails, networkInfo);
+        Log.d(TAG, "Offering " + status);
+        return status;
     }
 
     /**
      * Sends a system notification containing actions with pending intents to launch the app's
      * main activitiy or service.
      */
-    private void sendNotification(Context context, Intent intent) {
-        final int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1);
-        final String notificationType = intent.getStringExtra(EXTRA_NOTIFICATION_TYPE);
-        Log.d(TAG, "sendNotification: id=" + notificationId + ", type=" + notificationType
-                + ", intent=" + intent);
+    static void sendNotification(Context context, String channelId, int notificationId,
+            String notificationType ) {
+        Log.d(TAG, "sendNotification: id=" + notificationId + ", type=" + notificationType);
         final Intent serviceIntent = new Intent(context, MyService.class);
         final PendingIntent pendingIntent = PendingIntent.getService(context, 0, serviceIntent,
                 notificationId);
         final Bundle bundle = new Bundle();
         bundle.putCharSequence("parcelable", "I am not");
 
-        final Notification.Builder builder = new Notification.Builder(context)
+        final Notification.Builder builder = new Notification.Builder(context, channelId)
                 .setSmallIcon(R.drawable.ic_notification);
 
         Action action = null;
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
index b88c45d..ff4ba65 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
@@ -16,18 +16,27 @@
 package com.android.cts.net.hostside.app2;
 
 import static com.android.cts.net.hostside.app2.Common.TAG;
+import static com.android.cts.net.hostside.app2.Common.TEST_PKG;
+
 import android.R;
 import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
 import android.app.Service;
 import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.cts.net.hostside.INetworkStateObserver;
+
 /**
  * Service used to change app state to FOREGROUND_SERVICE.
  */
 public class MyForegroundService extends Service {
-
+    private static final String NOTIFICATION_CHANNEL_ID = "cts/MyForegroundService";
     private static final int FLAG_START_FOREGROUND = 1;
     private static final int FLAG_STOP_FOREGROUND = 2;
 
@@ -39,12 +48,17 @@
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         Log.v(TAG, "MyForegroundService.onStartCommand(): " + intent);
+        NotificationManager notificationManager = getSystemService(NotificationManager.class);
+        notificationManager.createNotificationChannel(new NotificationChannel(
+                NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID,
+                NotificationManager.IMPORTANCE_DEFAULT));
         switch (intent.getFlags()) {
             case FLAG_START_FOREGROUND:
                 Log.d(TAG, "Starting foreground");
-                startForeground(42, new Notification.Builder(this)
+                startForeground(42, new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
                         .setSmallIcon(R.drawable.ic_dialog_alert) // any icon is fine
                         .build());
+                Common.notifyNetworkStateObserver(this, intent);
                 break;
             case FLAG_STOP_FOREGROUND:
                 Log.d(TAG, "Stopping foreground");
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
index e6454c7..2496c4a 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
@@ -20,31 +20,92 @@
 import static com.android.cts.net.hostside.app2.Common.DYNAMIC_RECEIVER;
 import static com.android.cts.net.hostside.app2.Common.TAG;
 
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.SharedPreferences;
 import android.os.IBinder;
+import android.os.Looper;
 import android.util.Log;
+import android.widget.Toast;
+
+import com.android.cts.net.hostside.IMyService;
 
 /**
  * Service used to dynamically register a broadcast receiver.
  */
 public class MyService extends Service {
+    private static final String NOTIFICATION_CHANNEL_ID = "MyService";
+
+    private MyBroadcastReceiver mReceiver;
+
+    // TODO: move MyBroadcast static functions here - they were kept there to make git diff easier.
+
+    private IMyService.Stub mBinder =
+        new IMyService.Stub() {
+
+        @Override
+        public void registerBroadcastReceiver() {
+            if (mReceiver != null) {
+                Log.d(TAG, "receiver already registered: " + mReceiver);
+                return;
+            }
+            final Context context = getApplicationContext();
+            mReceiver = new MyBroadcastReceiver(DYNAMIC_RECEIVER);
+            context.registerReceiver(mReceiver, new IntentFilter(ACTION_RECEIVER_READY));
+            context.registerReceiver(mReceiver,
+                    new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED));
+            Log.d(TAG, "receiver registered");
+        }
+
+        @Override
+        public int getCounters(String receiverName, String action) {
+            return MyBroadcastReceiver.getCounter(getApplicationContext(), action, receiverName);
+        }
+
+        @Override
+        public String checkNetworkStatus() {
+            return MyBroadcastReceiver.checkNetworkStatus(getApplicationContext());
+        }
+
+        @Override
+        public String getRestrictBackgroundStatus() {
+            return MyBroadcastReceiver.getRestrictBackgroundStatus(getApplicationContext());
+        }
+
+        @Override
+        public void sendNotification(int notificationId, String notificationType) {
+            MyBroadcastReceiver .sendNotification(getApplicationContext(), NOTIFICATION_CHANNEL_ID,
+                    notificationId, notificationType);
+        }
+      };
 
     @Override
     public IBinder onBind(Intent intent) {
-        return null;
+        return mBinder;
     }
 
     @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        Log.d(TAG, "MyService.onStartCommand: " + intent);
+    public void onCreate() {
         final Context context = getApplicationContext();
-        final MyBroadcastReceiver myReceiver = new MyBroadcastReceiver(DYNAMIC_RECEIVER);
-        context.registerReceiver(myReceiver, new IntentFilter(ACTION_RECEIVER_READY));
-        context.registerReceiver(myReceiver, new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED));
-        Log.d(TAG, "receiver registered");
-        return START_STICKY;
+        ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
+                .createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID,
+                        NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT));
+    }
+
+    @Override
+    public void onDestroy() {
+        final Context context = getApplicationContext();
+        ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
+                .deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
+        if (mReceiver != null) {
+            Log.d(TAG, "onDestroy(): unregistering " + mReceiver);
+            getApplicationContext().unregisterReceiver(mReceiver);
+        }
+
+        super.onDestroy();
     }
 }
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java b/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
index e96537c..c6df893 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
@@ -16,7 +16,7 @@
 
 package com.android.cts.net;
 
-import com.android.cts.migration.MigrationHelper;
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.Log;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.TestIdentifier;
@@ -78,7 +78,8 @@
 
     protected void installPackage(String apk) throws FileNotFoundException,
             DeviceNotAvailableException {
-        assertNull(getDevice().installPackage(MigrationHelper.getTestFile(mCtsBuild, apk), false));
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+        assertNull(getDevice().installPackage(buildHelper.getTestFile(apk), false));
     }
 
     protected void uninstallPackage(String packageName, boolean shouldSucceed)
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index faf75d9..bf3fc08 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -251,6 +251,16 @@
                 "testDataAndBatterySaverModes_nonMeteredNetwork");
     }
 
+    public void testDozeAndBatterySaverMode_powerSaveWhitelists() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest",
+                "testDozeAndBatterySaverMode_powerSaveWhitelists");
+    }
+
+    public void testDozeAndAppIdle_powerSaveWhitelists() throws Exception {
+        runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest",
+                "testDozeAndAppIdle_powerSaveWhitelists");
+    }
+
     /*******************
      * Helper methods. *
      *******************/
diff --git a/tests/cts/net/Android.mk b/tests/cts/net/Android.mk
index 7d2b0ba..98cde9b 100644
--- a/tests/cts/net/Android.mk
+++ b/tests/cts/net/Android.mk
@@ -36,7 +36,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     core-tests-support \
-    ctsdeviceutil \
+    compatibility-device-util \
     ctstestrunner \
     ctstestserver \
     mockwebserver \
diff --git a/tests/cts/net/assets/PerProviderSubscription.xml b/tests/cts/net/assets/PerProviderSubscription.xml
index 7f2d95d..de6c0c6 100644
--- a/tests/cts/net/assets/PerProviderSubscription.xml
+++ b/tests/cts/net/assets/PerProviderSubscription.xml
@@ -8,10 +8,6 @@
       </Type>
     </RTProperties>
     <Node>
-      <NodeName>UpdateIdentifier</NodeName>
-      <Value>12</Value>
-    </Node>
-    <Node>
       <NodeName>i001</NodeName>
       <Node>
         <NodeName>HomeSP</NodeName>
@@ -27,86 +23,14 @@
           <NodeName>RoamingConsortiumOI</NodeName>
           <Value>112233,445566</Value>
         </Node>
-        <Node>
-          <NodeName>IconURL</NodeName>
-          <Value>icon.test.com</Value>
-        </Node>
-        <Node>
-          <NodeName>NetworkID</NodeName>
-          <Node>
-            <NodeName>n001</NodeName>
-            <Node>
-              <NodeName>SSID</NodeName>
-              <Value>TestSSID</Value>
-            </Node>
-            <Node>
-              <NodeName>HESSID</NodeName>
-              <Value>12345678</Value>
-            </Node>
-          </Node>
-          <Node>
-            <NodeName>n002</NodeName>
-            <Node>
-              <NodeName>SSID</NodeName>
-              <Value>NullHESSID</Value>
-            </Node>
-          </Node>
-        </Node>
-        <Node>
-          <NodeName>HomeOIList</NodeName>
-          <Node>
-            <NodeName>h001</NodeName>
-            <Node>
-              <NodeName>HomeOI</NodeName>
-              <Value>11223344</Value>
-            </Node>
-            <Node>
-              <NodeName>HomeOIRequired</NodeName>
-              <Value>true</Value>
-            </Node>
-          </Node>
-          <Node>
-            <NodeName>h002</NodeName>
-            <Node>
-              <NodeName>HomeOI</NodeName>
-              <Value>55667788</Value>
-            </Node>
-            <Node>
-              <NodeName>HomeOIRequired</NodeName>
-              <Value>false</Value>
-            </Node>
-          </Node>
-        </Node>
-        <Node>
-          <NodeName>OtherHomePartners</NodeName>
-          <Node>
-            <NodeName>o001</NodeName>
-            <Node>
-              <NodeName>FQDN</NodeName>
-              <Value>other.fqdn.com</Value>
-            </Node>
-          </Node>
-        </Node>
       </Node>
       <Node>
         <NodeName>Credential</NodeName>
         <Node>
-          <NodeName>CreationDate</NodeName>
-          <Value>2016-01-01T10:00:00Z</Value>
-        </Node>
-        <Node>
-          <NodeName>ExpirationDate</NodeName>
-          <Value>2016-02-01T10:00:00Z</Value>
-        </Node>
-        <Node>
           <NodeName>Realm</NodeName>
           <Value>shaken.stirred.com</Value>
         </Node>
         <Node>
-          <NodeName>CheckAAAServerCertStatus</NodeName>
-          <Value>true</Value>
-        </Node>
-        <Node>
           <NodeName>UsernamePassword</NodeName>
           <Node>
             <NodeName>Username</NodeName>
@@ -117,18 +41,6 @@
             <Value>Ym9uZDAwNw==</Value>
           </Node>
           <Node>
-            <NodeName>MachineManaged</NodeName>
-            <Value>true</Value>
-          </Node>
-          <Node>
-            <NodeName>SoftTokenApp</NodeName>
-            <Value>TestApp</Value>
-          </Node>
-          <Node>
-            <NodeName>AbleToShare</NodeName>
-            <Value>true</Value>
-          </Node>
-          <Node>
             <NodeName>EAPMethod</NodeName>
             <Node>
               <NodeName>EAPType</NodeName>
@@ -163,237 +75,6 @@
           </Node>
         </Node>
       </Node>
-      <Node>
-        <NodeName>Policy</NodeName>
-        <Node>
-          <NodeName>PreferredRoamingPartnerList</NodeName>
-          <Node>
-            <NodeName>p001</NodeName>
-            <Node>
-              <NodeName>FQDN_Match</NodeName>
-              <Value>test1.fqdn.com,exactMatch</Value>
-            </Node>
-            <Node>
-              <NodeName>Priority</NodeName>
-              <Value>127</Value>
-            </Node>
-            <Node>
-              <NodeName>Country</NodeName>
-              <Value>us,fr</Value>
-            </Node>
-          </Node>
-          <Node>
-            <NodeName>p002</NodeName>
-            <Node>
-              <NodeName>FQDN_Match</NodeName>
-              <Value>test2.fqdn.com,includeSubdomains</Value>
-            </Node>
-            <Node>
-              <NodeName>Priority</NodeName>
-              <Value>200</Value>
-            </Node>
-            <Node>
-              <NodeName>Country</NodeName>
-              <Value>*</Value>
-            </Node>
-          </Node>
-        </Node>
-        <Node>
-          <NodeName>MinBackhaulThreshold</NodeName>
-          <Node>
-            <NodeName>m001</NodeName>
-            <Node>
-              <NodeName>NetworkType</NodeName>
-              <Value>home</Value>
-            </Node>
-            <Node>
-              <NodeName>DLBandwidth</NodeName>
-              <Value>23412</Value>
-            </Node>
-            <Node>
-              <NodeName>ULBandwidth</NodeName>
-              <Value>9823</Value>
-            </Node>
-          </Node>
-          <Node>
-            <NodeName>m002</NodeName>
-            <Node>
-              <NodeName>NetworkType</NodeName>
-              <Value>roaming</Value>
-            </Node>
-            <Node>
-              <NodeName>DLBandwidth</NodeName>
-              <Value>9271</Value>
-            </Node>
-            <Node>
-              <NodeName>ULBandwidth</NodeName>
-              <Value>2315</Value>
-            </Node>
-          </Node>
-        </Node>
-        <Node>
-          <NodeName>PolicyUpdate</NodeName>
-          <Node>
-            <NodeName>UpdateInterval</NodeName>
-            <Value>120</Value>
-          </Node>
-          <Node>
-            <NodeName>UpdateMethod</NodeName>
-            <Value>OMA-DM-ClientInitiated</Value>
-          </Node>
-          <Node>
-            <NodeName>Restriction</NodeName>
-            <Value>HomeSP</Value>
-          </Node>
-          <Node>
-            <NodeName>URI</NodeName>
-            <Value>policy.update.com</Value>
-          </Node>
-          <Node>
-            <NodeName>UsernamePassword</NodeName>
-            <Node>
-              <NodeName>Username</NodeName>
-              <Value>updateUser</Value>
-            </Node>
-            <Node>
-              <NodeName>Password</NodeName>
-              <Value>updatePass</Value>
-            </Node>
-          </Node>
-          <Node>
-            <NodeName>TrustRoot</NodeName>
-            <Node>
-              <NodeName>CertURL</NodeName>
-              <Value>update.cert.com</Value>
-            </Node>
-            <Node>
-              <NodeName>CertSHA256Fingerprint</NodeName>
-              <Value>1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f</Value>
-            </Node>
-          </Node>
-        </Node>
-        <Node>
-          <NodeName>SPExclusionList</NodeName>
-          <Node>
-            <NodeName>s001</NodeName>
-            <Node>
-              <NodeName>SSID</NodeName>
-              <Value>excludeSSID</Value>
-            </Node>
-          </Node>
-        </Node>
-        <Node>
-          <NodeName>RequiredProtoPortTuple</NodeName>
-          <Node>
-            <NodeName>r001</NodeName>
-            <Node>
-              <NodeName>IPProtocol</NodeName>
-              <Value>12</Value>
-            </Node>
-            <Node>
-              <NodeName>PortNumber</NodeName>
-              <Value>34,92,234</Value>
-            </Node>
-          </Node>
-        </Node>
-        <Node>
-          <NodeName>MaximumBSSLoadValue</NodeName>
-          <Value>23</Value>
-        </Node>
-      </Node>
-      <Node>
-        <NodeName>CredentialPriority</NodeName>
-        <Value>99</Value>
-      </Node>
-      <Node>
-        <NodeName>AAAServerTrustRoot</NodeName>
-        <Node>
-          <NodeName>a001</NodeName>
-          <Node>
-            <NodeName>CertURL</NodeName>
-            <Value>server1.trust.root.com</Value>
-          </Node>
-          <Node>
-            <NodeName>CertSHA256Fingerprint</NodeName>
-            <Value>1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f</Value>
-          </Node>
-        </Node>
-      </Node>
-      <Node>
-        <NodeName>SubscriptionUpdate</NodeName>
-        <Node>
-          <NodeName>UpdateInterval</NodeName>
-          <Value>120</Value>
-        </Node>
-        <Node>
-          <NodeName>UpdateMethod</NodeName>
-          <Value>SSP-ClientInitiated</Value>
-        </Node>
-        <Node>
-          <NodeName>Restriction</NodeName>
-          <Value>RoamingPartner</Value>
-        </Node>
-        <Node>
-          <NodeName>URI</NodeName>
-          <Value>subscription.update.com</Value>
-        </Node>
-        <Node>
-          <NodeName>UsernamePassword</NodeName>
-          <Node>
-            <NodeName>Username</NodeName>
-            <Value>subscriptionUser</Value>
-          </Node>
-          <Node>
-            <NodeName>Password</NodeName>
-            <Value>subscriptionPass</Value>
-          </Node>
-        </Node>
-        <Node>
-          <NodeName>TrustRoot</NodeName>
-          <Node>
-            <NodeName>CertURL</NodeName>
-            <Value>subscription.update.cert.com</Value>
-          </Node>
-          <Node>
-            <NodeName>CertSHA256Fingerprint</NodeName>
-            <Value>1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f</Value>
-          </Node>
-        </Node>
-      </Node>
-      <Node>
-        <NodeName>SubscriptionParameter</NodeName>
-        <Node>
-          <NodeName>CreationDate</NodeName>
-          <Value>2016-02-01T10:00:00Z</Value>
-        </Node>
-        <Node>
-          <NodeName>ExpirationDate</NodeName>
-          <Value>2016-03-01T10:00:00Z</Value>
-        </Node>
-        <Node>
-          <NodeName>TypeOfSubscription</NodeName>
-          <Value>Gold</Value>
-        </Node>
-        <Node>
-          <NodeName>UsageLimits</NodeName>
-          <Node>
-            <NodeName>DataLimit</NodeName>
-            <Value>921890</Value>
-          </Node>
-          <Node>
-            <NodeName>StartDate</NodeName>
-            <Value>2016-12-01T10:00:00Z</Value>
-          </Node>
-          <Node>
-            <NodeName>TimeLimit</NodeName>
-            <Value>120</Value>
-          </Node>
-          <Node>
-            <NodeName>UsageTimePeriod</NodeName>
-            <Value>99910</Value>
-          </Node>
-        </Node>
-      </Node>
     </Node>
   </Node>
 </MgmtTree>
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index b619974..b951378 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -45,12 +45,15 @@
 
 import com.android.internal.telephony.PhoneConstants;
 
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.Socket;
 import java.net.InetSocketAddress;
 import java.util.HashMap;
+import java.util.Scanner;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -74,6 +77,17 @@
             "Host: " + TEST_HOST + "\r\n" +
             "Connection: keep-alive\r\n\r\n";
 
+    // Base path for IPv6 sysctls
+    private static final String IPV6_SYSCTL_DIR = "/proc/sys/net/ipv6/conf";
+
+    // Expected values for MIN|MAX_PLEN.
+    private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN = 48;
+    private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN = 64;
+
+    // Expected values for RFC 7559 router soliciations.
+    // Maximum number of router solicitations to send. -1 means no limit.
+    private static final int IPV6_WIFI_ROUTER_SOLICITATIONS = -1;
+
     // Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
     private static final String NETWORK_CALLBACK_ACTION =
             "ConnectivityManagerTest.NetworkCallbackAction";
@@ -91,6 +105,7 @@
     private PackageManager mPackageManager;
     private final HashMap<Integer, NetworkConfig> mNetworks =
             new HashMap<Integer, NetworkConfig>();
+    boolean mWifiConnectAttempted;
 
     @Override
     protected void setUp() throws Exception {
@@ -99,6 +114,7 @@
         mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mPackageManager = mContext.getPackageManager();
+        mWifiConnectAttempted = false;
 
         // Get com.android.internal.R.array.networkAttributes
         int resId = mContext.getResources().getIdentifier("networkAttributes", "array", "android");
@@ -116,6 +132,27 @@
         }
     }
 
+    @Override
+    protected void tearDown() throws Exception {
+        // Return WiFi to its original disabled state after tests that explicitly connect.
+        if (mWifiConnectAttempted) {
+            disconnectFromWifi(null);
+        }
+    }
+
+    /**
+     * Make sure WiFi is connected to an access point if it is not already. If
+     * WiFi is enabled as a result of this function, it will be disabled
+     * automatically in tearDown().
+     */
+    private Network ensureWifiConnected() {
+        if (mWifiManager.isWifiEnabled()) {
+            return getWifiNetwork();
+        }
+        mWifiConnectAttempted = true;
+        return connectToWifi();
+    }
+
     public void testIsNetworkTypeValid() {
         assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE));
         assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI));
@@ -298,14 +335,10 @@
         final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultTrackingCallback);
 
-        final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
         Network wifiNetwork = null;
 
         try {
-            // Make sure WiFi is connected to an access point to start with.
-            if (!previousWifiEnabledState) {
-                connectToWifi();
-            }
+            ensureWifiConnected();
 
             // Now we should expect to get a network callback about availability of the wifi
             // network even if it was already connected as a state-based action when the callback
@@ -321,11 +354,6 @@
         } finally {
             mCm.unregisterNetworkCallback(callback);
             mCm.unregisterNetworkCallback(defaultTrackingCallback);
-
-            // Return WiFi to its original enabled/disabled state.
-            if (!previousWifiEnabledState) {
-                disconnectFromWifi(wifiNetwork);
-            }
         }
     }
 
@@ -357,13 +385,8 @@
         // We will register for a WIFI network being available or lost.
         mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent);
 
-        final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
-
         try {
-            // Make sure WiFi is connected to an access point to start with.
-            if (!previousWifiEnabledState) {
-                connectToWifi();
-            }
+            ensureWifiConnected();
 
             // Now we expect to get the Intent delivered notifying of the availability of the wifi
             // network even if it was already connected as a state-based action when the callback
@@ -376,11 +399,6 @@
             mCm.unregisterNetworkCallback(pendingIntent);
             pendingIntent.cancel();
             mContext.unregisterReceiver(receiver);
-
-            // Return WiFi to its original enabled/disabled state.
-            if (!previousWifiEnabledState) {
-                disconnectFromWifi(null);
-            }
         }
     }
 
@@ -761,4 +779,42 @@
             fail("No exception thrown when restricted network requested.");
         } catch (SecurityException expected) {}
     }
+
+    private Scanner makeWifiSysctlScanner(String key) throws FileNotFoundException {
+        Network network = ensureWifiConnected();
+        String iface = mCm.getLinkProperties(network).getInterfaceName();
+        String path = IPV6_SYSCTL_DIR + "/" + iface + "/" + key;
+        return new Scanner(new File(path));
+    }
+
+    /** Verify that accept_ra_rt_info_min_plen exists and is set to the expected value */
+    public void testAcceptRaRtInfoMinPlen() throws Exception {
+        Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_min_plen");
+        assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN, s.nextInt());
+    }
+
+    /** Verify that accept_ra_rt_info_max_plen exists and is set to the expected value */
+    public void testAcceptRaRtInfoMaxPlen() throws Exception {
+        Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_max_plen");
+        assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN, s.nextInt());
+    }
+
+    /** Verify that router_solicitations exists and is set to the expected value */
+    public void testRouterSolicitations() throws Exception {
+        Scanner s = makeWifiSysctlScanner("router_solicitations");
+        assertEquals(IPV6_WIFI_ROUTER_SOLICITATIONS, s.nextInt());
+    }
+
+    /** Verify that router_solicitation_max_interval exists and is in an acceptable interval */
+    public void testRouterSolicitationMaxInterval() throws Exception {
+        Scanner s = makeWifiSysctlScanner("router_solicitation_max_interval");
+        int interval = s.nextInt();
+        // Verify we're in the interval [15 minutes, 60 minutes]. Lower values may adversely
+        // impact battery life and higher values can decrease the probability of detecting
+        // network changes.
+        final int lowerBoundSec = 15 * 60;
+        final int upperBoundSec = 60 * 60;
+        assertTrue(lowerBoundSec <= interval);
+        assertTrue(interval <= upperBoundSec);
+    }
 }
diff --git a/tests/cts/net/src/android/net/http/cts/HttpResponseCacheTest.java b/tests/cts/net/src/android/net/http/cts/HttpResponseCacheTest.java
index 7987a50..198f973 100644
--- a/tests/cts/net/src/android/net/http/cts/HttpResponseCacheTest.java
+++ b/tests/cts/net/src/android/net/http/cts/HttpResponseCacheTest.java
@@ -21,9 +21,10 @@
 
 import junit.framework.TestCase;
 
-import android.cts.util.FileUtils;
 import android.net.http.HttpResponseCache;
 
+import com.android.compatibility.common.util.FileUtils;
+
 import java.io.File;
 import java.io.InputStream;
 import java.net.CacheRequest;
diff --git a/tests/cts/net/src/android/net/wifi/aware/cts/SingleDeviceTest.java b/tests/cts/net/src/android/net/wifi/aware/cts/SingleDeviceTest.java
index 1f7b31b..d4982a5 100644
--- a/tests/cts/net/src/android/net/wifi/aware/cts/SingleDeviceTest.java
+++ b/tests/cts/net/src/android/net/wifi/aware/cts/SingleDeviceTest.java
@@ -257,6 +257,23 @@
          * be queued.
          */
         boolean waitForCallback(int callback) {
+            return waitForCallback(callback, WAIT_FOR_AWARE_CHANGE_SECS);
+        }
+
+        /**
+         * Wait for the specified callback - any of the ON_* constants. Returns a true
+         * on success (specified callback triggered) or false on failure (timed-out or
+         * interrupted while waiting for the requested callback).
+         *
+         * Same as waitForCallback(int callback) execpt that allows specifying a custom timeout.
+         * The default timeout is a short value expected to be sufficient for all behaviors which
+         * should happen relatively quickly. Specifying a custom timeout should only be done for
+         * those cases which are known to take a specific longer period of time.
+         *
+         * Note: other callbacks happening while while waiting for the specified callback will
+         * be queued.
+         */
+        boolean waitForCallback(int callback, int timeoutSec) {
             synchronized (mLocalLock) {
                 boolean found = mCallbackQueue.remove(callback);
                 if (found) {
@@ -268,7 +285,7 @@
             }
 
             try {
-                return mBlocker.await(WAIT_FOR_AWARE_CHANGE_SECS, TimeUnit.SECONDS);
+                return mBlocker.await(timeoutSec, TimeUnit.SECONDS);
             } catch (InterruptedException e) {
                 return false;
             }
@@ -369,7 +386,7 @@
         synchronized (mLock) {
             for (WifiAwareSession session : mSessions) {
                 // no damage from destroying twice (i.e. ok if test cleaned up after itself already)
-                session.destroy();
+                session.close();
             }
             mSessions.clear();
         }
@@ -436,7 +453,7 @@
         }
 
         WifiAwareSession session = attachAndGetSession();
-        session.destroy();
+        session.close();
     }
 
     /**
@@ -469,7 +486,7 @@
             byte[] mac = identityL.getMac();
             assertNotNull("Wi-Fi Aware discovery MAC: iteration " + i, mac);
 
-            session.destroy();
+            session.close();
 
             macs.add(new TestUtils.MacWrapper(mac));
         }
@@ -510,14 +527,54 @@
         // 3. destroy
         assertFalse("Publish not terminated", discoveryCb.hasCallbackAlreadyHappened(
                 DiscoverySessionCallbackTest.ON_SESSION_TERMINATED));
-        discoverySession.destroy();
+        discoverySession.close();
 
         // 4. try update post-destroy: should time-out waiting for cb
         discoverySession.updatePublish(publishConfig);
         assertFalse("Publish update post destroy", discoveryCb.waitForCallback(
                 DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED));
 
-        session.destroy();
+        session.close();
+    }
+
+    /**
+     * Validate that publish with a Time To Live (TTL) setting expires within the specified
+     * time (and validates that the terminate callback is triggered).
+     */
+    public void testPublishLimitedTtlSuccess() {
+        if (!TestUtils.shouldTestWifiAware(getContext())) {
+            return;
+        }
+
+        final String serviceName = "ValidName";
+        final int ttlSec = 5;
+
+        WifiAwareSession session = attachAndGetSession();
+
+        PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(
+                serviceName).setTtlSec(ttlSec).setTerminateNotificationEnabled(true).build();
+        DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest();
+
+        // 1. publish
+        session.publish(publishConfig, discoveryCb, mHandler);
+        assertTrue("Publish started",
+                discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_PUBLISH_STARTED));
+        PublishDiscoverySession discoverySession = discoveryCb.getPublishDiscoverySession();
+        assertNotNull("Publish session", discoverySession);
+
+        // 2. wait for terminate within 'ttlSec'.
+        assertTrue("Publish terminated",
+                discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_SESSION_TERMINATED,
+                        ttlSec + 5));
+
+        // 3. try update post-termination: should time-out waiting for cb
+        publishConfig = new PublishConfig.Builder().setServiceName(
+                serviceName).setServiceSpecificInfo("extras".getBytes()).build();
+        discoverySession.updatePublish(publishConfig);
+        assertFalse("Publish update post terminate", discoveryCb.waitForCallback(
+                DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED));
+
+        session.close();
     }
 
     /**
@@ -554,14 +611,54 @@
         // 3. destroy
         assertFalse("Subscribe not terminated", discoveryCb.hasCallbackAlreadyHappened(
                 DiscoverySessionCallbackTest.ON_SESSION_TERMINATED));
-        discoverySession.destroy();
+        discoverySession.close();
 
         // 4. try update post-destroy: should time-out waiting for cb
         discoverySession.updateSubscribe(subscribeConfig);
         assertFalse("Subscribe update post destroy", discoveryCb.waitForCallback(
                 DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED));
 
-        session.destroy();
+        session.close();
+    }
+
+    /**
+     * Validate that subscribe with a Time To Live (TTL) setting expires within the specified
+     * time (and validates that the terminate callback is triggered).
+     */
+    public void testSubscribeLimitedTtlSuccess() {
+        if (!TestUtils.shouldTestWifiAware(getContext())) {
+            return;
+        }
+
+        final String serviceName = "ValidName";
+        final int ttlSec = 5;
+
+        WifiAwareSession session = attachAndGetSession();
+
+        SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(
+                serviceName).setTtlSec(ttlSec).setTerminateNotificationEnabled(true).build();
+        DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest();
+
+        // 1. subscribe
+        session.subscribe(subscribeConfig, discoveryCb, mHandler);
+        assertTrue("Subscribe started",
+                discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_SUBSCRIBE_STARTED));
+        SubscribeDiscoverySession discoverySession = discoveryCb.getSubscribeDiscoverySession();
+        assertNotNull("Subscribe session", discoverySession);
+
+        // 2. wait for terminate within 'ttlSec'.
+        assertTrue("Subscribe terminated",
+                discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_SESSION_TERMINATED,
+                        ttlSec + 5));
+
+        // 3. try update post-termination: should time-out waiting for cb
+        subscribeConfig = new SubscribeConfig.Builder().setServiceName(
+                serviceName).setServiceSpecificInfo("extras".getBytes()).build();
+        discoverySession.updateSubscribe(subscribeConfig);
+        assertFalse("Subscribe update post terminate", discoveryCb.waitForCallback(
+                DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED));
+
+        session.close();
     }
 
     /**
@@ -594,8 +691,8 @@
             // empty
         }
 
-        discoverySession.destroy();
-        session.destroy();
+        discoverySession.close();
+        session.close();
     }
 
     /**
@@ -628,8 +725,8 @@
         mConnectivityManager.requestNetwork(nr, networkCb, 2000);
         assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable());
 
-        discoverySession.destroy();
-        session.destroy();
+        discoverySession.close();
+        session.close();
     }
 
     /**
@@ -663,8 +760,8 @@
         mConnectivityManager.requestNetwork(nr, networkCb, 2000);
         assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable());
 
-        discoverySession.destroy();
-        session.destroy();
+        discoverySession.close();
+        session.close();
     }
 
     /**
@@ -691,7 +788,7 @@
         mConnectivityManager.requestNetwork(nr, networkCb, 2000);
         assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable());
 
-        session.destroy();
+        session.close();
     }
 
     /**
@@ -719,7 +816,7 @@
         mConnectivityManager.requestNetwork(nr, networkCb, 2000);
         assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable());
 
-        session.destroy();
+        session.close();
     }
 
     // local utilities
diff --git a/tests/cts/net/src/android/net/wifi/cts/FakeKeys.java b/tests/cts/net/src/android/net/wifi/cts/FakeKeys.java
index f422c2f..f875301 100644
--- a/tests/cts/net/src/android/net/wifi/cts/FakeKeys.java
+++ b/tests/cts/net/src/android/net/wifi/cts/FakeKeys.java
@@ -73,6 +73,26 @@
             "-----END CERTIFICATE-----\n";
     public static final X509Certificate CA_CERT1 = loadCertificate(CA_CERT1_STRING);
 
+    private static final String CA_PUBLIC_CERT_STRING = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx\n" +
+            "GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds\n" +
+            "b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV\n" +
+            "BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD\n" +
+            "VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa\n" +
+            "DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc\n" +
+            "THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb\n" +
+            "Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP\n" +
+            "c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX\n" +
+            "gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n" +
+            "HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF\n" +
+            "AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj\n" +
+            "Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG\n" +
+            "j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH\n" +
+            "hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC\n" +
+            "X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n" +
+            "-----END CERTIFICATE-----\n";
+    public static final X509Certificate CA_PUBLIC_CERT = loadCertificate(CA_PUBLIC_CERT_STRING);
+
     private static final String CLIENT_CERT_STR = "-----BEGIN CERTIFICATE-----\n" +
             "MIIE/DCCAuQCAQEwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxCzAJBgNV\n" +
             "BAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdUZXN0aW5n\n" +
diff --git a/tests/cts/net/src/android/net/wifi/cts/PpsMoParserTest.java b/tests/cts/net/src/android/net/wifi/cts/PpsMoParserTest.java
index b5e2f77..feafd43 100644
--- a/tests/cts/net/src/android/net/wifi/cts/PpsMoParserTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/PpsMoParserTest.java
@@ -20,8 +20,6 @@
 import android.net.wifi.hotspot2.omadm.PpsMoParser;
 import android.net.wifi.hotspot2.pps.Credential;
 import android.net.wifi.hotspot2.pps.HomeSp;
-import android.net.wifi.hotspot2.pps.Policy;
-import android.net.wifi.hotspot2.pps.UpdateParameter;
 import android.test.AndroidTestCase;
 
 import java.io.BufferedReader;
@@ -72,58 +70,6 @@
         Arrays.fill(certFingerprint, (byte) 0x1f);
 
         PasspointConfiguration config = new PasspointConfiguration();
-        config.setUpdateIdentifier(12);
-        assertEquals(12, config.getUpdateIdentifier());
-        config.setCredentialPriority(99);
-        assertEquals(99, config.getCredentialPriority());
-
-        // AAA Server trust root.
-        Map<String, byte[]> trustRootCertList = new HashMap<>();
-        trustRootCertList.put("server1.trust.root.com", certFingerprint);
-        config.setTrustRootCertList(trustRootCertList);
-        assertEquals(trustRootCertList, config.getTrustRootCertList());
-
-        // Subscription update.
-        UpdateParameter subscriptionUpdate = new UpdateParameter();
-        subscriptionUpdate.setUpdateIntervalInMinutes(120);
-        assertEquals(120, subscriptionUpdate.getUpdateIntervalInMinutes());
-        subscriptionUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP);
-        assertEquals(UpdateParameter.UPDATE_METHOD_SSP, subscriptionUpdate.getUpdateMethod());
-        subscriptionUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER);
-        assertEquals(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER,
-                subscriptionUpdate.getRestriction());
-        subscriptionUpdate.setServerUri("subscription.update.com");
-        assertEquals("subscription.update.com", subscriptionUpdate.getServerUri());
-        subscriptionUpdate.setUsername("subscriptionUser");
-        assertEquals("subscriptionUser", subscriptionUpdate.getUsername());
-        subscriptionUpdate.setBase64EncodedPassword("subscriptionPass");
-        assertEquals("subscriptionPass", subscriptionUpdate.getBase64EncodedPassword());
-        subscriptionUpdate.setTrustRootCertUrl("subscription.update.cert.com");
-        assertEquals("subscription.update.cert.com", subscriptionUpdate.getTrustRootCertUrl());
-        subscriptionUpdate.setTrustRootCertSha256Fingerprint(certFingerprint);
-        assertTrue(Arrays.equals(certFingerprint,
-                subscriptionUpdate.getTrustRootCertSha256Fingerprint()));
-        config.setSubscriptionUpdate(subscriptionUpdate);
-        assertEquals(subscriptionUpdate, config.getSubscriptionUpdate());
-
-        // Subscription parameters.
-        config.setSubscriptionCreationTimeInMs(format.parse("2016-02-01T10:00:00Z").getTime());
-        assertEquals(format.parse("2016-02-01T10:00:00Z").getTime(),
-                config.getSubscriptionCreationTimeInMs());
-        config.setSubscriptionExpirationTimeInMs(format.parse("2016-03-01T10:00:00Z").getTime());
-        assertEquals(format.parse("2016-03-01T10:00:00Z").getTime(),
-                config.getSubscriptionExpirationTimeInMs());
-        config.setSubscriptionType("Gold");
-        assertEquals("Gold", config.getSubscriptionType());
-        config.setUsageLimitDataLimit(921890);
-        assertEquals(921890, config.getUsageLimitDataLimit());
-        config.setUsageLimitStartTimeInMs(format.parse("2016-12-01T10:00:00Z").getTime());
-        assertEquals(format.parse("2016-12-01T10:00:00Z").getTime(),
-                config.getUsageLimitStartTimeInMs());
-        config.setUsageLimitTimeLimitInMinutes(120);
-        assertEquals(120, config.getUsageLimitTimeLimitInMinutes());
-        config.setUsageLimitUsageTimePeriodInMinutes(99910);
-        assertEquals(99910, config.getUsageLimitUsageTimePeriodInMinutes());
 
         // HomeSP configuration.
         HomeSp homeSp = new HomeSp();
@@ -134,46 +80,18 @@
         homeSp.setRoamingConsortiumOis(new long[] {0x112233L, 0x445566L});
         assertTrue(Arrays.equals(new long[] {0x112233L, 0x445566L},
                 homeSp.getRoamingConsortiumOis()));
-        homeSp.setIconUrl("icon.test.com");
-        assertEquals("icon.test.com", homeSp.getIconUrl());
-        Map<String, Long> homeNetworkIds = new HashMap<>();
-        homeNetworkIds.put("TestSSID", 0x12345678L);
-        homeNetworkIds.put("NullHESSID", null);
-        homeSp.setHomeNetworkIds(homeNetworkIds);
-        assertEquals(homeNetworkIds, homeSp.getHomeNetworkIds());
-        homeSp.setMatchAllOis(new long[] {0x11223344});
-        assertTrue(Arrays.equals(new long[] {0x11223344}, homeSp.getMatchAllOis()));
-        homeSp.setMatchAnyOis(new long[] {0x55667788});
-        assertTrue(Arrays.equals(new long[] {0x55667788}, homeSp.getMatchAnyOis()));
-        homeSp.setOtherHomePartners(new String[] {"other.fqdn.com"});
-        assertTrue(Arrays.equals(new String[] {"other.fqdn.com"},
-                homeSp.getOtherHomePartners()));
         config.setHomeSp(homeSp);
         assertEquals(homeSp, config.getHomeSp());
 
         // Credential configuration.
         Credential credential = new Credential();
-        credential.setCreationTimeInMs(format.parse("2016-01-01T10:00:00Z").getTime());
-        assertEquals(format.parse("2016-01-01T10:00:00Z").getTime(),
-                credential.getCreationTimeInMs());
-        credential.setExpirationTimeInMs(format.parse("2016-02-01T10:00:00Z").getTime());
-        assertEquals(format.parse("2016-02-01T10:00:00Z").getTime(),
-                credential.getExpirationTimeInMs());
         credential.setRealm("shaken.stirred.com");
         assertEquals("shaken.stirred.com", credential.getRealm());
-        credential.setCheckAaaServerCertStatus(true);
-        assertTrue(credential.getCheckAaaServerCertStatus());
         Credential.UserCredential userCredential = new Credential.UserCredential();
         userCredential.setUsername("james");
         assertEquals("james", userCredential.getUsername());
         userCredential.setPassword("Ym9uZDAwNw==");
         assertEquals("Ym9uZDAwNw==", userCredential.getPassword());
-        userCredential.setMachineManaged(true);
-        assertTrue(userCredential.getMachineManaged());
-        userCredential.setSoftTokenApp("TestApp");
-        assertEquals("TestApp", userCredential.getSoftTokenApp());
-        userCredential.setAbleToShare(true);
-        assertTrue(userCredential.getAbleToShare());
         userCredential.setEapType(21);
         assertEquals(21, userCredential.getEapType());
         userCredential.setNonEapInnerMethod("MS-CHAP-V2");
@@ -196,70 +114,6 @@
         assertEquals(simCredential, credential.getSimCredential());
         config.setCredential(credential);
         assertEquals(credential, config.getCredential());
-
-        // Policy configuration.
-        Policy policy = new Policy();
-        List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>();
-        Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
-        partner1.setFqdn("test1.fqdn.com");
-        assertEquals("test1.fqdn.com", partner1.getFqdn());
-        partner1.setFqdnExactMatch(true);
-        assertTrue(partner1.getFqdnExactMatch());
-        partner1.setPriority(127);
-        assertEquals(127, partner1.getPriority());
-        partner1.setCountries("us,fr");
-        assertEquals("us,fr", partner1.getCountries());
-        Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
-        partner2.setFqdn("test2.fqdn.com");
-        assertEquals("test2.fqdn.com", partner2.getFqdn());
-        partner2.setFqdnExactMatch(false);
-        assertFalse(partner2.getFqdnExactMatch());
-        partner2.setPriority(200);
-        assertEquals(200, partner2.getPriority());
-        partner2.setCountries("*");
-        assertEquals("*", partner2.getCountries());
-        preferredRoamingPartnerList.add(partner1);
-        preferredRoamingPartnerList.add(partner2);
-        policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList);
-        assertEquals(preferredRoamingPartnerList, policy.getPreferredRoamingPartnerList());
-        policy.setMinHomeDownlinkBandwidth(23412);
-        assertEquals(23412, policy.getMinHomeDownlinkBandwidth());
-        policy.setMinHomeUplinkBandwidth(9823);
-        assertEquals(9823, policy.getMinHomeUplinkBandwidth());
-        policy.setMinRoamingDownlinkBandwidth(9271);
-        assertEquals(9271, policy.getMinRoamingDownlinkBandwidth());
-        policy.setMinRoamingUplinkBandwidth(2315);
-        assertEquals(2315, policy.getMinRoamingUplinkBandwidth());
-        policy.setExcludedSsidList(new String[] {"excludeSSID"});
-        assertTrue(Arrays.equals(new String[] {"excludeSSID"}, policy.getExcludedSsidList()));
-        Map<Integer, String> requiredProtoPortMap = new HashMap<>();
-        requiredProtoPortMap.put(12, "34,92,234");
-        policy.setRequiredProtoPortMap(requiredProtoPortMap);
-        assertEquals(requiredProtoPortMap, policy.getRequiredProtoPortMap());
-        policy.setMaximumBssLoadValue(23);
-        assertEquals(23, policy.getMaximumBssLoadValue());
-        UpdateParameter policyUpdate = new UpdateParameter();
-        policyUpdate.setUpdateIntervalInMinutes(120);
-        assertEquals(120, policyUpdate.getUpdateIntervalInMinutes());
-        policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
-        assertEquals(UpdateParameter.UPDATE_METHOD_OMADM, policyUpdate.getUpdateMethod());
-        policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
-        assertEquals(UpdateParameter.UPDATE_RESTRICTION_HOMESP, policyUpdate.getRestriction());
-        policyUpdate.setServerUri("policy.update.com");
-        assertEquals("policy.update.com", policyUpdate.getServerUri());
-        policyUpdate.setUsername("updateUser");
-        assertEquals("updateUser", policyUpdate.getUsername());
-        policyUpdate.setBase64EncodedPassword("updatePass");
-        assertEquals("updatePass", policyUpdate.getBase64EncodedPassword());
-        policyUpdate.setTrustRootCertUrl("update.cert.com");
-        assertEquals("update.cert.com", policyUpdate.getTrustRootCertUrl());
-        policyUpdate.setTrustRootCertSha256Fingerprint(certFingerprint);
-        assertTrue(Arrays.equals(certFingerprint,
-                policyUpdate.getTrustRootCertSha256Fingerprint()));
-        policy.setPolicyUpdate(policyUpdate);
-        assertEquals(policyUpdate, policy.getPolicyUpdate());
-        config.setPolicy(policy);
-        assertEquals(policy, config.getPolicy());
         return config;
     }
 
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java
index 696d215..5983cb7 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.cts.util.PollingCheck;
 import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
@@ -29,6 +28,8 @@
 import android.net.wifi.WifiSsid;
 import android.test.AndroidTestCase;
 
+import com.android.compatibility.common.util.PollingCheck;
+
 import java.util.concurrent.Callable;
 
 public class WifiInfoTest extends AndroidTestCase {
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
index f05ff82..33c184a 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -188,6 +188,7 @@
     private void startScan() throws Exception {
         synchronized (mMySync) {
             mMySync.expectedState = STATE_SCANNING;
+            mScanResults = null;
             assertTrue(mWifiManager.startScan());
             long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
             while (System.currentTimeMillis() < timeout && mMySync.expectedState == STATE_SCANNING)
@@ -239,11 +240,17 @@
         assertTrue(mWifiManager.reconnect());
         assertTrue(mWifiManager.reassociate());
         assertTrue(mWifiManager.disconnect());
-        assertTrue(mWifiManager.pingSupplicant());
-        startScan();
         setWifiEnabled(false);
+        startScan();
         Thread.sleep(DURATION);
-        assertTrue(mWifiManager.pingSupplicant() == mWifiManager.isScanAlwaysAvailable());
+        if (mWifiManager.isScanAlwaysAvailable()) {
+            // Make sure at least one AP is found.
+            assertNotNull("mScanResult should not be null!", mScanResults);
+            assertFalse("empty scan results!", mScanResults.isEmpty());
+        } else {
+            // Make sure no scan results are available.
+            assertNull("mScanResult should be null!", mScanResults);
+        }
         final String TAG = "Test";
         assertNotNull(mWifiManager.createWifiLock(TAG));
         assertNotNull(mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG));
@@ -592,6 +599,7 @@
         HomeSp homeSp = new HomeSp();
         homeSp.setFqdn("Test.com");
         homeSp.setFriendlyName("Test Provider");
+        homeSp.setRoamingConsortiumOis(new long[] {0x11223344});
         config.setHomeSp(homeSp);
 
         return config;
@@ -611,7 +619,7 @@
         userCred.setPassword("password");
         userCred.setNonEapInnerMethod("PAP");
         credential.setUserCredential(userCred);
-        credential.setCaCertificate(FakeKeys.CA_CERT0);
+        credential.setCaCertificate(FakeKeys.CA_PUBLIC_CERT);
         return credential;
     }
 
@@ -628,7 +636,7 @@
         certCredential.setCertSha256Fingerprint(
                 MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded()));
         credential.setCertCredential(certCredential);
-        credential.setCaCertificate(FakeKeys.CA_CERT0);
+        credential.setCaCertificate(FakeKeys.CA_PUBLIC_CERT);
         credential.setClientCertificateChain(new X509Certificate[] {FakeKeys.CLIENT_CERT});
         credential.setClientPrivateKey(FakeKeys.RSA_KEY1);
         return credential;
@@ -656,22 +664,26 @@
      * @param config The configuration to test with
      */
     private void testAddPasspointConfig(PasspointConfiguration config) throws Exception {
-        mWifiManager.addOrUpdatePasspointConfiguration(config);
+        try {
+            mWifiManager.addOrUpdatePasspointConfiguration(config);
 
-        // Certificates and keys will be set to null after it is installed to the KeyStore by
-        // WifiManager.  Reset them in the expected config so that it can be used to compare
-        // against the retrieved config.
-        config.getCredential().setCaCertificate(null);
-        config.getCredential().setClientCertificateChain(null);
-        config.getCredential().setClientPrivateKey(null);
+            // Certificates and keys will be set to null after it is installed to the KeyStore by
+            // WifiManager.  Reset them in the expected config so that it can be used to compare
+            // against the retrieved config.
+            config.getCredential().setCaCertificate(null);
+            config.getCredential().setClientCertificateChain(null);
+            config.getCredential().setClientPrivateKey(null);
 
-        // Retrieve the configuration and verify it.
-        List<PasspointConfiguration> configList = mWifiManager.getPasspointConfigurations();
-        assertEquals(1, configList.size());
-        assertEquals(config, configList.get(0));
+            // Retrieve the configuration and verify it.
+            List<PasspointConfiguration> configList = mWifiManager.getPasspointConfigurations();
+            assertEquals(1, configList.size());
+            assertEquals(config, configList.get(0));
 
-        // Remove the configuration and verify no installed configuration.
-        mWifiManager.removePasspointConfiguration(config.getHomeSp().getFqdn());
-        assertTrue(mWifiManager.getPasspointConfigurations().isEmpty());
+            // Remove the configuration and verify no installed configuration.
+            mWifiManager.removePasspointConfiguration(config.getHomeSp().getFqdn());
+            assertTrue(mWifiManager.getPasspointConfigurations().isEmpty());
+        } catch (UnsupportedOperationException e) {
+            // Passpoint build config |config_wifi_hotspot2_enabled| is disabled, so noop.
+        }
     }
 }