Add ConnectivityCheckTargetPreparer

ConnectivityCheckTargetPreparer is a tradefed target preparer that uses
the connectivitychecker app to verify device configuration, before
running any test.

The connectivitychecker app verifies that the device has a
pre-configured wifi configuration and can connect to it (except for
virtual devices where it may create the configuration itself), and
verifies that the device has a data-enabled SIM card inserted.

Checks are skipped if the device is not wifi- or mobile data-capable,
and can be skipped for local testing by running with:

  atest X -- --test-arg \
    com.android.testutils.ConnectivityCheckTargetPreparer:disable:true

Test: atest CtsNetTestCasesLatestSdk
Change-Id: I5b6d34a6c393863af23af57ff026b15973e9e784
diff --git a/staticlibs/testutils/app/connectivitychecker/Android.bp b/staticlibs/testutils/app/connectivitychecker/Android.bp
new file mode 100644
index 0000000..55b585a
--- /dev/null
+++ b/staticlibs/testutils/app/connectivitychecker/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 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.
+
+android_test_helper_app {
+    name: "ConnectivityChecker",
+    srcs: ["src/**/*.kt"],
+    sdk_version: "system_current",
+    // Allow running the test on any device with SDK Q+, even when built from a branch that uses
+    // an unstable SDK, by targeting a stable SDK regardless of the build SDK.
+    min_sdk_version: "29",
+    target_sdk_version: "30",
+    static_libs: [
+        "androidx.test.rules",
+        "modules-utils-build_system",
+        "net-tests-utils",
+    ],
+    host_required: ["net-tests-utils-host-common"],
+}
\ No newline at end of file
diff --git a/staticlibs/testutils/app/connectivitychecker/AndroidManifest.xml b/staticlibs/testutils/app/connectivitychecker/AndroidManifest.xml
new file mode 100644
index 0000000..8e5958c
--- /dev/null
+++ b/staticlibs/testutils/app/connectivitychecker/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.testutils.connectivitychecker">
+
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <!-- For wifi scans -->
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.testutils.connectivitychecker"
+                     android:label="Connectivity checker target preparer" />
+</manifest>
diff --git a/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitychecker/ConnectivityCheckTest.kt b/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitychecker/ConnectivityCheckTest.kt
new file mode 100644
index 0000000..43b130b
--- /dev/null
+++ b/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitychecker/ConnectivityCheckTest.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.testutils.connectivitychecker
+
+import android.content.pm.PackageManager.FEATURE_TELEPHONY
+import android.content.pm.PackageManager.FEATURE_WIFI
+import android.telephony.TelephonyManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.testutils.ConnectUtil
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertTrue
+import kotlin.test.fail
+
+@RunWith(AndroidJUnit4::class)
+class ConnectivityCheckTest {
+    val context by lazy { InstrumentationRegistry.getInstrumentation().context }
+    val pm by lazy { context.packageManager }
+
+    @Test
+    fun testCheckDeviceSetup() {
+        checkWifiSetup()
+        checkTelephonySetup()
+    }
+
+    private fun checkWifiSetup() {
+        if (!pm.hasSystemFeature(FEATURE_WIFI)) return
+        ConnectUtil(context).ensureWifiConnected()
+    }
+
+    private fun checkTelephonySetup() {
+        if (!pm.hasSystemFeature(FEATURE_TELEPHONY)) return
+        val tm = context.getSystemService(TelephonyManager::class.java)
+                ?: fail("Could not get telephony service")
+
+        val commonError = "Check the test bench. To run the tests anyway for quick & dirty local " +
+                "testing, you can use atest X -- " +
+                "--test-arg com.android.testutils.ConnectivityCheckTargetPreparer:disable:true"
+        // Do not use assertEquals: it outputs "expected X, was Y", which looks like a test failure
+        if (tm.simState == TelephonyManager.SIM_STATE_ABSENT) {
+            fail("The device has no SIM card inserted. " + commonError)
+        } else if (tm.simState != TelephonyManager.SIM_STATE_READY) {
+            fail("The device is not setup with a usable SIM card. Sim state was ${tm.simState}. " +
+                    commonError)
+        }
+        assertTrue(tm.isDataConnectivityPossible,
+            "The device is not setup with a SIM card that supports data connectivity. " +
+                    commonError)
+    }
+}
\ No newline at end of file