blob: 115210b405a4db9f46d65bac2a53aea17d27a90d [file] [log] [blame]
/*
* Copyright (C) 2024 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.google.snippet.connectivity
import android.Manifest.permission.OVERRIDE_WIFI_CONFIG
import android.content.pm.PackageManager.FEATURE_TELEPHONY
import android.content.pm.PackageManager.FEATURE_WIFI
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkRequest
import android.net.cts.util.CtsNetUtils
import android.net.cts.util.CtsTetheringUtils
import android.net.wifi.ScanResult
import android.net.wifi.SoftApConfiguration
import android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
import android.net.wifi.WifiConfiguration
import android.net.wifi.WifiManager
import android.net.wifi.WifiNetworkSpecifier
import android.net.wifi.WifiSsid
import androidx.test.platform.app.InstrumentationRegistry
import com.android.testutils.ConnectUtil
import com.android.testutils.RecorderCallback.CallbackEntry.Available
import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.runAsShell
import com.google.android.mobly.snippet.Snippet
import com.google.android.mobly.snippet.rpc.Rpc
class ConnectivityMultiDevicesSnippet : Snippet {
private val context = InstrumentationRegistry.getInstrumentation().getTargetContext()
private val wifiManager = context.getSystemService(WifiManager::class.java)!!
private val cm = context.getSystemService(ConnectivityManager::class.java)!!
private val pm = context.packageManager
private val ctsNetUtils = CtsNetUtils(context)
private val ctsTetheringUtils = CtsTetheringUtils(context)
private var oldSoftApConfig: SoftApConfiguration? = null
@Rpc(description = "Check whether the device has wifi feature.")
fun hasWifiFeature() = pm.hasSystemFeature(FEATURE_WIFI)
@Rpc(description = "Check whether the device has telephony feature.")
fun hasTelephonyFeature() = pm.hasSystemFeature(FEATURE_TELEPHONY)
@Rpc(description = "Check whether the device supporters AP + STA concurrency.")
fun isStaApConcurrencySupported() {
wifiManager.isStaApConcurrencySupported()
}
@Rpc(description = "Request cellular connection and ensure it is the default network.")
fun requestCellularAndEnsureDefault() {
ctsNetUtils.disableWifi()
val network = ctsNetUtils.connectToCell()
ctsNetUtils.expectNetworkIsSystemDefault(network)
}
@Rpc(description = "Unrequest cellular connection.")
fun unrequestCellular() {
ctsNetUtils.disconnectFromCell()
}
@Rpc(description = "Ensure any wifi is connected and is the default network.")
fun ensureWifiIsDefault() {
val network = ctsNetUtils.ensureWifiConnected()
ctsNetUtils.expectNetworkIsSystemDefault(network)
}
@Rpc(description = "Connect to specified wifi network.")
// Suppress warning because WifiManager methods to connect to a config are
// documented not to be deprecated for privileged users.
@Suppress("DEPRECATION")
fun connectToWifi(ssid: String, passphrase: String, requireValidation: Boolean): Network {
val specifier = WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(passphrase)
.setBand(ScanResult.WIFI_BAND_24_GHZ)
.build()
val wifiConfig = WifiConfiguration()
wifiConfig.SSID = "\"" + ssid + "\""
wifiConfig.preSharedKey = "\"" + passphrase + "\""
wifiConfig.hiddenSSID = true
wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK)
wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP)
wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP)
// Register network callback for the specific wifi.
val networkCallback = TestableNetworkCallback()
val wifiRequest = NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI)
.setNetworkSpecifier(specifier)
.build()
cm.registerNetworkCallback(wifiRequest, networkCallback)
try {
// Add the test configuration and connect to it.
val connectUtil = ConnectUtil(context)
connectUtil.connectToWifiConfig(wifiConfig)
val event = networkCallback.expect<Available>()
if (requireValidation) {
networkCallback.eventuallyExpect<CapabilitiesChanged> {
it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
}
}
return event.network
} finally {
cm.unregisterNetworkCallback(networkCallback)
}
}
@Rpc(description = "Check whether the device supports hotspot feature.")
fun hasHotspotFeature(): Boolean {
val tetheringCallback = ctsTetheringUtils.registerTetheringEventCallback()
try {
return tetheringCallback.isWifiTetheringSupported(context)
} finally {
ctsTetheringUtils.unregisterTetheringEventCallback(tetheringCallback)
}
}
@Rpc(description = "Start a hotspot with given SSID and passphrase.")
fun startHotspot(ssid: String, passphrase: String) {
// Store old config.
runAsShell(OVERRIDE_WIFI_CONFIG) {
oldSoftApConfig = wifiManager.getSoftApConfiguration()
}
val softApConfig = SoftApConfiguration.Builder()
.setWifiSsid(WifiSsid.fromBytes(ssid.toByteArray()))
.setPassphrase(passphrase, SECURITY_TYPE_WPA2_PSK)
.setBand(SoftApConfiguration.BAND_2GHZ)
.build()
runAsShell(OVERRIDE_WIFI_CONFIG) {
wifiManager.setSoftApConfiguration(softApConfig)
}
val tetheringCallback = ctsTetheringUtils.registerTetheringEventCallback()
try {
tetheringCallback.expectNoTetheringActive()
ctsTetheringUtils.startWifiTethering(tetheringCallback)
} finally {
ctsTetheringUtils.unregisterTetheringEventCallback(tetheringCallback)
}
}
@Rpc(description = "Stop all tethering.")
fun stopAllTethering() {
ctsTetheringUtils.stopAllTethering()
// Restore old config.
oldSoftApConfig?.let {
runAsShell(OVERRIDE_WIFI_CONFIG) {
wifiManager.setSoftApConfiguration(it)
}
}
}
}