Merge "Add IpConfigurationTest for new @SystemApi" into rvc-dev
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
index b6f5142..a8cc95b 100644
--- a/tests/cts/hostside/Android.bp
+++ b/tests/cts/hostside/Android.bp
@@ -25,6 +25,7 @@
     test_suites: [
         "cts",
         "vts",
+        "vts10",
         "general-tests",
     ],
 }
diff --git a/tests/cts/hostside/app/Android.bp b/tests/cts/hostside/app/Android.bp
index e988ea4..8b6d38b 100644
--- a/tests/cts/hostside/app/Android.bp
+++ b/tests/cts/hostside/app/Android.bp
@@ -36,6 +36,7 @@
     test_suites: [
         "cts",
         "vts",
+        "vts10",
         "general-tests",
     ],
 }
diff --git a/tests/cts/hostside/app2/Android.bp b/tests/cts/hostside/app2/Android.bp
index 8a3c8e7..0bb0d2f 100644
--- a/tests/cts/hostside/app2/Android.bp
+++ b/tests/cts/hostside/app2/Android.bp
@@ -24,6 +24,7 @@
     test_suites: [
         "cts",
         "vts",
+        "vts10",
         "general-tests",
     ],
     certificate: ":cts-net-app",
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index 624d149..d77f416 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -65,6 +65,7 @@
     test_suites: [
         "cts",
         "vts",
+        "vts10",
         "general-tests",
     ],
     test_config_template: "AndroidTestTemplate.xml",
diff --git a/tests/cts/net/api23Test/Android.bp b/tests/cts/net/api23Test/Android.bp
index ffe854e..614a5a2 100644
--- a/tests/cts/net/api23Test/Android.bp
+++ b/tests/cts/net/api23Test/Android.bp
@@ -46,6 +46,7 @@
     test_suites: [
         "cts",
         "vts",
+        "vts10",
         "general-tests",
     ],
 
diff --git a/tests/cts/net/appForApi23/Android.bp b/tests/cts/net/appForApi23/Android.bp
index 82e2a08..17cfe38 100644
--- a/tests/cts/net/appForApi23/Android.bp
+++ b/tests/cts/net/appForApi23/Android.bp
@@ -27,6 +27,7 @@
     test_suites: [
         "cts",
         "vts",
+        "vts10",
         "general-tests",
     ],
 
diff --git a/tests/cts/net/native/qtaguid/Android.bp b/tests/cts/net/native/qtaguid/Android.bp
index c0f0613..054937b 100644
--- a/tests/cts/net/native/qtaguid/Android.bp
+++ b/tests/cts/net/native/qtaguid/Android.bp
@@ -43,6 +43,7 @@
     test_suites: [
         "cts",
         "vts",
+        "vts10",
     ],
 
     cflags: [
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 5eb3e36..8f23324 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
@@ -16,7 +16,9 @@
 
 package android.net.wifi.aware.cts;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.mockito.Mockito.mock;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -30,17 +32,21 @@
 import android.net.wifi.WifiManager;
 import android.net.wifi.aware.AttachCallback;
 import android.net.wifi.aware.Characteristics;
+import android.net.wifi.aware.DiscoverySession;
 import android.net.wifi.aware.DiscoverySessionCallback;
 import android.net.wifi.aware.IdentityChangedListener;
+import android.net.wifi.aware.ParcelablePeerHandle;
 import android.net.wifi.aware.PeerHandle;
 import android.net.wifi.aware.PublishConfig;
 import android.net.wifi.aware.PublishDiscoverySession;
 import android.net.wifi.aware.SubscribeConfig;
 import android.net.wifi.aware.SubscribeDiscoverySession;
 import android.net.wifi.aware.WifiAwareManager;
+import android.net.wifi.aware.WifiAwareNetworkSpecifier;
 import android.net.wifi.aware.WifiAwareSession;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.Parcel;
 import android.platform.test.annotations.AppModeFull;
 import android.test.AndroidTestCase;
 
@@ -64,6 +70,9 @@
 
     // wait for Wi-Fi Aware state changes & network requests callbacks
     static private final int WAIT_FOR_AWARE_CHANGE_SECS = 10; // 10 seconds
+    private static final int MIN_DISTANCE_MM = 1 * 1000;
+    private static final int MAX_DISTANCE_MM = 3 * 1000;
+    private static final byte[] PMK_VALID = "01234567890123456789012345678901".getBytes();
 
     private final Object mLock = new Object();
     private final HandlerThread mHandlerThread = new HandlerThread("SingleDeviceTest");
@@ -615,7 +624,8 @@
 
         // 2. update-subscribe
         subscribeConfig = new SubscribeConfig.Builder().setServiceName(
-                serviceName).setServiceSpecificInfo("extras".getBytes()).build();
+                serviceName).setServiceSpecificInfo("extras".getBytes())
+                .setMinDistanceMm(MIN_DISTANCE_MM).build();
         discoverySession.updateSubscribe(subscribeConfig);
         assertTrue("Subscribe update", discoveryCb.waitForCallback(
                 DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED));
@@ -741,7 +751,8 @@
     }
 
     /**
-     * Request an Aware data-path (encrypted) as a Responder with an arbitrary peer MAC address.
+     * Request an Aware data-path (encrypted with Passphrase) as a Responder with an arbitrary peer
+     * MAC address.
      * Validate that receive an onUnavailable() callback.
      */
     public void testDataPathPassphraseOutOfBandFail() {
@@ -773,6 +784,77 @@
         session.close();
     }
 
+    /**
+     * Request an Aware data-path (encrypted with PMK) as a Responder with an arbitrary peer MAC
+     * address.
+     * Validate that receive an onUnavailable() callback.
+     */
+    public void testDataPathPmkOutOfBandFail() {
+        if (!TestUtils.shouldTestWifiAware(getContext())) {
+            return;
+        }
+        MacAddress mac = MacAddress.fromString("00:01:02:03:04:05");
+
+        // 1. initialize Aware: only purpose is to make sure it is available for OOB data-path
+        WifiAwareSession session = attachAndGetSession();
+
+        PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(
+                "ValidName").build();
+        DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest();
+        session.publish(publishConfig, discoveryCb, mHandler);
+        assertTrue("Publish started",
+                discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_PUBLISH_STARTED));
+
+        // 2. request an AWARE network
+        NetworkCallbackTest networkCb = new NetworkCallbackTest();
+        NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
+                NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
+                session.createNetworkSpecifierPmk(
+                        WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, mac.toByteArray(),
+                        PMK_VALID)).build();
+        mConnectivityManager.requestNetwork(nr, networkCb);
+        assertTrue("OnUnavailable not received", networkCb.waitForOnUnavailable());
+
+        session.close();
+    }
+
+    /**
+     * Test WifiAwareNetworkSpecifier.
+     */
+    public void testWifiAwareNetworkSpecifier() {
+        DiscoverySession session = mock(DiscoverySession.class);
+        PeerHandle handle = mock(PeerHandle.class);
+        WifiAwareNetworkSpecifier networkSpecifier =
+                new WifiAwareNetworkSpecifier.Builder(session, handle).build();
+        assertFalse(networkSpecifier.satisfiedBy(null));
+        assertTrue(networkSpecifier.satisfiedBy(networkSpecifier));
+
+        WifiAwareNetworkSpecifier anotherNetworkSpecifier =
+                new WifiAwareNetworkSpecifier.Builder(session, handle).setPmk(PMK_VALID).build();
+        assertFalse(networkSpecifier.satisfiedBy(anotherNetworkSpecifier));
+    }
+
+    /**
+     * Test ParcelablePeerHandle parcel.
+     */
+    public void testParcelablePeerHandle() {
+        PeerHandle peerHandle = mock(PeerHandle.class);
+        ParcelablePeerHandle parcelablePeerHandle = new ParcelablePeerHandle(peerHandle);
+        Parcel parcelW = Parcel.obtain();
+        parcelablePeerHandle.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        ParcelablePeerHandle rereadParcelablePeerHandle =
+                ParcelablePeerHandle.CREATOR.createFromParcel(parcelR);
+
+        assertEquals(parcelablePeerHandle, rereadParcelablePeerHandle);
+        assertEquals(parcelablePeerHandle.hashCode(), rereadParcelablePeerHandle.hashCode());
+    }
+
     // local utilities
 
     private WifiAwareSession attachAndGetSession() {
diff --git a/tests/cts/net/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java b/tests/cts/net/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
new file mode 100644
index 0000000..ce5bb81
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/cts/ConnectedNetworkScorerTest.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.cts;
+
+import static android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_FAILURE;
+import static android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_NO_PROBE;
+import static android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_SUCCESS;
+import static android.net.wifi.WifiUsabilityStatsEntry.PROBE_STATUS_UNKNOWN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.UiAutomation;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiUsabilityStatsEntry;
+import android.support.test.uiautomator.UiDevice;
+import android.telephony.TelephonyManager;
+import android.test.AndroidTestCase;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.ShellIdentityUtils;
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+public class ConnectedNetworkScorerTest extends AndroidTestCase {
+    private WifiManager mWifiManager;
+    private UiDevice mUiDevice;
+    private boolean mWasVerboseLoggingEnabled;
+
+    private static final int DURATION = 10_000;
+    private static final int DURATION_SCREEN_TOGGLE = 2000;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        mWifiManager = getContext().getSystemService(WifiManager.class);
+        assertThat(mWifiManager).isNotNull();
+
+        // turn on verbose logging for tests
+        mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.isVerboseLoggingEnabled());
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setVerboseLoggingEnabled(true));
+
+        if (!mWifiManager.isWifiEnabled()) setWifiEnabled(true);
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        turnScreenOn();
+        PollingCheck.check("Wifi not enabled", DURATION, () -> mWifiManager.isWifiEnabled());
+        List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.getConfiguredNetworks());
+        assertFalse("Need at least one saved network", savedNetworks.isEmpty());
+        // Wait for wifi is to be connected
+        PollingCheck.check(
+                "Wifi not connected",
+                DURATION,
+                () -> mWifiManager.getConnectionInfo().getNetworkId() != -1);
+        assertThat(mWifiManager.getConnectionInfo().getNetworkId()).isNotEqualTo(-1);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            super.tearDown();
+            return;
+        }
+        if (!mWifiManager.isWifiEnabled()) setWifiEnabled(true);
+        turnScreenOff();
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
+        super.tearDown();
+    }
+
+    private void setWifiEnabled(boolean enable) throws Exception {
+        // now trigger the change using shell commands.
+        SystemUtil.runShellCommand("svc wifi " + (enable ? "enable" : "disable"));
+    }
+
+    private void turnScreenOn() throws Exception {
+        mUiDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        mUiDevice.executeShellCommand("wm dismiss-keyguard");
+        // Since the screen on/off intent is ordered, they will not be sent right now.
+        Thread.sleep(DURATION_SCREEN_TOGGLE);
+    }
+
+    private void turnScreenOff() throws Exception {
+        mUiDevice.executeShellCommand("input keyevent KEYCODE_SLEEP");
+    }
+
+    private static class TestUsabilityStatsListener implements
+            WifiManager.OnWifiUsabilityStatsListener {
+        private final CountDownLatch mCountDownLatch;
+        public int seqNum;
+        public boolean isSameBssidAndFre;
+        public WifiUsabilityStatsEntry statsEntry;
+
+        TestUsabilityStatsListener(CountDownLatch countDownLatch) {
+            mCountDownLatch = countDownLatch;
+        }
+
+        @Override
+        public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq,
+                WifiUsabilityStatsEntry statsEntry) {
+            this.seqNum = seqNum;
+            this.isSameBssidAndFre = isSameBssidAndFreq;
+            this.statsEntry = statsEntry;
+            mCountDownLatch.countDown();
+        }
+    }
+
+    /**
+     * Tests the {@link android.net.wifi.WifiUsabilityStatsEntry} retrieved from
+     * {@link WifiManager.OnWifiUsabilityStatsListener}.
+     */
+    public void testWifiUsabilityStatsEntry() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        CountDownLatch countDownLatch = new CountDownLatch(1);
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        TestUsabilityStatsListener usabilityStatsListener =
+                new TestUsabilityStatsListener(countDownLatch);
+        try {
+            uiAutomation.adoptShellPermissionIdentity();
+            mWifiManager.addOnWifiUsabilityStatsListener(
+                    Executors.newSingleThreadExecutor(), usabilityStatsListener);
+            // Wait for new usability stats (while connected & screen on this is triggered
+            // by platform periodically).
+            assertThat(countDownLatch.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
+
+            assertThat(usabilityStatsListener.statsEntry).isNotNull();
+            WifiUsabilityStatsEntry statsEntry = usabilityStatsListener.statsEntry;
+
+            assertThat(statsEntry.getTimeStampMillis()).isGreaterThan(0L);
+            assertThat(statsEntry.getRssi()).isLessThan(0);
+            assertThat(statsEntry.getLinkSpeedMbps()).isGreaterThan(0);
+            assertThat(statsEntry.getTotalTxSuccess()).isGreaterThan(0L);
+            assertThat(statsEntry.getTotalTxRetries()).isAtLeast(0L);
+            assertThat(statsEntry.getTotalTxBad()).isAtLeast(0L);
+            assertThat(statsEntry.getTotalRxSuccess()).isAtLeast(0L);
+            assertThat(statsEntry.getTotalRadioOnTimeMillis()).isGreaterThan(0L);
+            assertThat(statsEntry.getTotalRadioTxTimeMillis()).isGreaterThan(0L);
+            assertThat(statsEntry.getTotalRadioRxTimeMillis()).isGreaterThan(0L);
+            assertThat(statsEntry.getTotalScanTimeMillis()).isGreaterThan(0L);
+            assertThat(statsEntry.getTotalNanScanTimeMillis()).isAtLeast(0L);
+            assertThat(statsEntry.getTotalBackgroundScanTimeMillis()).isAtLeast(0L);
+            assertThat(statsEntry.getTotalRoamScanTimeMillis()).isAtLeast(0L);
+            assertThat(statsEntry.getTotalPnoScanTimeMillis()).isAtLeast(0L);
+            assertThat(statsEntry.getTotalHotspot2ScanTimeMillis()).isAtLeast(0L);
+            assertThat(statsEntry.getTotalCcaBusyFreqTimeMillis()).isAtLeast(0L);
+            assertThat(statsEntry.getTotalRadioOnTimeMillis()).isGreaterThan(0L);
+            assertThat(statsEntry.getTotalBeaconRx()).isGreaterThan(0L);
+            assertThat(statsEntry.getProbeStatusSinceLastUpdate())
+                    .isAnyOf(PROBE_STATUS_SUCCESS,
+                            PROBE_STATUS_FAILURE,
+                            PROBE_STATUS_NO_PROBE,
+                            PROBE_STATUS_UNKNOWN);
+            // -1 is default value for some of these fields if they're not available.
+            assertThat(statsEntry.getProbeElapsedTimeSinceLastUpdateMillis()).isAtLeast(-1);
+            assertThat(statsEntry.getProbeMcsRateSinceLastUpdate()).isAtLeast(-1);
+            assertThat(statsEntry.getRxLinkSpeedMbps()).isAtLeast(-1);
+            // no longer populated, return default value.
+            assertThat(statsEntry.getCellularDataNetworkType())
+                    .isAnyOf(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                            TelephonyManager.NETWORK_TYPE_GPRS,
+                            TelephonyManager.NETWORK_TYPE_EDGE,
+                            TelephonyManager.NETWORK_TYPE_UMTS,
+                            TelephonyManager.NETWORK_TYPE_CDMA,
+                            TelephonyManager.NETWORK_TYPE_EVDO_0,
+                            TelephonyManager.NETWORK_TYPE_EVDO_A,
+                            TelephonyManager.NETWORK_TYPE_1xRTT,
+                            TelephonyManager.NETWORK_TYPE_HSDPA,
+                            TelephonyManager.NETWORK_TYPE_HSUPA,
+                            TelephonyManager.NETWORK_TYPE_HSPA,
+                            TelephonyManager.NETWORK_TYPE_IDEN,
+                            TelephonyManager.NETWORK_TYPE_EVDO_B,
+                            TelephonyManager.NETWORK_TYPE_LTE,
+                            TelephonyManager.NETWORK_TYPE_EHRPD,
+                            TelephonyManager.NETWORK_TYPE_HSPAP,
+                            TelephonyManager.NETWORK_TYPE_GSM,
+                            TelephonyManager.NETWORK_TYPE_TD_SCDMA,
+                            TelephonyManager.NETWORK_TYPE_IWLAN,
+                            TelephonyManager.NETWORK_TYPE_NR);
+            assertThat(statsEntry.getCellularSignalStrengthDbm()).isAtMost(0);
+            assertThat(statsEntry.getCellularSignalStrengthDb()).isAtMost(0);
+            assertThat(statsEntry.isSameRegisteredCell()).isFalse();
+        } finally {
+            mWifiManager.removeOnWifiUsabilityStatsListener(usabilityStatsListener);
+            uiAutomation.dropShellPermissionIdentity();
+        }
+    }
+
+    /**
+     * Tests the {@link android.net.wifi.WifiManager#updateWifiUsabilityScore(int, int, int)}
+     */
+    public void testUpdateWifiUsabilityScore() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        try {
+            uiAutomation.adoptShellPermissionIdentity();
+            // update scoring with dummy values.
+            mWifiManager.updateWifiUsabilityScore(0, 50, 50);
+        } finally {
+            uiAutomation.dropShellPermissionIdentity();
+        }
+    }
+
+    private static class TestConnectedNetworkScorer implements
+            WifiManager.WifiConnectedNetworkScorer {
+        private CountDownLatch mCountDownLatch;
+        public int startSessionId;
+        public int stopSessionId;
+        public WifiManager.ScoreUpdateObserver scoreUpdateObserver;
+
+        TestConnectedNetworkScorer(CountDownLatch countDownLatch) {
+            mCountDownLatch = countDownLatch;
+        }
+
+        @Override
+        public void onStart(int sessionId) {
+            synchronized (mCountDownLatch) {
+                this.startSessionId = sessionId;
+                mCountDownLatch.countDown();
+            }
+        }
+
+        @Override
+        public void onStop(int sessionId) {
+            synchronized (mCountDownLatch) {
+                this.stopSessionId = sessionId;
+                mCountDownLatch.countDown();
+            }
+        }
+
+        @Override
+        public void onSetScoreUpdateObserver(WifiManager.ScoreUpdateObserver observerImpl) {
+            this.scoreUpdateObserver = observerImpl;
+        }
+
+        public void resetCountDownLatch(CountDownLatch countDownLatch) {
+            synchronized (mCountDownLatch) {
+                mCountDownLatch = countDownLatch;
+            }
+        }
+    }
+
+    /**
+     * Tests the {@link android.net.wifi.WifiConnectedNetworkScorer} interface.
+     *
+     * Note: We could write more interesting test cases (if the device has a mobile connection), but
+     * that would make the test flaky. The default network/route selection on the device is not just
+     * controlled by the wifi scorer input, but also based on params which are controlled by
+     * other parts of the platform (likely in connectivity service) and hence will behave
+     * differently on OEM devices.
+     */
+    public void testSetWifiConnectedNetworkScorer() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        CountDownLatch countDownLatchScorer = new CountDownLatch(1);
+        CountDownLatch countDownLatchUsabilityStats = new CountDownLatch(1);
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        TestConnectedNetworkScorer connectedNetworkScorer =
+                new TestConnectedNetworkScorer(countDownLatchScorer);
+        TestUsabilityStatsListener usabilityStatsListener =
+                new TestUsabilityStatsListener(countDownLatchUsabilityStats);
+        try {
+            uiAutomation.adoptShellPermissionIdentity();
+            mWifiManager.setWifiConnectedNetworkScorer(
+                    Executors.newSingleThreadExecutor(), connectedNetworkScorer);
+            // Since we're already connected, wait for onStart to be invoked.
+            assertThat(countDownLatchScorer.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
+
+            assertThat(connectedNetworkScorer.startSessionId).isAtLeast(0);
+            assertThat(connectedNetworkScorer.scoreUpdateObserver).isNotNull();
+            WifiManager.ScoreUpdateObserver scoreUpdateObserver =
+                    connectedNetworkScorer.scoreUpdateObserver;
+
+            // Now trigger a dummy score update.
+            scoreUpdateObserver.notifyScoreUpdate(connectedNetworkScorer.startSessionId, 50);
+
+            // Register the usability listener
+            mWifiManager.addOnWifiUsabilityStatsListener(
+                    Executors.newSingleThreadExecutor(), usabilityStatsListener);
+            // Trigger a usability stats update.
+            scoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(
+                    connectedNetworkScorer.startSessionId);
+            // Ensure that we got the stats update callback.
+            assertThat(countDownLatchUsabilityStats.await(DURATION, TimeUnit.MILLISECONDS))
+                    .isTrue();
+            assertThat(usabilityStatsListener.seqNum).isAtLeast(0);
+
+            // Reset the scorer countdown latch for onStop
+            countDownLatchScorer = new CountDownLatch(1);
+            connectedNetworkScorer.resetCountDownLatch(countDownLatchScorer);
+            // Now disconnect from the network.
+            mWifiManager.disconnect();
+            // Wait for it to be disconnected.
+            PollingCheck.check(
+                    "Wifi not disconnected",
+                    DURATION,
+                    () -> mWifiManager.getConnectionInfo().getNetworkId() == -1);
+            assertThat(mWifiManager.getConnectionInfo().getNetworkId()).isEqualTo(-1);
+
+            // Wait for stop to be invoked and ensure that the session id matches.
+            assertThat(countDownLatchScorer.await(DURATION, TimeUnit.MILLISECONDS)).isTrue();
+            assertThat(connectedNetworkScorer.stopSessionId)
+                    .isEqualTo(connectedNetworkScorer.startSessionId);
+        } finally {
+            mWifiManager.removeOnWifiUsabilityStatsListener(usabilityStatsListener);
+            mWifiManager.clearWifiConnectedNetworkScorer();
+            uiAutomation.dropShellPermissionIdentity();
+        }
+    }
+}
diff --git a/tests/cts/net/src/android/net/wifi/cts/ScanResultTest.java b/tests/cts/net/src/android/net/wifi/cts/ScanResultTest.java
index 161b0b4..1977378 100644
--- a/tests/cts/net/src/android/net/wifi/cts/ScanResultTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/ScanResultTest.java
@@ -34,6 +34,7 @@
 import android.platform.test.annotations.AppModeFull;
 import android.test.AndroidTestCase;
 
+import com.android.compatibility.common.util.ShellIdentityUtils;
 import com.android.compatibility.common.util.SystemUtil;
 
 @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@@ -45,6 +46,8 @@
     private WifiManager mWifiManager;
     private WifiLock mWifiLock;
     private static MySync mMySync;
+    private boolean mWasVerboseLoggingEnabled;
+    private boolean mWasScanThrottleEnabled;
 
     private static final int STATE_NULL = 0;
     private static final int STATE_WIFI_CHANGING = 1;
@@ -113,6 +116,18 @@
         mContext.registerReceiver(mReceiver, mIntentFilter);
         mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
         assertThat(mWifiManager).isNotNull();
+
+        // turn on verbose logging for tests
+        mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.isVerboseLoggingEnabled());
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setVerboseLoggingEnabled(true));
+        // Disable scan throttling for tests.
+        mWasScanThrottleEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.isScanThrottleEnabled());
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setScanThrottleEnabled(false));
+
         mWifiLock = mWifiManager.createWifiLock(TAG);
         mWifiLock.acquire();
         if (!mWifiManager.isWifiEnabled())
@@ -133,6 +148,10 @@
         mContext.unregisterReceiver(mReceiver);
         if (!mWifiManager.isWifiEnabled())
             setWifiEnabled(true);
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setScanThrottleEnabled(mWasScanThrottleEnabled));
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
         Thread.sleep(ENABLE_WAIT_MSEC);
         super.tearDown();
     }
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiFeature.java b/tests/cts/net/src/android/net/wifi/cts/WifiFeature.java
index 63fa1dd..3e9fef4 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiFeature.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiFeature.java
@@ -20,12 +20,12 @@
 import android.content.pm.PackageManager;
 
 public class WifiFeature {
-    static boolean isWifiSupported(Context context) {
+    public static boolean isWifiSupported(Context context) {
         PackageManager packageManager = context.getPackageManager();
         return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
     }
 
-    static boolean isP2pSupported(Context context) {
+    public static boolean isP2pSupported(Context context) {
         PackageManager packageManager = context.getPackageManager();
         return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT);
     }
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiHotspot2Test.java b/tests/cts/net/src/android/net/wifi/cts/WifiHotspot2Test.java
index 96e1caa..a05b81b 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiHotspot2Test.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiHotspot2Test.java
@@ -18,23 +18,45 @@
 
 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE;
 
+import android.net.Uri;
+import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.hotspot2.pps.Credential;
 import android.net.wifi.hotspot2.pps.HomeSp;
 import android.test.AndroidTestCase;
+import android.text.TextUtils;
 
+import java.lang.reflect.Constructor;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 
 public class WifiHotspot2Test extends AndroidTestCase {
     static final int SIM_CREDENTIAL = 0;
     static final int USER_CREDENTIAL = 1;
     static final int CERT_CREDENTIAL = 2;
-
+    private static final String TEST_SSID = "TEST SSID";
+    private static final String TEST_FRIENDLY_NAME = "Friendly Name";
+    private static final Map<String, String> TEST_FRIENDLY_NAMES =
+            new HashMap<String, String>() {
+                {
+                    put("en", TEST_FRIENDLY_NAME);
+                    put("kr", TEST_FRIENDLY_NAME + 2);
+                    put("jp", TEST_FRIENDLY_NAME + 3);
+                }
+            };
+    private static final String TEST_SERVICE_DESCRIPTION = "Dummy Service";
+    private static final Uri TEST_SERVER_URI = Uri.parse("https://test.com");
+    private static final String TEST_NAI = "test.access.com";
+    private static final List<Integer> TEST_METHOD_LIST =
+            Arrays.asList(1 /* METHOD_SOAP_XML_SPP */);
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -434,4 +456,33 @@
         return createCredential(userCred, null, null, null, null,
                 FakeKeys.CA_CERT0);
     }
+
+    /**
+     * Tests {@link OsuProvider#getFriendlyName()} and {@link OsuProvider#getServerUri()} methods.
+     * <p>
+     * Test that getting a set friendly name and server URI produces the same value
+     */
+    public void testOsuProviderGetters() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+
+        // Using Java reflection to construct an OsuProvider instance because its constructor is
+        // hidden and not available to apps.
+        Class<?> osuProviderClass = Class.forName("android.net.wifi.hotspot2.OsuProvider");
+        Constructor<?> osuProviderClassConstructor = osuProviderClass.getConstructor(String.class,
+                Map.class, String.class, Uri.class, String.class, List.class);
+
+        OsuProvider osuProvider = (OsuProvider) osuProviderClassConstructor.newInstance(TEST_SSID,
+                TEST_FRIENDLY_NAMES, TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI,
+                TEST_METHOD_LIST);
+        String lang = Locale.getDefault().getLanguage();
+        String friendlyName = TEST_FRIENDLY_NAMES.get(lang);
+        if (TextUtils.isEmpty(friendlyName)) {
+            friendlyName = TEST_FRIENDLY_NAMES.get("en");
+        }
+        assertEquals(friendlyName, osuProvider.getFriendlyName());
+        assertEquals(TEST_SERVER_URI, osuProvider.getServerUri());
+    }
 }
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 2e3f188..3153149 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -32,7 +32,6 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.net.util.MacAddressUtils;
 import android.net.ConnectivityManager;
 import android.net.LinkProperties;
 import android.net.MacAddress;
@@ -40,15 +39,28 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkRequest;
+import android.net.TetheringManager;
+import android.net.Uri;
+import android.net.util.MacAddressUtils;
 import android.net.wifi.ScanResult;
+import android.net.wifi.SoftApCapability;
 import android.net.wifi.SoftApConfiguration;
+import android.net.wifi.SoftApInfo;
+import android.net.wifi.WifiClient;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiManager.WifiLock;
 import android.net.wifi.WifiNetworkConnectionStatistics;
 import android.net.wifi.hotspot2.ConfigParser;
+import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.ProvisioningCallback;
+import android.net.wifi.hotspot2.pps.Credential;
+import android.net.wifi.hotspot2.pps.HomeSp;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.HandlerThread;
 import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -72,12 +84,18 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.lang.reflect.Constructor;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.Callable;
+import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -92,6 +110,7 @@
 
     private WifiManager mWifiManager;
     private ConnectivityManager mConnectivityManager;
+    private TetheringManager mTetheringManager;
     private WifiLock mWifiLock;
     private static MySync mMySync;
     private List<ScanResult> mScanResults = null;
@@ -99,6 +118,8 @@
     private final Object mLock = new Object();
     private UiDevice mUiDevice;
     private boolean mWasVerboseLoggingEnabled;
+    private boolean mWasScanThrottleEnabled;
+    private SoftApConfiguration mOriginalSoftApConfig = null;
 
     // Please refer to WifiManager
     private static final int MIN_RSSI = -100;
@@ -119,7 +140,7 @@
     private static final int SCAN_TIMEOUT_MSEC = 9000;
     private static final int TIMEOUT_MSEC = 6000;
     private static final int WAIT_MSEC = 60;
-    private static final int DURATION = 10_000;
+    private static final int TEST_WAIT_DURATION_MS = 10_000;
     private static final int DURATION_SCREEN_TOGGLE = 2000;
     private static final int DURATION_SETTINGS_TOGGLE = 1_000;
     private static final int WIFI_SCAN_TEST_INTERVAL_MILLIS = 60 * 1000;
@@ -179,6 +200,54 @@
             }
         }
     };
+    // Initialize with an invalid status value (0)
+    private int mProvisioningStatus = 0;
+    // Initialize with an invalid status value (0)
+    private int mProvisioningFailureStatus = 0;
+    private boolean mProvisioningComplete = false;
+    private ProvisioningCallback mProvisioningCallback = new ProvisioningCallback() {
+        @Override
+        public void onProvisioningFailure(int status) {
+            synchronized (mLock) {
+                mProvisioningFailureStatus = status;
+                mLock.notify();
+            }
+        }
+
+        @Override
+        public void onProvisioningStatus(int status) {
+            synchronized (mLock) {
+                mProvisioningStatus = status;
+                mLock.notify();
+            }
+        }
+
+        @Override
+        public void onProvisioningComplete() {
+            mProvisioningComplete = true;
+        }
+    };
+    private static final String TEST_SSID = "TEST SSID";
+    private static final String TEST_FRIENDLY_NAME = "Friendly Name";
+    private static final Map<String, String> TEST_FRIENDLY_NAMES =
+            new HashMap<String, String>() {
+                {
+                    put("en", TEST_FRIENDLY_NAME);
+                    put("kr", TEST_FRIENDLY_NAME + 2);
+                    put("jp", TEST_FRIENDLY_NAME + 3);
+                }
+            };
+    private static final String TEST_SERVICE_DESCRIPTION = "Dummy Service";
+    private static final Uri TEST_SERVER_URI = Uri.parse("https://test.com");
+    private static final String TEST_NAI = "test.access.com";
+    private static final List<Integer> TEST_METHOD_LIST =
+            Arrays.asList(1 /* METHOD_SOAP_XML_SPP */);
+    private final HandlerThread mHandlerThread = new HandlerThread("WifiManagerTest");
+    protected final Executor mExecutor;
+    {
+        mHandlerThread.start();
+        mExecutor = new HandlerExecutor(new Handler(mHandlerThread.getLooper()));
+    }
 
     @Override
     protected void setUp() throws Exception {
@@ -201,13 +270,20 @@
         mContext.registerReceiver(mReceiver, mIntentFilter);
         mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
         mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
+        mTetheringManager = getContext().getSystemService(TetheringManager.class);
         assertNotNull(mWifiManager);
+        assertNotNull(mTetheringManager);
 
         // turn on verbose logging for tests
         mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
                 () -> mWifiManager.isVerboseLoggingEnabled());
         ShellIdentityUtils.invokeWithShellPermissions(
                 () -> mWifiManager.setVerboseLoggingEnabled(true));
+        // Disable scan throttling for tests.
+        mWasScanThrottleEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.isScanThrottleEnabled());
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setScanThrottleEnabled(false));
 
         mWifiLock = mWifiManager.createWifiLock(TAG);
         mWifiLock.acquire();
@@ -215,7 +291,7 @@
             setWifiEnabled(true);
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
         turnScreenOnNoDelay();
-        Thread.sleep(DURATION);
+        Thread.sleep(TEST_WAIT_DURATION_MS);
         assertTrue(mWifiManager.isWifiEnabled());
         synchronized (mMySync) {
             mMySync.expectedState = STATE_NULL;
@@ -224,6 +300,10 @@
         List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions(
                 mWifiManager::getConfiguredNetworks);
         assertFalse("Need at least one saved network", savedNetworks.isEmpty());
+
+        // Get original config for restore
+        mOriginalSoftApConfig = ShellIdentityUtils.invokeWithShellPermissions(
+                mWifiManager::getSoftApConfiguration);
     }
 
     @Override
@@ -238,8 +318,13 @@
         mWifiLock.release();
         mContext.unregisterReceiver(mReceiver);
         ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setScanThrottleEnabled(mWasScanThrottleEnabled));
+        ShellIdentityUtils.invokeWithShellPermissions(
                 () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
-        Thread.sleep(DURATION);
+        // restore original softap config
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setSoftApConfiguration(mOriginalSoftApConfig));
+        Thread.sleep(TEST_WAIT_DURATION_MS);
         super.tearDown();
     }
 
@@ -357,7 +442,7 @@
                     + " empty when location is disabled!");
         }
         setWifiEnabled(false);
-        Thread.sleep(DURATION);
+        Thread.sleep(TEST_WAIT_DURATION_MS);
         startScan();
         if (mWifiManager.isScanAlwaysAvailable() && isScanCurrentlyAvailable()) {
             // Make sure at least one AP is found.
@@ -508,6 +593,140 @@
         }
     }
 
+    public class TestSoftApCallback implements WifiManager.SoftApCallback {
+        Object softApLock;
+        int currentState;
+        int currentFailureReason;
+        List<WifiClient> currentClientList;
+        SoftApInfo currentSoftApInfo;
+        SoftApCapability currentSoftApCapability;
+        MacAddress lastBlockedClientMacAddress;
+        int lastBlockedClientReason;
+        boolean onStateChangedCalled = false;
+        boolean onSoftapInfoChangedCalled = false;
+        boolean onSoftApCapabilityChangedCalled = false;
+        boolean onConnectedClientCalled = false;
+        boolean onBlockedClientConnectingCalled = false;
+
+        TestSoftApCallback(Object lock) {
+            softApLock = lock;
+        }
+
+        public boolean getOnStateChangedCalled() {
+            synchronized(softApLock) {
+                return onStateChangedCalled;
+            }
+        }
+
+        public boolean getOnSoftapInfoChangedCalled() {
+            synchronized(softApLock) {
+                return onSoftapInfoChangedCalled;
+            }
+        }
+
+        public boolean getOnSoftApCapabilityChangedCalled() {
+            synchronized(softApLock) {
+                return onSoftApCapabilityChangedCalled;
+            }
+        }
+
+        public boolean getOnConnectedClientCalled() {
+            synchronized(softApLock) {
+                return onConnectedClientCalled;
+            }
+        }
+
+        public boolean getOnBlockedClientConnectingCalled() {
+            synchronized(softApLock) {
+                return onBlockedClientConnectingCalled;
+            }
+        }
+
+        public int getCurrentState() {
+            synchronized(softApLock) {
+                return currentState;
+            }
+        }
+
+        public int getCurrentStateFailureReason() {
+            synchronized(softApLock) {
+                return currentFailureReason;
+            }
+        }
+
+        public List<WifiClient> getCurrentClientList() {
+            synchronized(softApLock) {
+                return currentClientList;
+            }
+        }
+
+        public SoftApInfo getCurrentSoftApInfo() {
+            synchronized(softApLock) {
+                return currentSoftApInfo;
+            }
+        }
+
+        public SoftApCapability getCurrentSoftApCapability() {
+            synchronized(softApLock) {
+                return currentSoftApCapability;
+            }
+        }
+
+        public MacAddress getLastBlockedClientMacAddress() {
+            synchronized(softApLock) {
+                return lastBlockedClientMacAddress;
+            }
+        }
+
+        public int getLastBlockedClientReason() {
+            synchronized(softApLock) {
+                return lastBlockedClientReason;
+            }
+        }
+
+        @Override
+        public void onStateChanged(int state, int failureReason) {
+            synchronized(softApLock) {
+                currentState = state;
+                currentFailureReason = failureReason;
+                onStateChangedCalled = true;
+            }
+        }
+
+        @Override
+        public void onConnectedClientsChanged(List<WifiClient> clients) {
+            synchronized(softApLock) {
+                currentClientList = new ArrayList<>(clients);
+                onConnectedClientCalled = true;
+            }
+        }
+
+        @Override
+        public void onInfoChanged(SoftApInfo softApInfo) {
+            synchronized(softApLock) {
+                currentSoftApInfo = softApInfo;
+                onSoftapInfoChangedCalled = true;
+            }
+        }
+
+        @Override
+        public void onCapabilityChanged(SoftApCapability softApCapability) {
+            synchronized(softApLock) {
+                currentSoftApCapability = softApCapability;
+                onSoftApCapabilityChangedCalled = true;
+            }
+        }
+
+        @Override
+        public void onBlockedClientConnecting(WifiClient client, int blockedReason) {
+            synchronized(softApLock) {
+                lastBlockedClientMacAddress = client.getMacAddress();
+                lastBlockedClientReason = blockedReason;
+                onBlockedClientConnectingCalled = true;
+            }
+        }
+    }
+
     private static class TestLocalOnlyHotspotCallback extends WifiManager.LocalOnlyHotspotCallback {
         Object hotspotLock;
         WifiManager.LocalOnlyHotspotReservation reservation = null;
@@ -558,12 +777,15 @@
             try {
                 mWifiManager.startLocalOnlyHotspot(callback, null);
                 // now wait for callback
-                mLock.wait(DURATION);
+                mLock.wait(TEST_WAIT_DURATION_MS);
             } catch (InterruptedException e) {
             }
             // check if we got the callback
             assertTrue(callback.onStartedCalled);
-            assertNotNull(callback.reservation.getSoftApConfiguration());
+
+            SoftApConfiguration softApConfig = callback.reservation.getSoftApConfiguration();
+            assertNotNull(softApConfig);
+            assertNotNull(softApConfig.toWifiConfiguration());
             if (!hasAutomotiveFeature()) {
                 assertEquals(
                         SoftApConfiguration.BAND_2GHZ,
@@ -649,7 +871,7 @@
         boolean wifiEnabled = mWifiManager.isWifiEnabled();
         // now we should fail to toggle wifi state.
         assertFalse(mWifiManager.setWifiEnabled(!wifiEnabled));
-        Thread.sleep(DURATION);
+        Thread.sleep(TEST_WAIT_DURATION_MS);
         assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
     }
 
@@ -1057,8 +1279,12 @@
         Thread.sleep(DURATION_SCREEN_TOGGLE);
     }
 
-    private void turnScreenOff() throws Exception {
+    private void turnScreenOffNoDelay() throws Exception {
         mUiDevice.executeShellCommand("input keyevent KEYCODE_SLEEP");
+    }
+
+    private void turnScreenOff() throws Exception {
+        turnScreenOffNoDelay();
         // Since the screen on/off intent is ordered, they will not be sent right now.
         Thread.sleep(DURATION_SCREEN_TOGGLE);
     }
@@ -1158,6 +1384,180 @@
                 > ENFORCED_NUM_NETWORK_SUGGESTIONS_PER_APP);
     }
 
+    private void verifyRegisterSoftApCallback(TestExecutor executor, TestSoftApCallback callback)
+            throws Exception{
+        // Register callback to get SoftApCapability
+        mWifiManager.registerSoftApCallback(executor, callback);
+        PollingCheck.check(
+                "SoftAp register failed!", 1_000,
+                () -> { executor.runAll();
+                // Verify callback is run on the supplied executor and called
+                return callback.getOnStateChangedCalled() &&
+                callback.getOnSoftapInfoChangedCalled() &&
+                callback.getOnSoftApCapabilityChangedCalled() &&
+                callback.getOnConnectedClientCalled();
+                });
+    }
+
+    private void verifySetGetSoftApConfig(SoftApConfiguration targetConfig) {
+        mWifiManager.setSoftApConfiguration(targetConfig);
+        // Bssid set dodesn't support for tethered hotspot
+        SoftApConfiguration currentConfig = mWifiManager.getSoftApConfiguration();
+        assertNull(currentConfig.getBssid());
+        compareSoftApConfiguration(targetConfig, currentConfig);
+    }
+
+    private void compareSoftApConfiguration(SoftApConfiguration currentConfig,
+        SoftApConfiguration testSoftApConfig) {
+        assertEquals(currentConfig.getSsid(), testSoftApConfig.getSsid());
+        assertEquals(currentConfig.getSecurityType(), testSoftApConfig.getSecurityType());
+        assertEquals(currentConfig.getPassphrase(), testSoftApConfig.getPassphrase());
+        assertEquals(currentConfig.isHiddenSsid(), testSoftApConfig.isHiddenSsid());
+        assertEquals(currentConfig.getBand(), testSoftApConfig.getBand());
+        assertEquals(currentConfig.getChannel(), testSoftApConfig.getChannel());
+        assertEquals(currentConfig.getMaxNumberOfClients(),
+                testSoftApConfig.getMaxNumberOfClients());
+        assertEquals(currentConfig.isAutoShutdownEnabled(),
+                testSoftApConfig.isAutoShutdownEnabled());
+        assertEquals(currentConfig.getShutdownTimeoutMillis(),
+                testSoftApConfig.getShutdownTimeoutMillis());
+        assertEquals(currentConfig.isClientControlByUserEnabled(),
+                testSoftApConfig.isClientControlByUserEnabled());
+        assertEquals(currentConfig.getAllowedClientList(),
+                testSoftApConfig.getAllowedClientList());
+        assertEquals(currentConfig.getBlockedClientList(),
+                testSoftApConfig.getBlockedClientList());
+    }
+
+    private void turnOffWifiAndTetheredHotspotIfEnabled() throws Exception {
+        if (mWifiManager.isWifiEnabled()) {
+            Log.d(TAG, "Turn off WiFi");
+            mWifiManager.setWifiEnabled(false);
+            PollingCheck.check(
+                "Wifi turn off failed!", 2_000,
+                () -> mWifiManager.isWifiEnabled() == false);
+        }
+        if (mWifiManager.isWifiApEnabled()) {
+            mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
+            Log.d(TAG, "Turn off tethered Hotspot");
+            PollingCheck.check(
+                "SoftAp turn off failed!", 2_000,
+                () -> mWifiManager.isWifiApEnabled() == false);
+            mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
+        }
+    }
+
+    /**
+     * Verify that the configuration from getSoftApConfiguration is same as the configuration which
+     * set by setSoftApConfiguration. And depends softap capability callback to test different
+     * configuration.
+     * @throws Exception
+     */
+    public void testSetGetSoftApConfigurationAndSoftApCapabilityCallback() throws Exception {
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        TestExecutor executor = new TestExecutor();
+        TestSoftApCallback callback = new TestSoftApCallback(mLock);
+        try {
+            uiAutomation.adoptShellPermissionIdentity();
+            turnOffWifiAndTetheredHotspotIfEnabled();
+            verifyRegisterSoftApCallback(executor, callback);
+
+            SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder()
+                    .setSsid(TEST_SSID_UNQUOTED)
+                    .setBssid(TEST_MAC)
+                    .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
+                    .setAutoShutdownEnabled(true)
+                    .setShutdownTimeoutMillis(100000)
+                    .setBand(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ)
+                    .setHiddenSsid(false);
+
+            // Test SoftApConfiguration set and get
+            verifySetGetSoftApConfig(softApConfigBuilder.build());
+
+            // Test CLIENT_FORCE_DISCONNECT supported config.
+            if (callback.getCurrentSoftApCapability()
+                    .areFeaturesSupported(
+                    SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) {
+                softApConfigBuilder.setMaxNumberOfClients(10);
+                softApConfigBuilder.setClientControlByUserEnabled(true);
+                softApConfigBuilder.setBlockedClientList(new ArrayList<>());
+                softApConfigBuilder.setAllowedClientList(new ArrayList<>());
+                verifySetGetSoftApConfig(softApConfigBuilder.build());
+            }
+
+            // Test SAE config
+            if (callback.getCurrentSoftApCapability()
+                    .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE)) {
+                softApConfigBuilder
+                        .setPassphrase(TEST_PASSPHRASE,
+                          SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION);
+                verifySetGetSoftApConfig(softApConfigBuilder.build());
+                softApConfigBuilder
+                        .setPassphrase(TEST_PASSPHRASE,
+                        SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+                verifySetGetSoftApConfig(softApConfigBuilder.build());
+            }
+        } finally {
+            mWifiManager.unregisterSoftApCallback(callback);
+            uiAutomation.dropShellPermissionIdentity();
+        }
+    }
+
+    /**
+     * Verify that startTetheredHotspot with specific channel config.
+     * @throws Exception
+     */
+    public void testStartTetheredHotspotWithChannelConfigAndSoftApStateAndInfoCallback()
+            throws Exception {
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        TestExecutor executor = new TestExecutor();
+        TestSoftApCallback callback = new TestSoftApCallback(mLock);
+        try {
+            uiAutomation.adoptShellPermissionIdentity();
+            turnOffWifiAndTetheredHotspotIfEnabled();
+            verifyRegisterSoftApCallback(executor, callback);
+
+            SoftApConfiguration testSoftApConfig = new SoftApConfiguration.Builder()
+                    .setSsid(TEST_SSID_UNQUOTED)
+                    .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
+                    .setChannel(11, SoftApConfiguration.BAND_2GHZ) // Channel 11 = Freq 2462
+                    .build();
+
+            mWifiManager.setSoftApConfiguration(testSoftApConfig);
+
+            // start tethering which used to verify startTetheredHotspot
+            mTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI, executor,
+                new TetheringManager.StartTetheringCallback() {
+                    @Override
+                    public void onTetheringFailed(final int result) {
+                    }
+                });
+
+            // Verify state and info callback value as expected
+            PollingCheck.check(
+                    "SoftAp channel and state mismatch!!!", 5_000,
+                    () -> { executor.runAll();
+                    return WifiManager.WIFI_AP_STATE_ENABLED == callback.getCurrentState() &&
+                    2462 == callback.getCurrentSoftApInfo().getFrequency();
+                    });
+
+            // stop tethering which used to verify stopSoftAp
+            mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
+
+            // Verify clean up
+            PollingCheck.check(
+                    "Stop Softap failed", 2_000,
+                    () -> { executor.runAll();
+                    return WifiManager.WIFI_AP_STATE_DISABLED == callback.getCurrentState() &&
+                    0 == callback.getCurrentSoftApInfo().getBandwidth() &&
+                    0 == callback.getCurrentSoftApInfo().getFrequency();
+                    });
+        } finally {
+            mWifiManager.unregisterSoftApCallback(callback);
+            uiAutomation.dropShellPermissionIdentity();
+        }
+    }
+
     private static class TestActionListener implements WifiManager.ActionListener {
         private final Object mLock;
         public boolean onSuccessCalled = false;
@@ -1220,7 +1620,7 @@
                         mWifiManager.connect(savedNetworks.get(0), actionListener);
                     }
                     // now wait for callback
-                    mLock.wait(DURATION);
+                    mLock.wait(TEST_WAIT_DURATION_MS);
                 } catch (InterruptedException e) {
                 }
             }
@@ -1299,7 +1699,7 @@
                                 .build(),
                         networkCallbackListener);
                 // now wait for callback
-                mLock.wait(DURATION);
+                mLock.wait(TEST_WAIT_DURATION_MS);
             } catch (InterruptedException e) {
             }
         }
@@ -1347,7 +1747,7 @@
                     modSavedNetwork.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED;
                     mWifiManager.save(modSavedNetwork, actionListener);
                     // now wait for callback
-                    mLock.wait(DURATION);
+                    mLock.wait(TEST_WAIT_DURATION_MS);
                 } catch (InterruptedException e) {
                 }
             }
@@ -1395,7 +1795,7 @@
                 try {
                     mWifiManager.forget(newNetworkId, actionListener);
                     // now wait for callback
-                    mLock.wait(DURATION);
+                    mLock.wait(TEST_WAIT_DURATION_MS);
                 } catch (InterruptedException e) {
                 }
             }
@@ -1472,13 +1872,107 @@
         mWifiManager.isPreferredNetworkOffloadSupported();
     }
 
+    /** Test that PNO scans reconnects us when the device is disconnected and the screen is off. */
+    public void testPnoScan() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        if (!mWifiManager.isPreferredNetworkOffloadSupported()) {
+            // skip the test if PNO scanning is not supported
+            return;
+        }
+
+        // make sure we're connected
+        waitForConnection();
+
+        WifiInfo currentNetwork = ShellIdentityUtils.invokeWithShellPermissions(
+                mWifiManager::getConnectionInfo);
+
+        // disable all networks that aren't already disabled
+        List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions(
+                mWifiManager::getConfiguredNetworks);
+        Set<Integer> disabledNetworkIds = new HashSet<>();
+        for (WifiConfiguration config : savedNetworks) {
+            if (config.getNetworkSelectionStatus().getNetworkSelectionDisableReason()
+                    == WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE) {
+                ShellIdentityUtils.invokeWithShellPermissions(
+                        () -> mWifiManager.disableNetwork(config.networkId));
+                disabledNetworkIds.add(config.networkId);
+            }
+        }
+
+        try {
+            // wait for disconnection from current network
+            waitForDisconnection();
+
+            // turn screen off
+            turnScreenOffNoDelay();
+
+            // re-enable the current network - this will trigger PNO
+            ShellIdentityUtils.invokeWithShellPermissions(
+                    () -> mWifiManager.enableNetwork(currentNetwork.getNetworkId(), false));
+            disabledNetworkIds.remove(currentNetwork.getNetworkId());
+
+            // PNO should reconnect us back to the network we disconnected from
+            waitForConnection();
+        } finally {
+            // re-enable disabled networks
+            for (int disabledNetworkId : disabledNetworkIds) {
+                ShellIdentityUtils.invokeWithShellPermissions(
+                        () -> mWifiManager.enableNetwork(disabledNetworkId, false));
+            }
+        }
+    }
+
+    /**
+     * Tests {@link WifiManager#isTdlsSupported()} does not crash.
+     */
+    public void testIsTdlsSupported() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        mWifiManager.isTdlsSupported();
+    }
+
+    /**
+     * Tests {@link WifiManager#isStaApConcurrencySupported().
+     */
+    public void testIsStaApConcurrencySupported() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        // check that softap mode is supported by the device
+        if (!mWifiManager.isPortableHotspotSupported()) {
+            return;
+        }
+        assertTrue(mWifiManager.isWifiEnabled());
+
+        boolean isStaApConcurrencySupported = mWifiManager.isStaApConcurrencySupported();
+        // start local only hotspot.
+        TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+        if (isStaApConcurrencySupported) {
+            assertTrue(mWifiManager.isWifiEnabled());
+        } else {
+            // no concurrency, wifi should be disabled.
+            assertFalse(mWifiManager.isWifiEnabled());
+        }
+        stopLocalOnlyHotspot(callback, true);
+
+        assertTrue(mWifiManager.isWifiEnabled());
+    }
+
     private static class TestTrafficStateCallback implements WifiManager.TrafficStateCallback {
         private final Object mLock;
+        private final int mWaitForState;
         public boolean onStateChangedCalled = false;
         public int state = -1;
 
-        TestTrafficStateCallback(Object lock) {
+        TestTrafficStateCallback(Object lock, int waitForState) {
             mLock = lock;
+            mWaitForState = waitForState;
         }
 
         @Override
@@ -1486,7 +1980,9 @@
             synchronized (mLock) {
                 onStateChangedCalled = true;
                 this.state = state;
-                mLock.notify();
+                if (mWaitForState == state) { // only notify if we got the expected state.
+                    mLock.notify();
+                }
             }
         }
     }
@@ -1520,7 +2016,8 @@
             // skip the test if WiFi is not supported
             return;
         }
-        TestTrafficStateCallback trafficStateCallback = new TestTrafficStateCallback(mLock);
+        TestTrafficStateCallback trafficStateCallback =
+                new TestTrafficStateCallback(mLock, DATA_ACTIVITY_INOUT);
         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
         try {
             uiAutomation.adoptShellPermissionIdentity();
@@ -1537,7 +2034,7 @@
                     // Send some traffic to trigger the traffic state change callbacks.
                     sendTraffic();
                     // now wait for callback
-                    mLock.wait(DURATION);
+                    mLock.wait(TEST_WAIT_DURATION_MS);
                 } catch (InterruptedException e) {
                 }
             }
@@ -1677,7 +2174,7 @@
             uiAutomation.adoptShellPermissionIdentity();
             // These below API's only work with privileged permissions (obtained via shell identity
             // for test)
-            savedNetworks = mWifiManager.getConfiguredNetworks();
+            savedNetworks = mWifiManager.getPrivilegedConfiguredNetworks();
 
             mWifiManager.factoryReset();
             // Ensure all the saved networks are removed.
@@ -1686,7 +2183,9 @@
             // Restore the original saved networks.
             if (savedNetworks != null) {
                 for (WifiConfiguration network : savedNetworks) {
-                    mWifiManager.save(network, null);
+                    network.networkId = WifiConfiguration.INVALID_NETWORK_ID;
+                    int networkId = mWifiManager.addNetwork(network);
+                    mWifiManager.enableNetwork(networkId, false);
                 }
             }
             uiAutomation.dropShellPermissionIdentity();
@@ -1760,7 +2259,7 @@
                                 .build(),
                         networkCallbackListener);
                 // now wait for callback
-                mLock.wait(DURATION);
+                mLock.wait(TEST_WAIT_DURATION_MS);
             } catch (InterruptedException e) {
             }
         }
@@ -1940,4 +2439,88 @@
             assertTrue(is11axSupportedEnabled);
         }
     }
+
+    private static PasspointConfiguration createPasspointConfiguration() {
+        PasspointConfiguration config = new PasspointConfiguration();
+        HomeSp homeSp = new HomeSp();
+        homeSp.setFqdn("test.com");
+        homeSp.setFriendlyName("friendly name");
+        homeSp.setRoamingConsortiumOis(new long[]{0x55, 0x66});
+        config.setHomeSp(homeSp);
+        Credential.SimCredential simCred = new Credential.SimCredential();
+        simCred.setImsi("123456*");
+        simCred.setEapType(23 /* EAP_AKA */);
+        Credential cred = new Credential();
+        cred.setRealm("realm");
+        cred.setSimCredential(simCred);
+        config.setCredential(cred);
+
+        return config;
+    }
+
+    /**
+     * Tests {@link WifiManager#addOrUpdatePasspointConfiguration(PasspointConfiguration)}
+     * adds a Passpoint configuration correctly by getting it once it is added, and comparing it
+     * to the local copy of the configuration.
+     */
+    public void testAddOrUpdatePasspointConfiguration() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+
+        // Create and install a Passpoint configuration
+        PasspointConfiguration passpointConfiguration = createPasspointConfiguration();
+        mWifiManager.addOrUpdatePasspointConfiguration(passpointConfiguration);
+
+        // Compare configurations
+        List<PasspointConfiguration> configurations = mWifiManager.getPasspointConfigurations();
+        assertNotNull(configurations);
+        assertEquals(passpointConfiguration, configurations.get(0));
+
+        // Clean up
+        mWifiManager.removePasspointConfiguration(passpointConfiguration.getHomeSp().getFqdn());
+    }
+
+    /**
+     * Tests that
+     * {@link WifiManager#startSubscriptionProvisioning(OsuProvider, Executor, ProvisioningCallback)}
+     * starts a subscription provisioning, and confirm a status callback invoked once.
+     */
+    public void testStartSubscriptionProvisioning() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+
+        // Using Java reflection to construct an OsuProvider instance because its constructor is
+        // hidden and not available to apps.
+        Class<?> osuProviderClass = Class.forName("android.net.wifi.hotspot2.OsuProvider");
+        Constructor<?> osuProviderClassConstructor = osuProviderClass.getConstructor(String.class,
+                Map.class, String.class, Uri.class, String.class, List.class);
+
+        OsuProvider osuProvider = (OsuProvider) osuProviderClassConstructor.newInstance(TEST_SSID,
+                TEST_FRIENDLY_NAMES, TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI,
+                TEST_METHOD_LIST);
+
+        UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        try {
+            uiAutomation.adoptShellPermissionIdentity();
+            synchronized (mLock) {
+                // Start a subscription provisioning for a non-existent Passpoint R2 AP
+                mWifiManager.startSubscriptionProvisioning(osuProvider, mExecutor,
+                        mProvisioningCallback);
+                mLock.wait(TEST_WAIT_DURATION_MS);
+            }
+        } finally {
+            uiAutomation.dropShellPermissionIdentity();
+        }
+
+        // Expect only a single callback event, connecting. Since AP doesn't exist, it ends here
+        assertEquals(ProvisioningCallback.OSU_STATUS_AP_CONNECTING, mProvisioningStatus);
+        // No failure callbacks expected
+        assertEquals(0, mProvisioningFailureStatus);
+        // No completion callback expected
+        assertFalse(mProvisioningComplete);
+    }
 }
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiMigrationTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiMigrationTest.java
index 6e19a21..c74c177 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiMigrationTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiMigrationTest.java
@@ -16,16 +16,12 @@
 
 package android.net.wifi.cts;
 
-import static org.junit.Assert.assertNotNull;
-
-import android.net.wifi.SoftApConfiguration;
-import android.net.wifi.WifiConfiguration;
+import android.app.ActivityManager;
 import android.net.wifi.WifiMigration;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.test.AndroidTestCase;
 
-import java.util.Arrays;
-import java.util.List;
-
 public class WifiMigrationTest extends AndroidTestCase {
     private static final String TEST_SSID_UNQUOTED = "testSsid1";
 
@@ -49,42 +45,7 @@
     }
 
     /**
-     * Tests {@link android.net.wifi.WifiMigration.ConfigStoreMigrationData} class.
-     */
-    public void testWifiMigrationConfigStoreDataBuilder() throws Exception {
-        if (!WifiFeature.isWifiSupported(getContext())) {
-            // skip the test if WiFi is not supported
-            return;
-        }
-        WifiConfiguration savedNetwork1 = new WifiConfiguration();
-        savedNetwork1.SSID = "\"test1\"";
-        WifiConfiguration savedNetwork2 = new WifiConfiguration();
-        savedNetwork1.SSID = "\"test2\"";
-        List<WifiConfiguration> savedNetworks = Arrays.asList(savedNetwork1, savedNetwork2);
-
-        SoftApConfiguration softApConfiguration = new SoftApConfiguration.Builder()
-                .setSsid("\"test3\"")
-                .build();
-
-        WifiMigration.ConfigStoreMigrationData migrationData =
-                new WifiMigration.ConfigStoreMigrationData.Builder()
-                        .setUserSavedNetworkConfigurations(savedNetworks)
-                        .setUserSoftApConfiguration(softApConfiguration)
-                        .build();
-
-        assertNotNull(migrationData);
-        assertEquals(savedNetworks.size(),
-                migrationData.getUserSavedNetworkConfigurations().size());
-        assertEquals(savedNetwork1.SSID,
-                migrationData.getUserSavedNetworkConfigurations().get(0).SSID);
-        assertEquals(savedNetwork2.SSID,
-                migrationData.getUserSavedNetworkConfigurations().get(1).SSID);
-        assertEquals(softApConfiguration.getSsid(),
-                migrationData.getUserSoftApConfiguration().getSsid());
-    }
-
-    /**
-     * Tests {@link android.net.wifi.WifiMigration.ConfigStoreMigrationData} class.
+     * Tests {@link android.net.wifi.WifiMigration.SettingsMigrationData.Builder} class.
      */
     public void testWifiMigrationSettingsDataBuilder() throws Exception {
         if (!WifiFeature.isWifiSupported(getContext())) {
@@ -111,4 +72,67 @@
         assertTrue(migrationData.isVerboseLoggingEnabled());
         assertEquals(TEST_SSID_UNQUOTED, migrationData.getP2pDeviceName());
     }
+
+    /**
+     * Tests {@link android.net.wifi.WifiMigration.SettingsMigrationData} class.
+     */
+    public void testWifiMigrationSettings() throws Exception {
+        try {
+            WifiMigration.loadFromSettings(getContext());
+        } catch (Exception ignore) {
+        }
+    }
+
+    /**
+     * Tests {@link WifiMigration#convertAndRetrieveSharedConfigStoreFile(int)},
+     * {@link WifiMigration#convertAndRetrieveUserConfigStoreFile(int, UserHandle)},
+     * {@link WifiMigration#removeSharedConfigStoreFile(int)} and
+     * {@link WifiMigration#removeUserConfigStoreFile(int, UserHandle)}.
+     */
+    public void testWifiMigrationConfigStore() throws Exception {
+        try {
+            WifiMigration.convertAndRetrieveSharedConfigStoreFile(
+                    WifiMigration.STORE_FILE_SHARED_GENERAL);
+        } catch (Exception ignore) {
+        }
+        try {
+            WifiMigration.convertAndRetrieveSharedConfigStoreFile(
+                    WifiMigration.STORE_FILE_SHARED_SOFTAP);
+        } catch (Exception ignore) {
+        }
+        try {
+            WifiMigration.convertAndRetrieveUserConfigStoreFile(
+                    WifiMigration.STORE_FILE_USER_GENERAL,
+                    UserHandle.of(ActivityManager.getCurrentUser()));
+        } catch (Exception ignore) {
+        }
+        try {
+            WifiMigration.convertAndRetrieveUserConfigStoreFile(
+                    WifiMigration.STORE_FILE_USER_NETWORK_SUGGESTIONS,
+                    UserHandle.of(ActivityManager.getCurrentUser()));
+        } catch (Exception ignore) {
+        }
+        try {
+            WifiMigration.removeSharedConfigStoreFile(
+                    WifiMigration.STORE_FILE_SHARED_GENERAL);
+        } catch (Exception ignore) {
+        }
+        try {
+            WifiMigration.removeSharedConfigStoreFile(
+                    WifiMigration.STORE_FILE_SHARED_SOFTAP);
+        } catch (Exception ignore) {
+        }
+        try {
+            WifiMigration.removeUserConfigStoreFile(
+                    WifiMigration.STORE_FILE_USER_GENERAL,
+                    UserHandle.of(ActivityManager.getCurrentUser()));
+        } catch (Exception ignore) {
+        }
+        try {
+            WifiMigration.removeUserConfigStoreFile(
+                    WifiMigration.STORE_FILE_USER_NETWORK_SUGGESTIONS,
+                    UserHandle.of(ActivityManager.getCurrentUser()));
+        } catch (Exception ignore) {
+        }
+    }
 }
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
index 96cf45f..83018fa 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
@@ -31,6 +31,7 @@
 import android.net.NetworkRequest;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
@@ -70,6 +71,7 @@
     private final Object mUiLock = new Object();
     private WifiConfiguration mTestNetwork;
     private boolean mWasVerboseLoggingEnabled;
+    private boolean mWasScanThrottleEnabled;
 
     private static final int DURATION = 10_000;
     private static final int DURATION_UI_INTERACTION = 15_000;
@@ -92,6 +94,11 @@
                 () -> mWifiManager.isVerboseLoggingEnabled());
         ShellIdentityUtils.invokeWithShellPermissions(
                 () -> mWifiManager.setVerboseLoggingEnabled(true));
+        // Disable scan throttling for tests.
+        mWasScanThrottleEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.isScanThrottleEnabled());
+        ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setScanThrottleEnabled(false));
 
         if (!mWifiManager.isWifiEnabled()) setWifiEnabled(true);
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
@@ -126,6 +133,8 @@
         ShellIdentityUtils.invokeWithShellPermissions(
                 () -> mWifiManager.enableNetwork(mTestNetwork.networkId, false));
         ShellIdentityUtils.invokeWithShellPermissions(
+                () -> mWifiManager.setScanThrottleEnabled(mWasScanThrottleEnabled));
+        ShellIdentityUtils.invokeWithShellPermissions(
                 () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
         super.tearDown();
     }
@@ -506,4 +515,44 @@
                 .build();
         testUserRejectionWithSpecifier(specifier);
     }
+
+    /**
+     * Tests the builder for WPA2 enterprise networks.
+     * Note: Can't do end to end tests for such networks in CTS environment.
+     */
+    public void testBuilderForWpa2Enterprise() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        WifiNetworkSpecifier specifier1 = new WifiNetworkSpecifier.Builder()
+                .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+                .setWpa2EnterpriseConfig(new WifiEnterpriseConfig())
+                .build();
+        WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier.Builder()
+                .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+                .setWpa2EnterpriseConfig(new WifiEnterpriseConfig())
+                .build();
+        assertThat(specifier1.satisfiedBy(specifier2)).isTrue();
+    }
+
+    /**
+     * Tests the builder for WPA3 enterprise networks.
+     * Note: Can't do end to end tests for such networks in CTS environment.
+     */
+    public void testBuilderForWpa3Enterprise() {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        WifiNetworkSpecifier specifier1 = new WifiNetworkSpecifier.Builder()
+                .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+                .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+                .build();
+        WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier.Builder()
+                .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+                .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+                .build();
+        assertThat(specifier1.satisfiedBy(specifier2)).isTrue();
+    }
 }
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
index 994b6c9..e73abb8 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
@@ -17,6 +17,7 @@
 package android.net.wifi.cts;
 
 import static android.net.wifi.WifiEnterpriseConfig.Eap.AKA;
+import static android.net.wifi.WifiEnterpriseConfig.Eap.WAPI_CERT;
 
 import android.net.MacAddress;
 import android.net.wifi.WifiEnterpriseConfig;
@@ -199,6 +200,28 @@
     }
 
     /**
+     * Tests {@link android.net.wifi.WifiNetworkSuggestion.Builder} class.
+     */
+    public void testBuilderWithWapiEnterprise() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        enterpriseConfig.setEapMethod(WAPI_CERT);
+        WifiNetworkSuggestion suggestion =
+                createBuilderWithCommonParams()
+                        .setWapiEnterpriseConfig(enterpriseConfig)
+                        .build();
+        validateCommonParams(suggestion);
+        assertNull(suggestion.getPassphrase());
+        assertNotNull(suggestion.getEnterpriseConfig());
+        assertEquals(enterpriseConfig.getEapMethod(),
+                suggestion.getEnterpriseConfig().getEapMethod());
+        assertNull(suggestion.getPasspointConfig());
+    }
+
+    /**
      * Helper function for creating a {@link PasspointConfiguration} for testing.
      *
      * @return {@link PasspointConfiguration}
diff --git a/tests/cts/net/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java b/tests/cts/net/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java
new file mode 100644
index 0000000..d8f5e57
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.DeviceWiphyCapabilities;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** CTS tests for {@link DeviceWiphyCapabilities}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DeviceWiphyCapabilitiesTest {
+
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        // skip tests if Wifi is not supported
+        assumeTrue(WifiFeature.isWifiSupported(context));
+    }
+
+    /**
+     *  Test that a {@link DeviceWiphyCapabilities} object can be serialized and deserialized,
+     *  while keeping its values unchanged.
+     */
+    @Test
+    public void canSerializeAndDeserialize() {
+        DeviceWiphyCapabilities capa = new DeviceWiphyCapabilities();
+
+        capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, true);
+        capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, true);
+        capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, false);
+
+        Parcel parcel = Parcel.obtain();
+        capa.writeToParcel(parcel, 0);
+        // Rewind the pointer to the head of the parcel.
+        parcel.setDataPosition(0);
+        DeviceWiphyCapabilities capaDeserialized =
+                DeviceWiphyCapabilities.CREATOR.createFromParcel(parcel);
+
+        assertThat(capaDeserialized.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N)).isTrue();
+        assertThat(capaDeserialized.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC))
+                .isTrue();
+        assertThat(capaDeserialized.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX))
+                .isFalse();
+        assertThat(capaDeserialized).isEqualTo(capa);
+        assertThat(capaDeserialized.hashCode()).isEqualTo(capa.hashCode());
+    }
+
+    /** Test mapping wifi standard support into channel width support */
+    @Test
+    public void testMappingWifiStandardIntoChannelWidthSupport() {
+        DeviceWiphyCapabilities capa = new DeviceWiphyCapabilities();
+
+        capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, false);
+        capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, false);
+        capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, false);
+        assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_20MHZ)).isTrue();
+        assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)).isFalse();
+        assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)).isFalse();
+
+        capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, true);
+        assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_20MHZ)).isTrue();
+        assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)).isTrue();
+        assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)).isFalse();
+
+        capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, true);
+        assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_20MHZ)).isTrue();
+        assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)).isTrue();
+        assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)).isTrue();
+    }
+}
diff --git a/tests/cts/net/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java b/tests/cts/net/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java
new file mode 100644
index 0000000..3149b54
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.MacAddress;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.NativeWifiClient;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** CTS tests for {@link NativeWifiClient}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NativeWifiClientTest {
+
+    private static final byte[] TEST_MAC = { 1, 2, 3, 4, 5, 6 };
+
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        // skip tests if Wifi is not supported
+        assumeTrue(WifiFeature.isWifiSupported(context));
+    }
+
+    @Test
+    public void testGetters() {
+        NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(TEST_MAC));
+
+        assertThat(client.getMacAddress().toByteArray()).isEqualTo(TEST_MAC);
+    }
+
+    @Test
+    public void canSerializeAndDeserialize() {
+        NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(TEST_MAC));
+
+        Parcel parcel = Parcel.obtain();
+        client.writeToParcel(parcel, 0);
+        // Rewind the pointer to the head of the parcel.
+        parcel.setDataPosition(0);
+        NativeWifiClient clientDeserialized = NativeWifiClient.CREATOR.createFromParcel(parcel);
+
+        assertThat(clientDeserialized.getMacAddress().toByteArray()).isEqualTo(TEST_MAC);
+        assertThat(clientDeserialized).isEqualTo(client);
+        assertThat(clientDeserialized.hashCode()).isEqualTo(client.hashCode());
+    }
+
+    @Test
+    public void testEquals() {
+        NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(TEST_MAC));
+        NativeWifiClient client2 =
+                new NativeWifiClient(MacAddress.fromBytes(new byte[] { 7, 8, 9, 10, 11, 12 }));
+
+        assertThat(client2).isNotEqualTo(client);
+    }
+}
diff --git a/tests/cts/net/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java b/tests/cts/net/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java
new file mode 100644
index 0000000..f3a8f05
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.PnoNetwork;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** CTS tests for {@link PnoNetwork}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PnoNetworkTest {
+
+    private static final byte[] TEST_SSID = { 's', 's', 'i', 'd' };
+    private static final int[] TEST_FREQUENCIES = { 2412, 2417, 5035 };
+
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        // skip tests if Wifi is not supported
+        assumeTrue(WifiFeature.isWifiSupported(context));
+    }
+
+    @Test
+    public void testGetters() {
+        PnoNetwork network = new PnoNetwork();
+        network.setSsid(TEST_SSID);
+        network.setFrequenciesMhz(TEST_FREQUENCIES);
+        network.setHidden(true);
+
+        assertThat(network.getSsid()).isEqualTo(TEST_SSID);
+        assertThat(network.getFrequenciesMhz()).isEqualTo(TEST_FREQUENCIES);
+        assertThat(network.isHidden()).isTrue();
+    }
+
+    @Test
+    public void canSerializeAndDeserialize() {
+        PnoNetwork network = new PnoNetwork();
+        network.setSsid(TEST_SSID);
+        network.setFrequenciesMhz(TEST_FREQUENCIES);
+        network.setHidden(true);
+
+        Parcel parcel = Parcel.obtain();
+        network.writeToParcel(parcel, 0);
+        // Rewind the pointer to the head of the parcel.
+        parcel.setDataPosition(0);
+        PnoNetwork networkDeserialized = PnoNetwork.CREATOR.createFromParcel(parcel);
+
+        assertThat(networkDeserialized.getSsid()).isEqualTo(TEST_SSID);
+        assertThat(networkDeserialized.getFrequenciesMhz()).isEqualTo(TEST_FREQUENCIES);
+        assertThat(networkDeserialized.isHidden()).isTrue();
+        assertThat(networkDeserialized).isEqualTo(network);
+        assertThat(networkDeserialized.hashCode()).isEqualTo(network.hashCode());
+    }
+
+    @Test
+    public void testEquals() {
+        PnoNetwork network = new PnoNetwork();
+        network.setSsid(TEST_SSID);
+        network.setFrequenciesMhz(TEST_FREQUENCIES);
+        network.setHidden(true);
+
+        PnoNetwork network2 = new PnoNetwork();
+        network.setSsid(new byte[] { 'a', 's', 'd', 'f'});
+        network.setFrequenciesMhz(new int[] { 1, 2, 3 });
+        network.setHidden(false);
+
+        assertThat(network2).isNotEqualTo(network);
+    }
+}
diff --git a/tests/cts/net/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java b/tests/cts/net/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java
new file mode 100644
index 0000000..59f5d99
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.PnoNetwork;
+import android.net.wifi.nl80211.PnoSettings;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+/** CTS tests for {@link PnoSettings}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PnoSettingsTest {
+
+    private static List<PnoNetwork> createTestNetworks() {
+        PnoNetwork network1 = new PnoNetwork();
+        network1.setSsid(new byte[] { 's', 's', 'i', 'd' });
+        network1.setFrequenciesMhz(new int[] { 2412, 2417, 5035 });
+        network1.setHidden(true);
+
+        PnoNetwork network2 = new PnoNetwork();
+        network2.setSsid(new byte[] { 'a', 's', 'd', 'f' });
+        network2.setFrequenciesMhz(new int[] { 2422, 2427, 5040 });
+        network2.setHidden(false);
+
+        return Arrays.asList(network1, network2);
+    }
+
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        // skip tests if Wifi is not supported
+        assumeTrue(WifiFeature.isWifiSupported(context));
+    }
+
+    @Test
+    public void testGetters() {
+        PnoSettings settings = new PnoSettings();
+        settings.setIntervalMillis(1000);
+        settings.setMin2gRssiDbm(-70);
+        settings.setMin5gRssiDbm(-60);
+        settings.setMin6gRssiDbm(-50);
+        settings.setPnoNetworks(createTestNetworks());
+
+        assertThat(settings.getIntervalMillis()).isEqualTo(1000);
+        assertThat(settings.getMin2gRssiDbm()).isEqualTo(-70);
+        assertThat(settings.getMin5gRssiDbm()).isEqualTo(-60);
+        assertThat(settings.getMin6gRssiDbm()).isEqualTo(-50);
+        assertThat(settings.getPnoNetworks()).isEqualTo(createTestNetworks());
+    }
+
+    @Test
+    public void canSerializeAndDeserialize() {
+        PnoSettings settings = new PnoSettings();
+        settings.setIntervalMillis(1000);
+        settings.setMin2gRssiDbm(-70);
+        settings.setMin5gRssiDbm(-60);
+        settings.setMin6gRssiDbm(-50);
+        settings.setPnoNetworks(createTestNetworks());
+
+        Parcel parcel = Parcel.obtain();
+        settings.writeToParcel(parcel, 0);
+        // Rewind the pointer to the head of the parcel.
+        parcel.setDataPosition(0);
+        PnoSettings settingsDeserialized = PnoSettings.CREATOR.createFromParcel(parcel);
+
+        assertThat(settingsDeserialized.getIntervalMillis()).isEqualTo(1000);
+        assertThat(settingsDeserialized.getMin2gRssiDbm()).isEqualTo(-70);
+        assertThat(settingsDeserialized.getMin5gRssiDbm()).isEqualTo(-60);
+        assertThat(settingsDeserialized.getMin6gRssiDbm()).isEqualTo(-50);
+        assertThat(settingsDeserialized.getPnoNetworks()).isEqualTo(createTestNetworks());
+        assertThat(settingsDeserialized).isEqualTo(settings);
+        assertThat(settingsDeserialized.hashCode()).isEqualTo(settings.hashCode());
+    }
+
+    @Test
+    public void testEquals() {
+        PnoSettings settings = new PnoSettings();
+        settings.setIntervalMillis(1000);
+        settings.setMin2gRssiDbm(-70);
+        settings.setMin5gRssiDbm(-60);
+        settings.setMin6gRssiDbm(-50);
+        settings.setPnoNetworks(createTestNetworks());
+
+        PnoSettings settings2 = new PnoSettings();
+        settings.setIntervalMillis(2000);
+        settings.setMin2gRssiDbm(-70);
+        settings.setMin5gRssiDbm(-60);
+        settings.setMin6gRssiDbm(-50);
+        settings.setPnoNetworks(createTestNetworks());
+
+        assertThat(settings2).isNotEqualTo(settings);
+    }
+}
diff --git a/tests/cts/net/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java b/tests/cts/net/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java
new file mode 100644
index 0000000..0a76bdb
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.RadioChainInfo;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** CTS tests for {@link RadioChainInfo}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RadioChainInfoTest {
+
+    private static final int TEST_CHAIN_ID = 1;
+    private static final int TEST_CHAIN_ID2 = 2;
+    private static final int TEST_LEVEL_DBM = -50;
+    private static final int TEST_LEVEL_DBM2 = -80;
+
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        // skip tests if Wifi is not supported
+        assumeTrue(WifiFeature.isWifiSupported(context));
+    }
+
+    @Test
+    public void testGetters() {
+        RadioChainInfo info = new RadioChainInfo(TEST_CHAIN_ID, TEST_LEVEL_DBM);
+        assertThat(info.getChainId()).isEqualTo(TEST_CHAIN_ID);
+        assertThat(info.getLevelDbm()).isEqualTo(TEST_LEVEL_DBM);
+    }
+
+    @Test
+    public void canSerializeAndDeserialize() {
+        RadioChainInfo info = new RadioChainInfo(TEST_CHAIN_ID, TEST_LEVEL_DBM);
+
+        Parcel parcel = Parcel.obtain();
+        info.writeToParcel(parcel, 0);
+        // Rewind the pointer to the head of the parcel.
+        parcel.setDataPosition(0);
+        RadioChainInfo infoDeserialized = RadioChainInfo.CREATOR.createFromParcel(parcel);
+
+        assertThat(infoDeserialized.getChainId()).isEqualTo(TEST_CHAIN_ID);
+        assertThat(infoDeserialized.getLevelDbm()).isEqualTo(TEST_LEVEL_DBM);
+        assertThat(infoDeserialized).isEqualTo(info);
+        assertThat(infoDeserialized.hashCode()).isEqualTo(info.hashCode());
+    }
+
+    @Test
+    public void testEquals() {
+        RadioChainInfo info = new RadioChainInfo(TEST_CHAIN_ID, TEST_LEVEL_DBM);
+        RadioChainInfo info2 = new RadioChainInfo(TEST_CHAIN_ID2, TEST_LEVEL_DBM2);
+
+        assertThat(info2).isNotEqualTo(info);
+    }
+}
diff --git a/tests/cts/net/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java b/tests/cts/net/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
new file mode 100644
index 0000000..f1f3010
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.nl80211.cts;
+
+import static android.net.wifi.nl80211.WifiNl80211Manager.OemSecurityType;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.WifiNl80211Manager;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/** CTS tests for {@link WifiNl80211Manager}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WifiNl80211ManagerTest {
+
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        // skip tests if Wifi is not supported
+        assumeTrue(WifiFeature.isWifiSupported(mContext));
+    }
+
+    @Test
+    public void testOemSecurityTypeConstructor() {
+        OemSecurityType securityType = new OemSecurityType(
+                ScanResult.PROTOCOL_WPA,
+                Arrays.asList(ScanResult.KEY_MGMT_PSK, ScanResult.KEY_MGMT_SAE),
+                Arrays.asList(ScanResult.CIPHER_NONE, ScanResult.CIPHER_TKIP),
+                ScanResult.CIPHER_CCMP);
+
+        assertThat(securityType.protocol).isEqualTo(ScanResult.PROTOCOL_WPA);
+        assertThat(securityType.keyManagement)
+                .isEqualTo(Arrays.asList(ScanResult.KEY_MGMT_PSK, ScanResult.KEY_MGMT_SAE));
+        assertThat(securityType.pairwiseCipher)
+                .isEqualTo(Arrays.asList(ScanResult.CIPHER_NONE, ScanResult.CIPHER_TKIP));
+        assertThat(securityType.groupCipher).isEqualTo(ScanResult.CIPHER_CCMP);
+    }
+
+    @Test
+    public void testSendMgmtFrame() {
+        try {
+            WifiNl80211Manager manager = mContext.getSystemService(WifiNl80211Manager.class);
+            manager.sendMgmtFrame("wlan0", new byte[]{}, -1, Runnable::run,
+                    new WifiNl80211Manager.SendMgmtFrameCallback() {
+                        @Override
+                        public void onAck(int elapsedTimeMs) {}
+
+                        @Override
+                        public void onFailure(int reason) {}
+                    });
+        } catch (Exception ignore) {}
+    }
+}
diff --git a/tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
index d5361d7..49aa47e 100644
--- a/tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -18,9 +18,12 @@
 
 import static org.mockito.Mockito.mock;
 
+import android.net.MacAddress;
 import android.net.wifi.ScanResult;
+import android.net.wifi.aware.PeerHandle;
 import android.net.wifi.rtt.RangingRequest;
 import android.net.wifi.rtt.RangingResult;
+import android.net.wifi.rtt.ResponderLocation;
 import android.platform.test.annotations.AppModeFull;
 
 import com.android.compatibility.common.util.DeviceReportLog;
@@ -51,6 +54,9 @@
     // Minimum valid RSSI value
     private static final int MIN_VALID_RSSI = -100;
 
+    // Valid Mac Address
+    private static final MacAddress MAC = MacAddress.fromString("00:01:02:03:04:05");
+
     /**
      * Test Wi-Fi RTT ranging operation:
      * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11mc)
@@ -163,7 +169,8 @@
 
         // Analyze results
         assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures + ", ITERATIONS="
-                        + NUM_OF_RTT_ITERATIONS + ", AP RSSI=" + testAp.level,
+                        + NUM_OF_RTT_ITERATIONS + ", AP RSSI=" + testAp.level
+                        + ", AP SSID=" + testAp.SSID,
                 numFailures <= NUM_OF_RTT_ITERATIONS * MAX_FAILURE_RATE_PERCENT / 100);
         if (numFailures != NUM_OF_RTT_ITERATIONS) {
             double distanceAvg = distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
@@ -213,4 +220,189 @@
                         + "many peers",
                 false);
     }
+
+    /**
+     * Verify ResponderLocation API
+     */
+    public void testRangingToTestApWithResponderLocation() throws InterruptedException {
+        if (!shouldTestWifiRtt(getContext())) {
+            return;
+        }
+        // Scan for IEEE 802.11mc supporting APs
+        ScanResult testAp = scanForTestAp(NUM_SCANS_SEARCHING_FOR_IEEE80211MC_AP);
+        assertTrue(
+                "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that "
+                        + "your test setup includes them!",
+                testAp != null);
+
+        // Perform RTT operations
+        RangingRequest request = new RangingRequest.Builder().addAccessPoint(testAp).build();
+        ResultCallback callback = new ResultCallback();
+        mWifiRttManager.startRanging(request, mExecutor, callback);
+        assertTrue("Wi-Fi RTT results: no callback! ",
+                callback.waitForCallback());
+
+        RangingResult result = callback.getResults().get(0);
+        assertEquals("Ranging request not success",
+                result.getStatus(), RangingResult.STATUS_SUCCESS);
+        ResponderLocation responderLocation = result.getUnverifiedResponderLocation();
+        assertNotNull("ResponderLocation should not be null", responderLocation);
+        assertTrue("ResponderLocation is not valid", responderLocation.isLciSubelementValid());
+
+        // Check LCI related APIs
+        int exceptionCount = 0;
+        int apiCount = 0;
+        try {
+            apiCount++;
+            responderLocation.getLatitudeUncertainty();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            responderLocation.getLatitude();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            responderLocation.getLongitudeUncertainty();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            responderLocation.getLongitude();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            responderLocation.getAltitudeType();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            responderLocation.getAltitudeUncertainty();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            responderLocation.getAltitude();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            responderLocation.getDatum();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            responderLocation.getRegisteredLocationAgreementIndication();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            responderLocation.getLciVersion();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        try {
+            apiCount++;
+            assertNotNull(responderLocation.toLocation());
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        // If LCI is not valid, all APIs should throw exception, otherwise no exception.
+        assertEquals("Exception number should equal to API number",
+                responderLocation.isLciSubelementValid()? 0 : apiCount, exceptionCount);
+
+        // Verify ZaxisSubelement APIs
+        apiCount = 0;
+        exceptionCount = 0;
+
+        try {
+            apiCount++;
+            responderLocation.getExpectedToMove();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+
+        try {
+            apiCount++;
+            responderLocation.getFloorNumber();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+
+        try {
+            apiCount++;
+            responderLocation.getHeightAboveFloorMeters();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+
+        try {
+            apiCount++;
+            responderLocation.getHeightAboveFloorUncertaintyMeters();
+        } catch (IllegalStateException e) {
+            exceptionCount++;
+        }
+        // If Zaxis is not valid, all APIs should throw exception, otherwise no exception.
+        assertEquals("Exception number should equal to API number",
+                responderLocation.isZaxisSubelementValid() ? 0 : apiCount, exceptionCount);
+        // Verify civic location
+        if (responderLocation.toCivicLocationAddress() == null) {
+            assertNull(responderLocation.toCivicLocationSparseArray());
+        } else {
+            assertNotNull(responderLocation.toCivicLocationSparseArray());
+        }
+        // Verify map image
+        if (responderLocation.getMapImageUri() == null) {
+            assertNull(responderLocation.getMapImageMimeType());
+        } else {
+            assertNotNull(responderLocation.getMapImageMimeType());
+        }
+        boolean extraInfoOnAssociationIndication =
+                responderLocation.getExtraInfoOnAssociationIndication();
+        assertNotNull("ColocatedBSSID list should be nonNull",
+                responderLocation.getColocatedBssids());
+    }
+
+    /**
+     * Verify ranging request with aware peer Mac address and peer handle.
+     */
+    public void testAwareRttWithMacAddress() throws InterruptedException {
+        RangingRequest request = new RangingRequest.Builder()
+                .addWifiAwarePeer(MAC).build();
+        ResultCallback callback = new ResultCallback();
+        mWifiRttManager.startRanging(request, mExecutor, callback);
+        assertTrue("Wi-Fi RTT results: no callback",
+                callback.waitForCallback());
+        List<RangingResult> rangingResults = callback.getResults();
+        assertNotNull("Wi-Fi RTT results: null results", rangingResults);
+        assertEquals(1, rangingResults.size());
+        assertEquals(RangingResult.STATUS_FAIL, rangingResults.get(0).getStatus());
+    }
+
+    /**
+     * Verify ranging request with aware peer handle.
+     */
+    public void testAwareRttWithPeerHandle() throws InterruptedException {
+        PeerHandle peerHandle = mock(PeerHandle.class);
+        RangingRequest request = new RangingRequest.Builder()
+                .addWifiAwarePeer(peerHandle).build();
+        ResultCallback callback = new ResultCallback();
+        mWifiRttManager.startRanging(request, mExecutor, callback);
+        assertTrue("Wi-Fi RTT results: no callback",
+                callback.waitForCallback());
+        List<RangingResult> rangingResults = callback.getResults();
+        assertNotNull("Wi-Fi RTT results: null results", rangingResults);
+        assertEquals("Invalid peerHandle should return 0 result", 0, rangingResults.size());
+    }
 }
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index 98dbe52..4d72eae 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -180,15 +180,15 @@
         }
     }
 
-    private class StartTetheringCallback extends TetheringManager.StartTetheringCallback {
+    private class StartTetheringCallback implements TetheringManager.StartTetheringCallback {
         @Override
         public void onTetheringStarted() {
             // Do nothing, TetherChangeReceiver will wait until it receives the broadcast.
         }
 
         @Override
-        public void onTetheringFailed(final int resultCode) {
-            fail("startTethering fail: " + resultCode);
+        public void onTetheringFailed(final int error) {
+            fail("startTethering fail: " + error);
         }
     }