Merge changes I8843ce7c,I90566998 into main
* changes: Block the package updater while CTS are running Add a command to block networking for an app
This commit is contained in:
@@ -97,14 +97,12 @@ import static android.os.Process.VPN_UID;
|
|||||||
import static android.system.OsConstants.ETH_P_ALL;
|
import static android.system.OsConstants.ETH_P_ALL;
|
||||||
import static android.system.OsConstants.IPPROTO_TCP;
|
import static android.system.OsConstants.IPPROTO_TCP;
|
||||||
import static android.system.OsConstants.IPPROTO_UDP;
|
import static android.system.OsConstants.IPPROTO_UDP;
|
||||||
|
|
||||||
import static com.android.net.module.util.NetworkMonitorUtils.isPrivateDnsValidationRequired;
|
import static com.android.net.module.util.NetworkMonitorUtils.isPrivateDnsValidationRequired;
|
||||||
import static com.android.net.module.util.PermissionUtils.checkAnyPermissionOf;
|
import static com.android.net.module.util.PermissionUtils.checkAnyPermissionOf;
|
||||||
import static com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf;
|
import static com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf;
|
||||||
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermission;
|
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermission;
|
||||||
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermissionOr;
|
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermissionOr;
|
||||||
import static com.android.server.ConnectivityStatsLog.CONNECTIVITY_STATE_SAMPLE;
|
import static com.android.server.ConnectivityStatsLog.CONNECTIVITY_STATE_SAMPLE;
|
||||||
|
|
||||||
import static java.util.Map.Entry;
|
import static java.util.Map.Entry;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
@@ -10614,6 +10612,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
err.getFileDescriptor(), args);
|
err.getFileDescriptor(), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Boolean parseBooleanArgument(final String arg) {
|
||||||
|
if ("true".equals(arg)) {
|
||||||
|
return true;
|
||||||
|
} else if ("false".equals(arg)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ShellCmd extends BasicShellCommandHandler {
|
private class ShellCmd extends BasicShellCommandHandler {
|
||||||
@Override
|
@Override
|
||||||
public int onCommand(String cmd) {
|
public int onCommand(String cmd) {
|
||||||
@@ -10643,6 +10651,54 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
onHelp();
|
onHelp();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
case "set-chain3-enabled": {
|
||||||
|
final Boolean enabled = parseBooleanArgument(getNextArg());
|
||||||
|
if (null == enabled) {
|
||||||
|
onHelp();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Log.i(TAG, (enabled ? "En" : "Dis") + "abled FIREWALL_CHAIN_OEM_DENY_3");
|
||||||
|
setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3,
|
||||||
|
enabled);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case "get-chain3-enabled": {
|
||||||
|
final boolean chainEnabled = getFirewallChainEnabled(
|
||||||
|
ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3);
|
||||||
|
pw.println("chain:" + (chainEnabled ? "enabled" : "disabled"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case "set-package-networking-enabled": {
|
||||||
|
final Boolean enabled = parseBooleanArgument(getNextArg());
|
||||||
|
final String packageName = getNextArg();
|
||||||
|
if (null == enabled || null == packageName) {
|
||||||
|
onHelp();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Throws NameNotFound if the package doesn't exist.
|
||||||
|
final int appId = setPackageFirewallRule(
|
||||||
|
ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3,
|
||||||
|
packageName, enabled ? FIREWALL_RULE_DEFAULT : FIREWALL_RULE_DENY);
|
||||||
|
final String msg = (enabled ? "Enabled" : "Disabled")
|
||||||
|
+ " networking for " + packageName + ", appId " + appId;
|
||||||
|
Log.i(TAG, msg);
|
||||||
|
pw.println(msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case "get-package-networking-enabled": {
|
||||||
|
final String packageName = getNextArg();
|
||||||
|
final int rule = getPackageFirewallRule(
|
||||||
|
ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3, packageName);
|
||||||
|
if (FIREWALL_RULE_ALLOW == rule || FIREWALL_RULE_DEFAULT == rule) {
|
||||||
|
pw.println(packageName + ":" + "allow");
|
||||||
|
} else if (FIREWALL_RULE_DENY == rule) {
|
||||||
|
pw.println(packageName + ":" + "deny");
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unknown rule " + rule + " for package "
|
||||||
|
+ packageName);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
case "reevaluate":
|
case "reevaluate":
|
||||||
// Usage : adb shell cmd connectivity reevaluate <netId>
|
// Usage : adb shell cmd connectivity reevaluate <netId>
|
||||||
// If netId is omitted, then reevaluate the default network
|
// If netId is omitted, then reevaluate the default network
|
||||||
@@ -10683,6 +10739,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
pw.println(" Turn airplane mode on or off.");
|
pw.println(" Turn airplane mode on or off.");
|
||||||
pw.println(" airplane-mode");
|
pw.println(" airplane-mode");
|
||||||
pw.println(" Get airplane mode.");
|
pw.println(" Get airplane mode.");
|
||||||
|
pw.println(" set-chain3-enabled [true|false]");
|
||||||
|
pw.println(" Enable or disable FIREWALL_CHAIN_OEM_DENY_3 for debugging.");
|
||||||
|
pw.println(" get-chain3-enabled");
|
||||||
|
pw.println(" Returns whether FIREWALL_CHAIN_OEM_DENY_3 is enabled.");
|
||||||
|
pw.println(" set-package-networking-enabled [true|false] [package name]");
|
||||||
|
pw.println(" Set the deny bit in FIREWALL_CHAIN_OEM_DENY_3 to package. This has\n"
|
||||||
|
+ " no effect if the chain is disabled.");
|
||||||
|
pw.println(" get-package-networking-enabled [package name]");
|
||||||
|
pw.println(" Get the deny bit in FIREWALL_CHAIN_OEM_DENY_3 for package.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12418,6 +12483,21 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int setPackageFirewallRule(final int chain, final String packageName, final int rule)
|
||||||
|
throws PackageManager.NameNotFoundException {
|
||||||
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
|
final int appId = UserHandle.getAppId(pm.getPackageUid(packageName, 0 /* flags */));
|
||||||
|
if (appId < Process.FIRST_APPLICATION_UID) {
|
||||||
|
throw new RuntimeException("Can't set package firewall rule for system app "
|
||||||
|
+ packageName + " with appId " + appId);
|
||||||
|
}
|
||||||
|
for (final UserHandle uh : mUserManager.getUserHandles(false /* excludeDying */)) {
|
||||||
|
final int uid = uh.getUid(appId);
|
||||||
|
setUidFirewallRule(chain, uid, rule);
|
||||||
|
}
|
||||||
|
return appId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUidFirewallRule(final int chain, final int uid, final int rule) {
|
public void setUidFirewallRule(final int chain, final int uid, final int rule) {
|
||||||
enforceNetworkStackOrSettingsPermission();
|
enforceNetworkStackOrSettingsPermission();
|
||||||
@@ -12436,6 +12516,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getPackageFirewallRule(final int chain, final String packageName)
|
||||||
|
throws PackageManager.NameNotFoundException {
|
||||||
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
|
final int appId = UserHandle.getAppId(pm.getPackageUid(packageName, 0 /* flags */));
|
||||||
|
return getUidFirewallRule(chain, appId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getUidFirewallRule(final int chain, final int uid) {
|
public int getUidFirewallRule(final int chain, final int uid) {
|
||||||
enforceNetworkStackOrSettingsPermission();
|
enforceNetworkStackOrSettingsPermission();
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ private const val CONNECTIVITY_CHECK_CLASS = "$CONNECTIVITY_PKG_NAME.Connectivit
|
|||||||
private const val CONNECTIVITY_CHECK_RUNNER_NAME = "androidx.test.runner.AndroidJUnitRunner"
|
private const val CONNECTIVITY_CHECK_RUNNER_NAME = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
private const val IGNORE_CONN_CHECK_OPTION = "ignore-connectivity-check"
|
private const val IGNORE_CONN_CHECK_OPTION = "ignore-connectivity-check"
|
||||||
|
|
||||||
|
// The default updater package names, which might be updating packages while the CTS
|
||||||
|
// are running
|
||||||
|
private val UPDATER_PKGS = arrayOf("com.google.android.gms", "com.android.vending")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A target preparer that sets up and verifies a device for connectivity tests.
|
* A target preparer that sets up and verifies a device for connectivity tests.
|
||||||
*
|
*
|
||||||
@@ -45,35 +49,42 @@ open class ConnectivityTestTargetPreparer : BaseTargetPreparer() {
|
|||||||
@Option(name = IGNORE_CONN_CHECK_OPTION,
|
@Option(name = IGNORE_CONN_CHECK_OPTION,
|
||||||
description = "Disables the check for mobile data and wifi")
|
description = "Disables the check for mobile data and wifi")
|
||||||
private var ignoreConnectivityCheck = false
|
private var ignoreConnectivityCheck = false
|
||||||
|
// The default value is never used, but false is a reasonable default
|
||||||
|
private var originalTestChainEnabled = false
|
||||||
|
private val originalUpdaterPkgsStatus = HashMap<String, Boolean>()
|
||||||
|
|
||||||
override fun setUp(testInformation: TestInformation) {
|
override fun setUp(testInfo: TestInformation) {
|
||||||
if (isDisabled) return
|
if (isDisabled) return
|
||||||
disableGmsUpdate(testInformation)
|
disableGmsUpdate(testInfo)
|
||||||
runPreparerApk(testInformation)
|
originalTestChainEnabled = getTestChainEnabled(testInfo)
|
||||||
|
originalUpdaterPkgsStatus.putAll(getUpdaterPkgsStatus(testInfo))
|
||||||
|
setUpdaterNetworkingEnabled(testInfo, enableChain = true,
|
||||||
|
enablePkgs = UPDATER_PKGS.associateWith { false })
|
||||||
|
runPreparerApk(testInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runPreparerApk(testInformation: TestInformation) {
|
private fun runPreparerApk(testInfo: TestInformation) {
|
||||||
installer.setCleanApk(true)
|
installer.setCleanApk(true)
|
||||||
installer.addTestFileName(CONNECTIVITY_CHECKER_APK)
|
installer.addTestFileName(CONNECTIVITY_CHECKER_APK)
|
||||||
installer.setShouldGrantPermission(true)
|
installer.setShouldGrantPermission(true)
|
||||||
installer.setUp(testInformation)
|
installer.setUp(testInfo)
|
||||||
|
|
||||||
val runner = DefaultRemoteAndroidTestRunner(
|
val runner = DefaultRemoteAndroidTestRunner(
|
||||||
CONNECTIVITY_PKG_NAME,
|
CONNECTIVITY_PKG_NAME,
|
||||||
CONNECTIVITY_CHECK_RUNNER_NAME,
|
CONNECTIVITY_CHECK_RUNNER_NAME,
|
||||||
testInformation.device.iDevice)
|
testInfo.device.iDevice)
|
||||||
runner.runOptions = "--no-hidden-api-checks"
|
runner.runOptions = "--no-hidden-api-checks"
|
||||||
|
|
||||||
val receiver = CollectingTestListener()
|
val receiver = CollectingTestListener()
|
||||||
if (!testInformation.device.runInstrumentationTests(runner, receiver)) {
|
if (!testInfo.device.runInstrumentationTests(runner, receiver)) {
|
||||||
throw TargetSetupError("Device state check failed to complete",
|
throw TargetSetupError("Device state check failed to complete",
|
||||||
testInformation.device.deviceDescriptor)
|
testInfo.device.deviceDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
val runResult = receiver.currentRunResults
|
val runResult = receiver.currentRunResults
|
||||||
if (runResult.isRunFailure) {
|
if (runResult.isRunFailure) {
|
||||||
throw TargetSetupError("Failed to check device state before the test: " +
|
throw TargetSetupError("Failed to check device state before the test: " +
|
||||||
runResult.runFailureMessage, testInformation.device.deviceDescriptor)
|
runResult.runFailureMessage, testInfo.device.deviceDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
val ignoredTestClasses = mutableSetOf<String>()
|
val ignoredTestClasses = mutableSetOf<String>()
|
||||||
@@ -92,25 +103,50 @@ open class ConnectivityTestTargetPreparer : BaseTargetPreparer() {
|
|||||||
if (errorMsg.isBlank()) return
|
if (errorMsg.isBlank()) return
|
||||||
|
|
||||||
throw TargetSetupError("Device setup checks failed. Check the test bench: \n$errorMsg",
|
throw TargetSetupError("Device setup checks failed. Check the test bench: \n$errorMsg",
|
||||||
testInformation.device.deviceDescriptor)
|
testInfo.device.deviceDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun disableGmsUpdate(testInformation: TestInformation) {
|
private fun disableGmsUpdate(testInfo: TestInformation) {
|
||||||
// This will be a no-op on devices without root (su) or not using gservices, but that's OK.
|
// This will be a no-op on devices without root (su) or not using gservices, but that's OK.
|
||||||
testInformation.device.executeShellCommand("su 0 am broadcast " +
|
testInfo.exec("su 0 am broadcast " +
|
||||||
"-a com.google.gservices.intent.action.GSERVICES_OVERRIDE " +
|
"-a com.google.gservices.intent.action.GSERVICES_OVERRIDE " +
|
||||||
"-e finsky.play_services_auto_update_enabled false")
|
"-e finsky.play_services_auto_update_enabled false")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearGmsUpdateOverride(testInformation: TestInformation) {
|
private fun clearGmsUpdateOverride(testInfo: TestInformation) {
|
||||||
testInformation.device.executeShellCommand("su 0 am broadcast " +
|
testInfo.exec("su 0 am broadcast " +
|
||||||
"-a com.google.gservices.intent.action.GSERVICES_OVERRIDE " +
|
"-a com.google.gservices.intent.action.GSERVICES_OVERRIDE " +
|
||||||
"--esn finsky.play_services_auto_update_enabled")
|
"--esn finsky.play_services_auto_update_enabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tearDown(testInformation: TestInformation, e: Throwable?) {
|
private fun setUpdaterNetworkingEnabled(
|
||||||
|
testInfo: TestInformation,
|
||||||
|
enableChain: Boolean,
|
||||||
|
enablePkgs: Map<String, Boolean>
|
||||||
|
) {
|
||||||
|
// Build.VERSION_CODES.S = 31 where this is not available, then do nothing.
|
||||||
|
if (testInfo.device.getApiLevel() < 31) return
|
||||||
|
testInfo.exec("cmd connectivity set-chain3-enabled $enableChain")
|
||||||
|
enablePkgs.forEach { (pkg, allow) ->
|
||||||
|
testInfo.exec("cmd connectivity set-package-networking-enabled $pkg $allow")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTestChainEnabled(testInfo: TestInformation) =
|
||||||
|
testInfo.exec("cmd connectivity get-chain3-enabled").contains("chain:enabled")
|
||||||
|
|
||||||
|
private fun getUpdaterPkgsStatus(testInfo: TestInformation) =
|
||||||
|
UPDATER_PKGS.associateWith { pkg ->
|
||||||
|
!testInfo.exec("cmd connectivity get-package-networking-enabled $pkg")
|
||||||
|
.contains(":deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tearDown(testInfo: TestInformation, e: Throwable?) {
|
||||||
if (isTearDownDisabled) return
|
if (isTearDownDisabled) return
|
||||||
installer.tearDown(testInformation, e)
|
installer.tearDown(testInfo, e)
|
||||||
clearGmsUpdateOverride(testInformation)
|
setUpdaterNetworkingEnabled(testInfo,
|
||||||
|
enableChain = originalTestChainEnabled,
|
||||||
|
enablePkgs = originalUpdaterPkgsStatus)
|
||||||
|
clearGmsUpdateOverride(testInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,4 +58,4 @@ class DisableConfigSyncTargetPreparer : BaseTargetPreparer() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TestInformation.exec(cmd: String) = this.device.executeShellCommand(cmd)
|
fun TestInformation.exec(cmd: String) = this.device.executeShellCommand(cmd)
|
||||||
|
|||||||
Reference in New Issue
Block a user