From 2f82a83bb1a34c3e16326fc3915984d39d076694 Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Fri, 13 Nov 2020 00:26:31 +0000 Subject: [PATCH] Revert "Merge history of CTS" This reverts commit 4cf61e4609c895beb61605784506d6323239099f. Reason for revert: Re-Establish with History Merged-In: I91190d8644ff7a7dfaf4fa3f2d43c17f67dfac11 Change-Id: Iea881b738f7d80bfe6931ae4f4c808560c01f282 --- tests/cts/hostside/Android.bp | 30 - tests/cts/hostside/AndroidTest.xml | 41 - tests/cts/hostside/OWNERS | 4 - tests/cts/hostside/aidl/Android.bp | 24 - .../android/cts/net/hostside/IMyService.aidl | 29 - .../cts/net/hostside/INetworkCallback.aidl | 27 - .../net/hostside/INetworkStateObserver.aidl | 22 - .../net/hostside/IRemoteSocketFactory.aidl | 25 - tests/cts/hostside/app/Android.bp | 41 - tests/cts/hostside/app/AndroidManifest.xml | 56 - .../net/hostside/AbstractAppIdleTestCase.java | 190 --- .../AbstractBatterySaverModeTestCase.java | 111 -- .../hostside/AbstractDozeModeTestCase.java | 141 -- ...ractRestrictBackgroundNetworkTestCase.java | 881 ----------- .../cts/net/hostside/AppIdleMeteredTest.java | 23 - .../net/hostside/AppIdleNonMeteredTest.java | 23 - .../hostside/BatterySaverModeMeteredTest.java | 23 - .../BatterySaverModeNonMeteredTest.java | 24 - .../cts/net/hostside/DataSaverModeTest.java | 207 --- .../cts/net/hostside/DozeModeMeteredTest.java | 23 - .../net/hostside/DozeModeNonMeteredTest.java | 23 - .../cts/net/hostside/DumpOnFailureRule.java | 92 -- .../MeterednessConfigurationRule.java | 60 - .../cts/net/hostside/MixedModesTest.java | 370 ----- .../android/cts/net/hostside/MyActivity.java | 49 - .../MyNotificationListenerService.java | 123 -- .../cts/net/hostside/MyServiceClient.java | 107 -- .../cts/net/hostside/MyVpnService.java | 184 --- .../cts/net/hostside/NetworkCallbackTest.java | 300 ---- .../net/hostside/NetworkPolicyTestRunner.java | 44 - .../net/hostside/NetworkPolicyTestUtils.java | 284 ---- .../cts/net/hostside/PacketReflector.java | 254 --- .../android/cts/net/hostside/Property.java | 70 - .../hostside/RemoteSocketFactoryClient.java | 100 -- .../cts/net/hostside/RequiredProperties.java | 31 - .../net/hostside/RequiredPropertiesRule.java | 94 -- .../com/android/cts/net/hostside/VpnTest.java | 1090 ------------- tests/cts/hostside/app2/Android.bp | 30 - tests/cts/hostside/app2/AndroidManifest.xml | 55 - .../app2/res/drawable/ic_notification.png | Bin 3777 -> 0 bytes .../android/cts/net/hostside/app2/Common.java | 94 -- .../cts/net/hostside/app2/MyActivity.java | 75 - .../hostside/app2/MyBroadcastReceiver.java | 267 ---- .../hostside/app2/MyForegroundService.java | 72 - .../cts/net/hostside/app2/MyService.java | 193 --- .../app2/RemoteSocketFactoryService.java | 63 - tests/cts/hostside/certs/Android.bp | 4 - tests/cts/hostside/certs/README | 2 - tests/cts/hostside/certs/cts-net-app.pk8 | Bin 1219 -> 0 bytes tests/cts/hostside/certs/cts-net-app.x509.pem | 19 - .../cts/net/HostsideNetworkCallbackTests.java | 42 - .../cts/net/HostsideNetworkTestCase.java | 186 --- ...ostsideRestrictBackgroundNetworkTests.java | 377 ----- .../com/android/cts/net/HostsideVpnTests.java | 98 -- .../cts/net/NetworkPolicyTestsPreparer.java | 92 -- .../src/com/android/cts/net/ProcNetTest.java | 169 -- tests/cts/net/Android.bp | 85 - tests/cts/net/AndroidManifest.xml | 57 - tests/cts/net/AndroidTestTemplate.xml | 35 - tests/cts/net/OWNERS | 3 - tests/cts/net/TEST_MAPPING | 23 - tests/cts/net/api23Test/Android.bp | 52 - tests/cts/net/api23Test/AndroidManifest.xml | 45 - tests/cts/net/api23Test/AndroidTest.xml | 31 - .../ConnectivityManagerApi23Test.java | 132 -- .../cts/api23test/ConnectivityReceiver.java | 69 - tests/cts/net/appForApi23/Android.bp | 33 - tests/cts/net/appForApi23/AndroidManifest.xml | 47 - .../ConnectivityListeningActivity.java | 22 - .../cts/appForApi23/ConnectivityReceiver.java | 41 - ...etwork_watchlist_config_empty_for_test.xml | 29 - .../network_watchlist_config_for_test.xml | 34 - tests/cts/net/jarjar-rules-shared.txt | 2 - tests/cts/net/jni/Android.bp | 51 - tests/cts/net/jni/NativeDnsJni.c | 181 --- tests/cts/net/jni/NativeMultinetworkJni.cpp | 515 ------ tests/cts/net/native/dns/Android.bp | 40 - tests/cts/net/native/dns/AndroidTest.xml | 32 - .../cts/net/native/dns/NativeDnsAsyncTest.cpp | 257 --- tests/cts/net/native/qtaguid/Android.bp | 53 - tests/cts/net/native/qtaguid/AndroidTest.xml | 32 - .../native/qtaguid/src/NativeQtaguidTest.cpp | 130 -- .../src/android/net/cts/AirplaneModeTest.java | 86 - .../src/android/net/cts/CaptivePortalTest.kt | 194 --- .../ConnectivityDiagnosticsManagerTest.java | 576 ------- .../net/cts/ConnectivityManagerTest.java | 1384 ----------------- .../src/android/net/cts/CredentialsTest.java | 44 - .../src/android/net/cts/DnsResolverTest.java | 763 --------- .../cts/net/src/android/net/cts/DnsTest.java | 309 ---- .../net/src/android/net/cts/IkeTunUtils.java | 188 --- .../net/src/android/net/cts/Ikev2VpnTest.java | 535 ------- .../android/net/cts/InetAddressesTest.java | 134 -- .../android/net/cts/IpConfigurationTest.java | 123 -- .../src/android/net/cts/IpSecBaseTest.java | 556 ------- .../src/android/net/cts/IpSecManagerTest.java | 1189 -------------- .../net/cts/IpSecManagerTunnelTest.java | 899 ----------- .../net/cts/LocalServerSocketTest.java | 61 - .../net/cts/LocalSocketAddressTest.java | 47 - .../cts/LocalSocketAddress_NamespaceTest.java | 36 - .../src/android/net/cts/LocalSocketTest.java | 470 ------ .../src/android/net/cts/MacAddressTest.java | 223 --- .../net/src/android/net/cts/MailToTest.java | 125 -- .../android/net/cts/MultinetworkApiTest.java | 240 --- .../src/android/net/cts/NetworkAgentTest.kt | 641 -------- .../src/android/net/cts/NetworkInfoTest.kt | 122 -- .../cts/NetworkInfo_DetailedStateTest.java | 56 - .../net/cts/NetworkInfo_StateTest.java | 43 - .../android/net/cts/NetworkRequestTest.java | 276 ---- .../net/cts/NetworkStackDependenciesTest.kt | 53 - .../net/cts/NetworkStatsBinderTest.java | 146 -- .../android/net/cts/NetworkValidationTest.kt | 245 --- .../net/cts/NetworkValidationTestUtil.kt | 68 - .../android/net/cts/NetworkWatchlistTest.java | 163 -- .../net/src/android/net/cts/PacketUtils.java | 474 ------ .../src/android/net/cts/ProxyInfoTest.java | 135 -- .../net/src/android/net/cts/ProxyTest.java | 39 - .../src/android/net/cts/RssiCurveTest.java | 102 -- .../cts/SSLCertificateSocketFactoryTest.java | 348 ----- .../src/android/net/cts/TheaterModeTest.java | 84 - .../src/android/net/cts/TrafficStatsTest.java | 279 ---- .../cts/net/src/android/net/cts/TunUtils.java | 254 --- .../cts/net/src/android/net/cts/UriTest.java | 590 ------- .../src/android/net/cts/Uri_BuilderTest.java | 64 - .../net/cts/UrlQuerySanitizerTest.java | 290 ---- ...er_IllegalCharacterValueSanitizerTest.java | 29 - ...QuerySanitizer_ParameterValuePairTest.java | 33 - .../src/android/net/cts/VpnServiceTest.java | 124 -- .../src/android/net/ipv6/cts/PingTest.java | 172 -- .../android/net/rtp/cts/AudioCodecTest.java | 73 - .../android/net/rtp/cts/AudioGroupTest.java | 177 --- .../android/net/rtp/cts/AudioStreamTest.java | 96 -- tests/cts/net/util/Android.bp | 26 - .../android/net/cts/util/CtsNetUtils.java | 693 --------- .../net/cts/util/CtsTetheringUtils.java | 397 ----- tests/cts/tethering/Android.bp | 56 - tests/cts/tethering/AndroidManifest.xml | 33 - tests/cts/tethering/AndroidTest.xml | 35 - tests/cts/tethering/OWNERS | 4 - .../tethering/cts/TetheringManagerTest.java | 465 ------ 139 files changed, 24156 deletions(-) delete mode 100644 tests/cts/hostside/Android.bp delete mode 100644 tests/cts/hostside/AndroidTest.xml delete mode 100644 tests/cts/hostside/OWNERS delete mode 100644 tests/cts/hostside/aidl/Android.bp delete mode 100644 tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl delete mode 100644 tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkCallback.aidl delete mode 100644 tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl delete mode 100644 tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl delete mode 100644 tests/cts/hostside/app/Android.bp delete mode 100644 tests/cts/hostside/app/AndroidManifest.xml delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/AppIdleMeteredTest.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/AppIdleNonMeteredTest.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/BatterySaverModeMeteredTest.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/DozeModeMeteredTest.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/DozeModeNonMeteredTest.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/MeterednessConfigurationRule.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/MyActivity.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/MyNotificationListenerService.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/MyVpnService.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkCallbackTest.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestRunner.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/PacketReflector.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/Property.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/RequiredProperties.java delete mode 100644 tests/cts/hostside/app/src/com/android/cts/net/hostside/RequiredPropertiesRule.java delete mode 100755 tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java delete mode 100644 tests/cts/hostside/app2/Android.bp delete mode 100644 tests/cts/hostside/app2/AndroidManifest.xml delete mode 100644 tests/cts/hostside/app2/res/drawable/ic_notification.png delete mode 100644 tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java delete mode 100644 tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java delete mode 100644 tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java delete mode 100644 tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java delete mode 100644 tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java delete mode 100644 tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java delete mode 100644 tests/cts/hostside/certs/Android.bp delete mode 100644 tests/cts/hostside/certs/README delete mode 100644 tests/cts/hostside/certs/cts-net-app.pk8 delete mode 100644 tests/cts/hostside/certs/cts-net-app.x509.pem delete mode 100644 tests/cts/hostside/src/com/android/cts/net/HostsideNetworkCallbackTests.java delete mode 100644 tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java delete mode 100644 tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java delete mode 100644 tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java delete mode 100644 tests/cts/hostside/src/com/android/cts/net/NetworkPolicyTestsPreparer.java delete mode 100644 tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java delete mode 100644 tests/cts/net/Android.bp delete mode 100644 tests/cts/net/AndroidManifest.xml delete mode 100644 tests/cts/net/AndroidTestTemplate.xml delete mode 100644 tests/cts/net/OWNERS delete mode 100644 tests/cts/net/TEST_MAPPING delete mode 100644 tests/cts/net/api23Test/Android.bp delete mode 100644 tests/cts/net/api23Test/AndroidManifest.xml delete mode 100644 tests/cts/net/api23Test/AndroidTest.xml delete mode 100644 tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java delete mode 100644 tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityReceiver.java delete mode 100644 tests/cts/net/appForApi23/Android.bp delete mode 100644 tests/cts/net/appForApi23/AndroidManifest.xml delete mode 100644 tests/cts/net/appForApi23/src/android/net/cts/appForApi23/ConnectivityListeningActivity.java delete mode 100644 tests/cts/net/appForApi23/src/android/net/cts/appForApi23/ConnectivityReceiver.java delete mode 100644 tests/cts/net/assets/network_watchlist_config_empty_for_test.xml delete mode 100644 tests/cts/net/assets/network_watchlist_config_for_test.xml delete mode 100644 tests/cts/net/jarjar-rules-shared.txt delete mode 100644 tests/cts/net/jni/Android.bp delete mode 100644 tests/cts/net/jni/NativeDnsJni.c delete mode 100644 tests/cts/net/jni/NativeMultinetworkJni.cpp delete mode 100644 tests/cts/net/native/dns/Android.bp delete mode 100644 tests/cts/net/native/dns/AndroidTest.xml delete mode 100644 tests/cts/net/native/dns/NativeDnsAsyncTest.cpp delete mode 100644 tests/cts/net/native/qtaguid/Android.bp delete mode 100644 tests/cts/net/native/qtaguid/AndroidTest.xml delete mode 100644 tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp delete mode 100644 tests/cts/net/src/android/net/cts/AirplaneModeTest.java delete mode 100644 tests/cts/net/src/android/net/cts/CaptivePortalTest.kt delete mode 100644 tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java delete mode 100644 tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java delete mode 100644 tests/cts/net/src/android/net/cts/CredentialsTest.java delete mode 100644 tests/cts/net/src/android/net/cts/DnsResolverTest.java delete mode 100644 tests/cts/net/src/android/net/cts/DnsTest.java delete mode 100644 tests/cts/net/src/android/net/cts/IkeTunUtils.java delete mode 100644 tests/cts/net/src/android/net/cts/Ikev2VpnTest.java delete mode 100644 tests/cts/net/src/android/net/cts/InetAddressesTest.java delete mode 100644 tests/cts/net/src/android/net/cts/IpConfigurationTest.java delete mode 100644 tests/cts/net/src/android/net/cts/IpSecBaseTest.java delete mode 100644 tests/cts/net/src/android/net/cts/IpSecManagerTest.java delete mode 100644 tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java delete mode 100644 tests/cts/net/src/android/net/cts/LocalServerSocketTest.java delete mode 100644 tests/cts/net/src/android/net/cts/LocalSocketAddressTest.java delete mode 100644 tests/cts/net/src/android/net/cts/LocalSocketAddress_NamespaceTest.java delete mode 100644 tests/cts/net/src/android/net/cts/LocalSocketTest.java delete mode 100644 tests/cts/net/src/android/net/cts/MacAddressTest.java delete mode 100644 tests/cts/net/src/android/net/cts/MailToTest.java delete mode 100644 tests/cts/net/src/android/net/cts/MultinetworkApiTest.java delete mode 100644 tests/cts/net/src/android/net/cts/NetworkAgentTest.kt delete mode 100644 tests/cts/net/src/android/net/cts/NetworkInfoTest.kt delete mode 100644 tests/cts/net/src/android/net/cts/NetworkInfo_DetailedStateTest.java delete mode 100644 tests/cts/net/src/android/net/cts/NetworkInfo_StateTest.java delete mode 100644 tests/cts/net/src/android/net/cts/NetworkRequestTest.java delete mode 100644 tests/cts/net/src/android/net/cts/NetworkStackDependenciesTest.kt delete mode 100644 tests/cts/net/src/android/net/cts/NetworkStatsBinderTest.java delete mode 100644 tests/cts/net/src/android/net/cts/NetworkValidationTest.kt delete mode 100644 tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt delete mode 100644 tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java delete mode 100644 tests/cts/net/src/android/net/cts/PacketUtils.java delete mode 100644 tests/cts/net/src/android/net/cts/ProxyInfoTest.java delete mode 100644 tests/cts/net/src/android/net/cts/ProxyTest.java delete mode 100644 tests/cts/net/src/android/net/cts/RssiCurveTest.java delete mode 100644 tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java delete mode 100644 tests/cts/net/src/android/net/cts/TheaterModeTest.java delete mode 100755 tests/cts/net/src/android/net/cts/TrafficStatsTest.java delete mode 100644 tests/cts/net/src/android/net/cts/TunUtils.java delete mode 100644 tests/cts/net/src/android/net/cts/UriTest.java delete mode 100644 tests/cts/net/src/android/net/cts/Uri_BuilderTest.java delete mode 100644 tests/cts/net/src/android/net/cts/UrlQuerySanitizerTest.java delete mode 100644 tests/cts/net/src/android/net/cts/UrlQuerySanitizer_IllegalCharacterValueSanitizerTest.java delete mode 100644 tests/cts/net/src/android/net/cts/UrlQuerySanitizer_ParameterValuePairTest.java delete mode 100644 tests/cts/net/src/android/net/cts/VpnServiceTest.java delete mode 100644 tests/cts/net/src/android/net/ipv6/cts/PingTest.java delete mode 100644 tests/cts/net/src/android/net/rtp/cts/AudioCodecTest.java delete mode 100644 tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java delete mode 100644 tests/cts/net/src/android/net/rtp/cts/AudioStreamTest.java delete mode 100644 tests/cts/net/util/Android.bp delete mode 100644 tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java delete mode 100644 tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java delete mode 100644 tests/cts/tethering/Android.bp delete mode 100644 tests/cts/tethering/AndroidManifest.xml delete mode 100644 tests/cts/tethering/AndroidTest.xml delete mode 100644 tests/cts/tethering/OWNERS delete mode 100644 tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp deleted file mode 100644 index 741c961e5f..0000000000 --- a/tests/cts/hostside/Android.bp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2014 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. - -java_test_host { - name: "CtsHostsideNetworkTests", - defaults: ["cts_defaults"], - // Only compile source java files in this apk. - srcs: ["src/**/*.java"], - libs: [ - "cts-tradefed", - "tradefed", - ], - // Tag this module as a cts test artifact - test_suites: [ - "cts", - "vts10", - "general-tests", - ], -} diff --git a/tests/cts/hostside/AndroidTest.xml b/tests/cts/hostside/AndroidTest.xml deleted file mode 100644 index b7fefaf3b5..0000000000 --- a/tests/cts/hostside/AndroidTest.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - diff --git a/tests/cts/hostside/OWNERS b/tests/cts/hostside/OWNERS deleted file mode 100644 index 52c8053323..0000000000 --- a/tests/cts/hostside/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# Bug component: 61373 -sudheersai@google.com -lorenzo@google.com -jchalard@google.com diff --git a/tests/cts/hostside/aidl/Android.bp b/tests/cts/hostside/aidl/Android.bp deleted file mode 100644 index 320a1fa443..0000000000 --- a/tests/cts/hostside/aidl/Android.bp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_test_helper_library { - name: "CtsHostsideNetworkTestsAidl", - sdk_version: "current", - srcs: [ - "com/android/cts/net/hostside/IMyService.aidl", - "com/android/cts/net/hostside/INetworkCallback.aidl", - "com/android/cts/net/hostside/INetworkStateObserver.aidl", - "com/android/cts/net/hostside/IRemoteSocketFactory.aidl", - ], -} diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl deleted file mode 100644 index 5aafdf06cb..0000000000 --- a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IMyService.aidl +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import com.android.cts.net.hostside.INetworkCallback; - -interface IMyService { - void registerBroadcastReceiver(); - int getCounters(String receiverName, String action); - String checkNetworkStatus(); - String getRestrictBackgroundStatus(); - void sendNotification(int notificationId, String notificationType); - void registerNetworkCallback(in INetworkCallback cb); - void unregisterNetworkCallback(); -} diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkCallback.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkCallback.aidl deleted file mode 100644 index 2048bab498..0000000000 --- a/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkCallback.aidl +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import android.net.Network; -import android.net.NetworkCapabilities; - -interface INetworkCallback { - void onBlockedStatusChanged(in Network network, boolean blocked); - void onAvailable(in Network network); - void onLost(in Network network); - void onCapabilitiesChanged(in Network network, in NetworkCapabilities cap); -} diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl deleted file mode 100644 index 165f5306c3..0000000000 --- a/tests/cts/hostside/aidl/com/android/cts/net/hostside/INetworkStateObserver.aidl +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -interface INetworkStateObserver { - boolean isForeground(); - void onNetworkStateChecked(String resultData); -} \ No newline at end of file diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl deleted file mode 100644 index 68176ad80d..0000000000 --- a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import android.os.ParcelFileDescriptor; - -interface IRemoteSocketFactory { - ParcelFileDescriptor openSocketFd(String host, int port, int timeoutMs); - String getPackageName(); - int getUid(); -} diff --git a/tests/cts/hostside/app/Android.bp b/tests/cts/hostside/app/Android.bp deleted file mode 100644 index e129be7b7d..0000000000 --- a/tests/cts/hostside/app/Android.bp +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (C) 2014 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: "CtsHostsideNetworkTestsApp", - defaults: ["cts_support_defaults"], - //sdk_version: "current", - platform_apis: true, - static_libs: [ - "androidx.test.rules", - "androidx.test.ext.junit", - "compatibility-device-util-axt", - "ctstestrunner-axt", - "ub-uiautomator", - "CtsHostsideNetworkTestsAidl", - ], - libs: [ - "android.test.runner", - "android.test.base", - ], - srcs: ["src/**/*.java"], - // Tag this module as a cts test artifact - test_suites: [ - "cts", - "vts10", - "general-tests", - ], -} diff --git a/tests/cts/hostside/app/AndroidManifest.xml b/tests/cts/hostside/app/AndroidManifest.xml deleted file mode 100644 index 3940de4240..0000000000 --- a/tests/cts/hostside/app/AndroidManifest.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java deleted file mode 100644 index 219cc3da32..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.Property.APP_STANDBY_MODE; -import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE; - -import static org.junit.Assert.assertEquals; - -import android.os.SystemClock; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Base class for metered and non-metered tests on idle apps. - */ -@RequiredProperties({APP_STANDBY_MODE}) -abstract class AbstractAppIdleTestCase extends AbstractRestrictBackgroundNetworkTestCase { - - @Before - public final void setUp() throws Exception { - super.setUp(); - - // Set initial state. - removePowerSaveModeWhitelist(TEST_APP2_PKG); - removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - setAppIdle(false); - turnBatteryOn(); - - registerBroadcastReceiver(); - } - - @After - public final void tearDown() throws Exception { - super.tearDown(); - - executeSilentShellCommand("cmd battery reset"); - setAppIdle(false); - } - - @Test - public void testBackgroundNetworkAccess_enabled() throws Exception { - setAppIdle(true); - assertBackgroundNetworkAccess(false); - - assertsForegroundAlwaysHasNetworkAccess(); - setAppIdle(true); - assertBackgroundNetworkAccess(false); - - // Make sure foreground app doesn't lose access upon enabling it. - setAppIdle(true); - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY); - finishActivity(); - assertAppIdle(false); // Sanity check - not idle anymore, since activity was launched... - assertBackgroundNetworkAccess(true); - setAppIdle(true); - assertBackgroundNetworkAccess(false); - - // Same for foreground service. - setAppIdle(true); - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE); - stopForegroundService(); - assertAppIdle(true); - assertBackgroundNetworkAccess(false); - } - - @Test - public void testBackgroundNetworkAccess_whitelisted() throws Exception { - setAppIdle(true); - assertBackgroundNetworkAccess(false); - - addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertAppIdle(false); // Sanity check - not idle anymore, since whitelisted - assertBackgroundNetworkAccess(true); - - setAppIdleNoAssert(true); - assertAppIdle(false); // app is still whitelisted - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertAppIdle(true); // Sanity check - idle again, once whitelisted was removed - assertBackgroundNetworkAccess(false); - - setAppIdle(true); - addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertAppIdle(false); // Sanity check - not idle anymore, since whitelisted - assertBackgroundNetworkAccess(true); - - setAppIdleNoAssert(true); - assertAppIdle(false); // app is still whitelisted - removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertAppIdle(true); // Sanity check - idle again, once whitelisted was removed - assertBackgroundNetworkAccess(false); - - assertsForegroundAlwaysHasNetworkAccess(); - - // Sanity check - no whitelist, no access! - setAppIdle(true); - assertBackgroundNetworkAccess(false); - } - - @Test - public void testBackgroundNetworkAccess_tempWhitelisted() throws Exception { - setAppIdle(true); - assertBackgroundNetworkAccess(false); - - addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(true); - // Wait until the whitelist duration is expired. - SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(false); - } - - @Test - public void testBackgroundNetworkAccess_disabled() throws Exception { - assertBackgroundNetworkAccess(true); - - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(true); - } - - @RequiredProperties({BATTERY_SAVER_MODE}) - @Test - public void testAppIdleNetworkAccess_whenCharging() throws Exception { - // Check that app is paroled when charging - setAppIdle(true); - assertBackgroundNetworkAccess(false); - turnBatteryOff(); - assertBackgroundNetworkAccess(true); - turnBatteryOn(); - assertBackgroundNetworkAccess(false); - - // Check that app is restricted when not idle but power-save is on - setAppIdle(false); - assertBackgroundNetworkAccess(true); - setBatterySaverMode(true); - assertBackgroundNetworkAccess(false); - // Use setBatterySaverMode API to leave power-save mode instead of plugging in charger - setBatterySaverMode(false); - turnBatteryOff(); - assertBackgroundNetworkAccess(true); - - // And when no longer charging, it still has network access, since it's not idle - turnBatteryOn(); - assertBackgroundNetworkAccess(true); - } - - @Test - public void testAppIdleNetworkAccess_idleWhitelisted() throws Exception { - setAppIdle(true); - assertAppIdle(true); - assertBackgroundNetworkAccess(false); - - addAppIdleWhitelist(mUid); - assertBackgroundNetworkAccess(true); - - removeAppIdleWhitelist(mUid); - assertBackgroundNetworkAccess(false); - - // Make sure whitelisting a random app doesn't affect the tested app. - addAppIdleWhitelist(mUid + 1); - assertBackgroundNetworkAccess(false); - removeAppIdleWhitelist(mUid + 1); - } - - @Test - public void testAppIdle_toast() throws Exception { - setAppIdle(true); - assertAppIdle(true); - assertEquals("Shown", showToast()); - assertAppIdle(true); - // Wait for a couple of seconds for the toast to actually be shown - SystemClock.sleep(2000); - assertAppIdle(true); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java deleted file mode 100644 index 04d054d54a..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Base class for metered and non-metered Battery Saver Mode tests. - */ -@RequiredProperties({BATTERY_SAVER_MODE}) -abstract class AbstractBatterySaverModeTestCase extends AbstractRestrictBackgroundNetworkTestCase { - - @Before - public final void setUp() throws Exception { - super.setUp(); - - // Set initial state. - removePowerSaveModeWhitelist(TEST_APP2_PKG); - removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - setBatterySaverMode(false); - - registerBroadcastReceiver(); - } - - @After - public final void tearDown() throws Exception { - super.tearDown(); - - setBatterySaverMode(false); - } - - @Test - public void testBackgroundNetworkAccess_enabled() throws Exception { - setBatterySaverMode(true); - assertBackgroundNetworkAccess(false); - - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - - // Make sure foreground app doesn't lose access upon Battery Saver. - setBatterySaverMode(false); - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY); - setBatterySaverMode(true); - assertForegroundNetworkAccess(); - - // Although it should not have access while the screen is off. - turnScreenOff(); - assertBackgroundNetworkAccess(false); - turnScreenOn(); - assertForegroundNetworkAccess(); - - // Goes back to background state. - finishActivity(); - assertBackgroundNetworkAccess(false); - - // Make sure foreground service doesn't lose access upon enabling Battery Saver. - setBatterySaverMode(false); - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE); - setBatterySaverMode(true); - assertForegroundNetworkAccess(); - stopForegroundService(); - assertBackgroundNetworkAccess(false); - } - - @Test - public void testBackgroundNetworkAccess_whitelisted() throws Exception { - setBatterySaverMode(true); - assertBackgroundNetworkAccess(false); - - addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(true); - - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - - addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(true); - - removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - } - - @Test - public void testBackgroundNetworkAccess_disabled() throws Exception { - assertBackgroundNetworkAccess(true); - - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(true); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java deleted file mode 100644 index 6f32c563c1..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.Property.DOZE_MODE; -import static com.android.cts.net.hostside.Property.NOT_LOW_RAM_DEVICE; - -import android.os.SystemClock; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Base class for metered and non-metered Doze Mode tests. - */ -@RequiredProperties({DOZE_MODE}) -abstract class AbstractDozeModeTestCase extends AbstractRestrictBackgroundNetworkTestCase { - - @Before - public final void setUp() throws Exception { - super.setUp(); - - // Set initial state. - removePowerSaveModeWhitelist(TEST_APP2_PKG); - removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - setDozeMode(false); - - registerBroadcastReceiver(); - } - - @After - public final void tearDown() throws Exception { - super.tearDown(); - - setDozeMode(false); - } - - @Test - public void testBackgroundNetworkAccess_enabled() throws Exception { - setDozeMode(true); - assertBackgroundNetworkAccess(false); - - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - - // Make sure foreground service doesn't lose network access upon enabling doze. - setDozeMode(false); - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE); - setDozeMode(true); - assertForegroundNetworkAccess(); - stopForegroundService(); - assertBackgroundState(); - assertBackgroundNetworkAccess(false); - } - - @Test - public void testBackgroundNetworkAccess_whitelisted() throws Exception { - setDozeMode(true); - assertBackgroundNetworkAccess(false); - - addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(true); - - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - - addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - - removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - } - - @Test - public void testBackgroundNetworkAccess_disabled() throws Exception { - assertBackgroundNetworkAccess(true); - - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(true); - } - - @RequiredProperties({NOT_LOW_RAM_DEVICE}) - @Test - public void testBackgroundNetworkAccess_enabledButWhitelistedOnNotificationAction() - throws Exception { - setPendingIntentWhitelistDuration(NETWORK_TIMEOUT_MS); - try { - registerNotificationListenerService(); - setDozeMode(true); - assertBackgroundNetworkAccess(false); - - testNotification(4, NOTIFICATION_TYPE_CONTENT); - testNotification(8, NOTIFICATION_TYPE_DELETE); - testNotification(15, NOTIFICATION_TYPE_FULL_SCREEN); - testNotification(16, NOTIFICATION_TYPE_BUNDLE); - testNotification(23, NOTIFICATION_TYPE_ACTION); - testNotification(42, NOTIFICATION_TYPE_ACTION_BUNDLE); - testNotification(108, NOTIFICATION_TYPE_ACTION_REMOTE_INPUT); - } finally { - resetDeviceIdleSettings(); - } - } - - private void testNotification(int id, String type) throws Exception { - sendNotification(id, type); - assertBackgroundNetworkAccess(true); - if (type.equals(NOTIFICATION_TYPE_ACTION)) { - // Make sure access is disabled after it expires. Since this check considerably slows - // downs the CTS tests, do it just once. - SystemClock.sleep(NETWORK_TIMEOUT_MS); - assertBackgroundNetworkAccess(false); - } - } - - // Must override so it only tests foreground service - once an app goes to foreground, device - // leaves Doze Mode. - @Override - protected void assertsForegroundAlwaysHasNetworkAccess() throws Exception { - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE); - stopForegroundService(); - assertBackgroundState(); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java deleted file mode 100644 index e5fd149aec..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java +++ /dev/null @@ -1,881 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED; -import static android.os.BatteryManager.BATTERY_PLUGGED_AC; -import static android.os.BatteryManager.BATTERY_PLUGGED_USB; -import static android.os.BatteryManager.BATTERY_PLUGGED_WIRELESS; - -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.executeShellCommand; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getConnectivityManager; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getContext; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getInstrumentation; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.getWifiManager; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isDozeModeSupported; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.restrictBackgroundValueToString; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.app.ActivityManager; -import android.app.Instrumentation; -import android.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.NetworkInfo.DetailedState; -import android.net.NetworkInfo.State; -import android.net.wifi.WifiManager; -import android.os.BatteryManager; -import android.os.Binder; -import android.os.Bundle; -import android.os.SystemClock; -import android.provider.Settings; -import android.service.notification.NotificationListenerService; -import android.util.Log; - -import org.junit.Rule; -import org.junit.rules.RuleChain; -import org.junit.runner.RunWith; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -/** - * Superclass for tests related to background network restrictions. - */ -@RunWith(NetworkPolicyTestRunner.class) -public abstract class AbstractRestrictBackgroundNetworkTestCase { - public static final String TAG = "RestrictBackgroundNetworkTests"; - - protected static final String TEST_PKG = "com.android.cts.net.hostside"; - protected static final String TEST_APP2_PKG = "com.android.cts.net.hostside.app2"; - - private static final String TEST_APP2_ACTIVITY_CLASS = TEST_APP2_PKG + ".MyActivity"; - private static final String TEST_APP2_SERVICE_CLASS = TEST_APP2_PKG + ".MyForegroundService"; - - private static final int SLEEP_TIME_SEC = 1; - - // Constants below must match values defined on app2's Common.java - private static final String MANIFEST_RECEIVER = "ManifestReceiver"; - private static final String DYNAMIC_RECEIVER = "DynamicReceiver"; - - private static final String ACTION_RECEIVER_READY = - "com.android.cts.net.hostside.app2.action.RECEIVER_READY"; - static final String ACTION_SHOW_TOAST = - "com.android.cts.net.hostside.app2.action.SHOW_TOAST"; - - protected static final String NOTIFICATION_TYPE_CONTENT = "CONTENT"; - protected static final String NOTIFICATION_TYPE_DELETE = "DELETE"; - protected static final String NOTIFICATION_TYPE_FULL_SCREEN = "FULL_SCREEN"; - protected static final String NOTIFICATION_TYPE_BUNDLE = "BUNDLE"; - protected static final String NOTIFICATION_TYPE_ACTION = "ACTION"; - protected static final String NOTIFICATION_TYPE_ACTION_BUNDLE = "ACTION_BUNDLE"; - protected static final String NOTIFICATION_TYPE_ACTION_REMOTE_INPUT = "ACTION_REMOTE_INPUT"; - - // TODO: Update BatteryManager.BATTERY_PLUGGED_ANY as @TestApi - public static final int BATTERY_PLUGGED_ANY = - BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS; - - private static final String NETWORK_STATUS_SEPARATOR = "\\|"; - private static final int SECOND_IN_MS = 1000; - static final int NETWORK_TIMEOUT_MS = 15 * SECOND_IN_MS; - private static int PROCESS_STATE_FOREGROUND_SERVICE; - - private static final String KEY_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer"; - - protected static final int TYPE_COMPONENT_ACTIVTIY = 0; - protected static final int TYPE_COMPONENT_FOREGROUND_SERVICE = 1; - - private static final int BATTERY_STATE_TIMEOUT_MS = 5000; - private static final int BATTERY_STATE_CHECK_INTERVAL_MS = 500; - - private static final int FOREGROUND_PROC_NETWORK_TIMEOUT_MS = 6000; - - // Must be higher than NETWORK_TIMEOUT_MS - private static final int ORDERED_BROADCAST_TIMEOUT_MS = NETWORK_TIMEOUT_MS * 4; - - private static final IntentFilter BATTERY_CHANGED_FILTER = - new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - - private static final String APP_NOT_FOREGROUND_ERROR = "app_not_fg"; - - protected static final long TEMP_POWERSAVE_WHITELIST_DURATION_MS = 5_000; // 5 sec - - protected Context mContext; - protected Instrumentation mInstrumentation; - protected ConnectivityManager mCm; - protected int mUid; - private int mMyUid; - private MyServiceClient mServiceClient; - private String mDeviceIdleConstantsSetting; - - @Rule - public final RuleChain mRuleChain = RuleChain.outerRule(new RequiredPropertiesRule()) - .around(new MeterednessConfigurationRule()); - - protected void setUp() throws Exception { - - PROCESS_STATE_FOREGROUND_SERVICE = (Integer) ActivityManager.class - .getDeclaredField("PROCESS_STATE_FOREGROUND_SERVICE").get(null); - mInstrumentation = getInstrumentation(); - mContext = getContext(); - mCm = getConnectivityManager(); - mUid = getUid(TEST_APP2_PKG); - mMyUid = getUid(mContext.getPackageName()); - mServiceClient = new MyServiceClient(mContext); - mServiceClient.bind(); - mDeviceIdleConstantsSetting = "device_idle_constants"; - executeShellCommand("cmd netpolicy start-watching " + mUid); - setAppIdle(false); - - Log.i(TAG, "Apps status:\n" - + "\ttest app: uid=" + mMyUid + ", state=" + getProcessStateByUid(mMyUid) + "\n" - + "\tapp2: uid=" + mUid + ", state=" + getProcessStateByUid(mUid)); - } - - protected void tearDown() throws Exception { - executeShellCommand("cmd netpolicy stop-watching"); - mServiceClient.unbind(); - } - - protected int getUid(String packageName) throws Exception { - return mContext.getPackageManager().getPackageUid(packageName, 0); - } - - protected void assertRestrictBackgroundChangedReceived(int expectedCount) throws Exception { - assertRestrictBackgroundChangedReceived(DYNAMIC_RECEIVER, expectedCount); - assertRestrictBackgroundChangedReceived(MANIFEST_RECEIVER, 0); - } - - protected void assertRestrictBackgroundChangedReceived(String receiverName, int expectedCount) - throws Exception { - int attempts = 0; - int count = 0; - final int maxAttempts = 5; - do { - attempts++; - count = getNumberBroadcastsReceived(receiverName, ACTION_RESTRICT_BACKGROUND_CHANGED); - assertFalse("Expected count " + expectedCount + " but actual is " + count, - count > expectedCount); - if (count == expectedCount) { - break; - } - Log.d(TAG, "Expecting count " + expectedCount + " but actual is " + count + " after " - + attempts + " attempts; sleeping " - + SLEEP_TIME_SEC + " seconds before trying again"); - SystemClock.sleep(SLEEP_TIME_SEC * SECOND_IN_MS); - } while (attempts <= maxAttempts); - assertEquals("Number of expected broadcasts for " + receiverName + " not reached after " - + maxAttempts * SLEEP_TIME_SEC + " seconds", expectedCount, count); - } - - protected String sendOrderedBroadcast(Intent intent) throws Exception { - return sendOrderedBroadcast(intent, ORDERED_BROADCAST_TIMEOUT_MS); - } - - protected String sendOrderedBroadcast(Intent intent, int timeoutMs) throws Exception { - final LinkedBlockingQueue result = new LinkedBlockingQueue<>(1); - Log.d(TAG, "Sending ordered broadcast: " + intent); - mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { - - @Override - public void onReceive(Context context, Intent intent) { - final String resultData = getResultData(); - if (resultData == null) { - Log.e(TAG, "Received null data from ordered intent"); - return; - } - result.offer(resultData); - } - }, null, 0, null, null); - - final String resultData = result.poll(timeoutMs, TimeUnit.MILLISECONDS); - Log.d(TAG, "Ordered broadcast response after " + timeoutMs + "ms: " + resultData ); - return resultData; - } - - protected int getNumberBroadcastsReceived(String receiverName, String action) throws Exception { - return mServiceClient.getCounters(receiverName, action); - } - - protected void assertRestrictBackgroundStatus(int expectedStatus) throws Exception { - final String status = mServiceClient.getRestrictBackgroundStatus(); - assertNotNull("didn't get API status from app2", status); - assertEquals(restrictBackgroundValueToString(expectedStatus), - restrictBackgroundValueToString(Integer.parseInt(status))); - } - - protected void assertBackgroundNetworkAccess(boolean expectAllowed) throws Exception { - assertBackgroundState(); // Sanity check. - assertNetworkAccess(expectAllowed /* expectAvailable */, false /* needScreenOn */); - } - - protected void assertForegroundNetworkAccess() throws Exception { - assertForegroundState(); // Sanity check. - // We verified that app is in foreground state but if the screen turns-off while - // verifying for network access, the app will go into background state (in case app's - // foreground status was due to top activity). So, turn the screen on when verifying - // network connectivity. - assertNetworkAccess(true /* expectAvailable */, true /* needScreenOn */); - } - - protected void assertForegroundServiceNetworkAccess() throws Exception { - assertForegroundServiceState(); // Sanity check. - assertNetworkAccess(true /* expectAvailable */, false /* needScreenOn */); - } - - /** - * Asserts that an app always have access while on foreground or running a foreground service. - * - *

This method will launch an activity and a foreground service to make the assertion, but - * will finish the activity / stop the service afterwards. - */ - protected void assertsForegroundAlwaysHasNetworkAccess() throws Exception{ - // Checks foreground first. - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY); - finishActivity(); - - // Then foreground service - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE); - stopForegroundService(); - } - - protected final void assertBackgroundState() throws Exception { - final int maxTries = 30; - ProcessState state = null; - for (int i = 1; i <= maxTries; i++) { - state = getProcessStateByUid(mUid); - Log.v(TAG, "assertBackgroundState(): status for app2 (" + mUid + ") on attempt #" + i - + ": " + state); - if (isBackground(state.state)) { - return; - } - Log.d(TAG, "App not on background state (" + state + ") on attempt #" + i - + "; sleeping 1s before trying again"); - SystemClock.sleep(SECOND_IN_MS); - } - fail("App2 is not on background state after " + maxTries + " attempts: " + state ); - } - - protected final void assertForegroundState() throws Exception { - final int maxTries = 30; - ProcessState state = null; - for (int i = 1; i <= maxTries; i++) { - state = getProcessStateByUid(mUid); - Log.v(TAG, "assertForegroundState(): status for app2 (" + mUid + ") on attempt #" + i - + ": " + state); - if (!isBackground(state.state)) { - return; - } - Log.d(TAG, "App not on foreground state on attempt #" + i - + "; sleeping 1s before trying again"); - turnScreenOn(); - SystemClock.sleep(SECOND_IN_MS); - } - fail("App2 is not on foreground state after " + maxTries + " attempts: " + state ); - } - - protected final void assertForegroundServiceState() throws Exception { - final int maxTries = 30; - ProcessState state = null; - for (int i = 1; i <= maxTries; i++) { - state = getProcessStateByUid(mUid); - Log.v(TAG, "assertForegroundServiceState(): status for app2 (" + mUid + ") on attempt #" - + i + ": " + state); - if (state.state == PROCESS_STATE_FOREGROUND_SERVICE) { - return; - } - Log.d(TAG, "App not on foreground service state on attempt #" + i - + "; sleeping 1s before trying again"); - SystemClock.sleep(SECOND_IN_MS); - } - fail("App2 is not on foreground service state after " + maxTries + " attempts: " + state ); - } - - /** - * Returns whether an app state should be considered "background" for restriction purposes. - */ - protected boolean isBackground(int state) { - return state > PROCESS_STATE_FOREGROUND_SERVICE; - } - - /** - * Asserts whether the active network is available or not. - */ - private void assertNetworkAccess(boolean expectAvailable, boolean needScreenOn) - throws Exception { - final int maxTries = 5; - String error = null; - int timeoutMs = 500; - - for (int i = 1; i <= maxTries; i++) { - error = checkNetworkAccess(expectAvailable); - - if (error.isEmpty()) return; - - // TODO: ideally, it should retry only when it cannot connect to an external site, - // or no retry at all! But, currently, the initial change fails almost always on - // battery saver tests because the netd changes are made asynchronously. - // Once b/27803922 is fixed, this retry mechanism should be revisited. - - Log.w(TAG, "Network status didn't match for expectAvailable=" + expectAvailable - + " on attempt #" + i + ": " + error + "\n" - + "Sleeping " + timeoutMs + "ms before trying again"); - if (needScreenOn) { - turnScreenOn(); - } - // No sleep after the last turn - if (i < maxTries) { - SystemClock.sleep(timeoutMs); - } - // Exponential back-off. - timeoutMs = Math.min(timeoutMs*2, NETWORK_TIMEOUT_MS); - } - fail("Invalid state for expectAvailable=" + expectAvailable + " after " + maxTries - + " attempts.\nLast error: " + error); - } - - /** - * Checks whether the network is available as expected. - * - * @return error message with the mismatch (or empty if assertion passed). - */ - private String checkNetworkAccess(boolean expectAvailable) throws Exception { - final String resultData = mServiceClient.checkNetworkStatus(); - return checkForAvailabilityInResultData(resultData, expectAvailable); - } - - private String checkForAvailabilityInResultData(String resultData, boolean expectAvailable) { - if (resultData == null) { - assertNotNull("Network status from app2 is null", resultData); - } - // Network status format is described on MyBroadcastReceiver.checkNetworkStatus() - final String[] parts = resultData.split(NETWORK_STATUS_SEPARATOR); - assertEquals("Wrong network status: " + resultData, 5, parts.length); // Sanity check - final State state = parts[0].equals("null") ? null : State.valueOf(parts[0]); - final DetailedState detailedState = parts[1].equals("null") - ? null : DetailedState.valueOf(parts[1]); - final boolean connected = Boolean.valueOf(parts[2]); - final String connectionCheckDetails = parts[3]; - final String networkInfo = parts[4]; - - final StringBuilder errors = new StringBuilder(); - final State expectedState; - final DetailedState expectedDetailedState; - if (expectAvailable) { - expectedState = State.CONNECTED; - expectedDetailedState = DetailedState.CONNECTED; - } else { - expectedState = State.DISCONNECTED; - expectedDetailedState = DetailedState.BLOCKED; - } - - if (expectAvailable != connected) { - errors.append(String.format("External site connection failed: expected %s, got %s\n", - expectAvailable, connected)); - } - if (expectedState != state || expectedDetailedState != detailedState) { - errors.append(String.format("Connection state mismatch: expected %s/%s, got %s/%s\n", - expectedState, expectedDetailedState, state, detailedState)); - } - - if (errors.length() > 0) { - errors.append("\tnetworkInfo: " + networkInfo + "\n"); - errors.append("\tconnectionCheckDetails: " + connectionCheckDetails + "\n"); - } - return errors.toString(); - } - - /** - * Runs a Shell command which is not expected to generate output. - */ - protected void executeSilentShellCommand(String command) { - final String result = executeShellCommand(command); - assertTrue("Command '" + command + "' failed: " + result, result.trim().isEmpty()); - } - - /** - * Asserts the result of a command, wait and re-running it a couple times if necessary. - */ - protected void assertDelayedShellCommand(String command, final String expectedResult) - throws Exception { - assertDelayedShellCommand(command, 5, 1, expectedResult); - } - - protected void assertDelayedShellCommand(String command, int maxTries, int napTimeSeconds, - final String expectedResult) throws Exception { - assertDelayedShellCommand(command, maxTries, napTimeSeconds, new ExpectResultChecker() { - - @Override - public boolean isExpected(String result) { - return expectedResult.equals(result); - } - - @Override - public String getExpected() { - return expectedResult; - } - }); - } - - protected void assertDelayedShellCommand(String command, int maxTries, int napTimeSeconds, - ExpectResultChecker checker) throws Exception { - String result = ""; - for (int i = 1; i <= maxTries; i++) { - result = executeShellCommand(command).trim(); - if (checker.isExpected(result)) return; - Log.v(TAG, "Command '" + command + "' returned '" + result + " instead of '" - + checker.getExpected() + "' on attempt #" + i - + "; sleeping " + napTimeSeconds + "s before trying again"); - SystemClock.sleep(napTimeSeconds * SECOND_IN_MS); - } - fail("Command '" + command + "' did not return '" + checker.getExpected() + "' after " - + maxTries - + " attempts. Last result: '" + result + "'"); - } - - protected void addRestrictBackgroundWhitelist(int uid) throws Exception { - executeShellCommand("cmd netpolicy add restrict-background-whitelist " + uid); - assertRestrictBackgroundWhitelist(uid, true); - // UID policies live by the Highlander rule: "There can be only one". - // Hence, if app is whitelisted, it should not be blacklisted. - assertRestrictBackgroundBlacklist(uid, false); - } - - protected void removeRestrictBackgroundWhitelist(int uid) throws Exception { - executeShellCommand("cmd netpolicy remove restrict-background-whitelist " + uid); - assertRestrictBackgroundWhitelist(uid, false); - } - - protected void assertRestrictBackgroundWhitelist(int uid, boolean expected) throws Exception { - assertRestrictBackground("restrict-background-whitelist", uid, expected); - } - - protected void addRestrictBackgroundBlacklist(int uid) throws Exception { - executeShellCommand("cmd netpolicy add restrict-background-blacklist " + uid); - assertRestrictBackgroundBlacklist(uid, true); - // UID policies live by the Highlander rule: "There can be only one". - // Hence, if app is blacklisted, it should not be whitelisted. - assertRestrictBackgroundWhitelist(uid, false); - } - - protected void removeRestrictBackgroundBlacklist(int uid) throws Exception { - executeShellCommand("cmd netpolicy remove restrict-background-blacklist " + uid); - assertRestrictBackgroundBlacklist(uid, false); - } - - protected void assertRestrictBackgroundBlacklist(int uid, boolean expected) throws Exception { - assertRestrictBackground("restrict-background-blacklist", uid, expected); - } - - protected void addAppIdleWhitelist(int uid) throws Exception { - executeShellCommand("cmd netpolicy add app-idle-whitelist " + uid); - assertAppIdleWhitelist(uid, true); - } - - protected void removeAppIdleWhitelist(int uid) throws Exception { - executeShellCommand("cmd netpolicy remove app-idle-whitelist " + uid); - assertAppIdleWhitelist(uid, false); - } - - protected void assertAppIdleWhitelist(int uid, boolean expected) throws Exception { - assertRestrictBackground("app-idle-whitelist", uid, expected); - } - - private void assertRestrictBackground(String list, int uid, boolean expected) throws Exception { - final int maxTries = 5; - boolean actual = false; - final String expectedUid = Integer.toString(uid); - String uids = ""; - for (int i = 1; i <= maxTries; i++) { - final String output = - executeShellCommand("cmd netpolicy list " + list); - uids = output.split(":")[1]; - for (String candidate : uids.split(" ")) { - actual = candidate.trim().equals(expectedUid); - if (expected == actual) { - return; - } - } - Log.v(TAG, list + " check for uid " + uid + " doesn't match yet (expected " - + expected + ", got " + actual + "); sleeping 1s before polling again"); - SystemClock.sleep(SECOND_IN_MS); - } - fail(list + " check for uid " + uid + " failed: expected " + expected + ", got " + actual - + ". Full list: " + uids); - } - - protected void addTempPowerSaveModeWhitelist(String packageName, long duration) - throws Exception { - Log.i(TAG, "Adding pkg " + packageName + " to temp-power-save-mode whitelist"); - executeShellCommand("dumpsys deviceidle tempwhitelist -d " + duration + " " + packageName); - } - - protected void assertPowerSaveModeWhitelist(String packageName, boolean expected) - throws Exception { - // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll - // need to use netpolicy for whitelisting - assertDelayedShellCommand("dumpsys deviceidle whitelist =" + packageName, - Boolean.toString(expected)); - } - - protected void addPowerSaveModeWhitelist(String packageName) throws Exception { - Log.i(TAG, "Adding package " + packageName + " to power-save-mode whitelist"); - // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll - // need to use netpolicy for whitelisting - executeShellCommand("dumpsys deviceidle whitelist +" + packageName); - assertPowerSaveModeWhitelist(packageName, true); // Sanity check - } - - protected void removePowerSaveModeWhitelist(String packageName) throws Exception { - Log.i(TAG, "Removing package " + packageName + " from power-save-mode whitelist"); - // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll - // need to use netpolicy for whitelisting - executeShellCommand("dumpsys deviceidle whitelist -" + packageName); - assertPowerSaveModeWhitelist(packageName, false); // Sanity check - } - - protected void assertPowerSaveModeExceptIdleWhitelist(String packageName, boolean expected) - throws Exception { - // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll - // need to use netpolicy for whitelisting - assertDelayedShellCommand("dumpsys deviceidle except-idle-whitelist =" + packageName, - Boolean.toString(expected)); - } - - protected void addPowerSaveModeExceptIdleWhitelist(String packageName) throws Exception { - Log.i(TAG, "Adding package " + packageName + " to power-save-mode-except-idle whitelist"); - // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll - // need to use netpolicy for whitelisting - executeShellCommand("dumpsys deviceidle except-idle-whitelist +" + packageName); - assertPowerSaveModeExceptIdleWhitelist(packageName, true); // Sanity check - } - - protected void removePowerSaveModeExceptIdleWhitelist(String packageName) throws Exception { - Log.i(TAG, "Removing package " + packageName - + " from power-save-mode-except-idle whitelist"); - // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll - // need to use netpolicy for whitelisting - executeShellCommand("dumpsys deviceidle except-idle-whitelist reset"); - assertPowerSaveModeExceptIdleWhitelist(packageName, false); // Sanity check - } - - protected void turnBatteryOn() throws Exception { - executeSilentShellCommand("cmd battery unplug"); - executeSilentShellCommand("cmd battery set status " - + BatteryManager.BATTERY_STATUS_DISCHARGING); - assertBatteryState(false); - } - - protected void turnBatteryOff() throws Exception { - executeSilentShellCommand("cmd battery set ac " + BATTERY_PLUGGED_ANY); - executeSilentShellCommand("cmd battery set level 100"); - executeSilentShellCommand("cmd battery set status " - + BatteryManager.BATTERY_STATUS_CHARGING); - assertBatteryState(true); - } - - private void assertBatteryState(boolean pluggedIn) throws Exception { - final long endTime = SystemClock.elapsedRealtime() + BATTERY_STATE_TIMEOUT_MS; - while (isDevicePluggedIn() != pluggedIn && SystemClock.elapsedRealtime() <= endTime) { - Thread.sleep(BATTERY_STATE_CHECK_INTERVAL_MS); - } - if (isDevicePluggedIn() != pluggedIn) { - fail("Timed out waiting for the plugged-in state to change," - + " expected pluggedIn: " + pluggedIn); - } - } - - private boolean isDevicePluggedIn() { - final Intent batteryIntent = mContext.registerReceiver(null, BATTERY_CHANGED_FILTER); - return batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) > 0; - } - - protected void turnScreenOff() throws Exception { - executeSilentShellCommand("input keyevent KEYCODE_SLEEP"); - } - - protected void turnScreenOn() throws Exception { - executeSilentShellCommand("input keyevent KEYCODE_WAKEUP"); - executeSilentShellCommand("wm dismiss-keyguard"); - } - - protected void setBatterySaverMode(boolean enabled) throws Exception { - Log.i(TAG, "Setting Battery Saver Mode to " + enabled); - if (enabled) { - turnBatteryOn(); - executeSilentShellCommand("cmd power set-mode 1"); - } else { - executeSilentShellCommand("cmd power set-mode 0"); - turnBatteryOff(); - } - } - - protected void setDozeMode(boolean enabled) throws Exception { - // Sanity check, since tests should check beforehand.... - assertTrue("Device does not support Doze Mode", isDozeModeSupported()); - - Log.i(TAG, "Setting Doze Mode to " + enabled); - if (enabled) { - turnBatteryOn(); - turnScreenOff(); - executeShellCommand("dumpsys deviceidle force-idle deep"); - } else { - turnScreenOn(); - turnBatteryOff(); - executeShellCommand("dumpsys deviceidle unforce"); - } - // Sanity check. - assertDozeMode(enabled); - } - - protected void assertDozeMode(boolean enabled) throws Exception { - assertDelayedShellCommand("dumpsys deviceidle get deep", enabled ? "IDLE" : "ACTIVE"); - } - - protected void setAppIdle(boolean enabled) throws Exception { - Log.i(TAG, "Setting app idle to " + enabled); - executeSilentShellCommand("am set-inactive " + TEST_APP2_PKG + " " + enabled ); - assertAppIdle(enabled); // Sanity check - } - - protected void setAppIdleNoAssert(boolean enabled) throws Exception { - Log.i(TAG, "Setting app idle to " + enabled); - executeSilentShellCommand("am set-inactive " + TEST_APP2_PKG + " " + enabled ); - } - - protected void assertAppIdle(boolean enabled) throws Exception { - try { - assertDelayedShellCommand("am get-inactive " + TEST_APP2_PKG, 15, 2, "Idle=" + enabled); - } catch (Throwable e) { - throw e; - } - } - - /** - * Starts a service that will register a broadcast receiver to receive - * {@code RESTRICT_BACKGROUND_CHANGE} intents. - *

- * The service must run in a separate app because otherwise it would be killed every time - * {@link #runDeviceTests(String, String)} is executed. - */ - protected void registerBroadcastReceiver() throws Exception { - mServiceClient.registerBroadcastReceiver(); - - final Intent intent = new Intent(ACTION_RECEIVER_READY) - .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); - // Wait until receiver is ready. - final int maxTries = 10; - for (int i = 1; i <= maxTries; i++) { - final String message = sendOrderedBroadcast(intent, SECOND_IN_MS * 4); - Log.d(TAG, "app2 receiver acked: " + message); - if (message != null) { - return; - } - Log.v(TAG, "app2 receiver is not ready yet; sleeping 1s before polling again"); - SystemClock.sleep(SECOND_IN_MS); - } - fail("app2 receiver is not ready"); - } - - protected void registerNetworkCallback(INetworkCallback cb) throws Exception { - mServiceClient.registerNetworkCallback(cb); - } - - protected void unregisterNetworkCallback() throws Exception { - mServiceClient.unregisterNetworkCallback(); - } - - /** - * Registers a {@link NotificationListenerService} implementation that will execute the - * notification actions right after the notification is sent. - */ - protected void registerNotificationListenerService() throws Exception { - executeShellCommand("cmd notification allow_listener " - + MyNotificationListenerService.getId()); - final NotificationManager nm = mContext.getSystemService(NotificationManager.class); - final ComponentName listenerComponent = MyNotificationListenerService.getComponentName(); - assertTrue(listenerComponent + " has not been granted access", - nm.isNotificationListenerAccessGranted(listenerComponent)); - } - - protected void setPendingIntentWhitelistDuration(int durationMs) throws Exception { - executeSilentShellCommand(String.format( - "settings put global %s %s=%d", mDeviceIdleConstantsSetting, - "notification_whitelist_duration", durationMs)); - } - - protected void resetDeviceIdleSettings() throws Exception { - executeShellCommand(String.format("settings delete global %s", - mDeviceIdleConstantsSetting)); - } - - protected void launchComponentAndAssertNetworkAccess(int type) throws Exception { - if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) { - startForegroundService(); - assertForegroundServiceNetworkAccess(); - return; - } else if (type == TYPE_COMPONENT_ACTIVTIY) { - turnScreenOn(); - // Wait for screen-on state to propagate through the system. - SystemClock.sleep(2000); - final CountDownLatch latch = new CountDownLatch(1); - final Intent launchIntent = getIntentForComponent(type); - final Bundle extras = new Bundle(); - final String[] errors = new String[]{null}; - extras.putBinder(KEY_NETWORK_STATE_OBSERVER, getNewNetworkStateObserver(latch, errors)); - launchIntent.putExtras(extras); - mContext.startActivity(launchIntent); - if (latch.await(FOREGROUND_PROC_NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { - if (!errors[0].isEmpty()) { - if (errors[0] == APP_NOT_FOREGROUND_ERROR) { - // App didn't come to foreground when the activity is started, so try again. - assertForegroundNetworkAccess(); - } else { - fail("Network is not available for app2 (" + mUid + "): " + errors[0]); - } - } - } else { - fail("Timed out waiting for network availability status from app2 (" + mUid + ")"); - } - } else { - throw new IllegalArgumentException("Unknown type: " + type); - } - } - - private void startForegroundService() throws Exception { - final Intent launchIntent = getIntentForComponent(TYPE_COMPONENT_FOREGROUND_SERVICE); - mContext.startForegroundService(launchIntent); - assertForegroundServiceState(); - } - - private Intent getIntentForComponent(int type) { - final Intent intent = new Intent(); - if (type == TYPE_COMPONENT_ACTIVTIY) { - intent.setComponent(new ComponentName(TEST_APP2_PKG, TEST_APP2_ACTIVITY_CLASS)) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } else if (type == TYPE_COMPONENT_FOREGROUND_SERVICE) { - intent.setComponent(new ComponentName(TEST_APP2_PKG, TEST_APP2_SERVICE_CLASS)) - .setFlags(1); - } else { - fail("Unknown type: " + type); - } - return intent; - } - - protected void stopForegroundService() throws Exception { - executeShellCommand(String.format("am startservice -f 2 %s/%s", - TEST_APP2_PKG, TEST_APP2_SERVICE_CLASS)); - // NOTE: cannot assert state because it depends on whether activity was on top before. - } - - private Binder getNewNetworkStateObserver(final CountDownLatch latch, - final String[] errors) { - return new INetworkStateObserver.Stub() { - @Override - public boolean isForeground() { - try { - final ProcessState state = getProcessStateByUid(mUid); - return !isBackground(state.state); - } catch (Exception e) { - Log.d(TAG, "Error while reading the proc state for " + mUid + ": " + e); - return false; - } - } - - @Override - public void onNetworkStateChecked(String resultData) { - errors[0] = resultData == null - ? APP_NOT_FOREGROUND_ERROR - : checkForAvailabilityInResultData(resultData, true); - latch.countDown(); - } - }; - } - - /** - * Finishes an activity on app2 so its process is demoted fromforeground status. - */ - protected void finishActivity() throws Exception { - executeShellCommand("am broadcast -a " - + " com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY " - + "--receiver-foreground --receiver-registered-only"); - } - - protected void sendNotification(int notificationId, String notificationType) throws Exception { - Log.d(TAG, "Sending notification broadcast (id=" + notificationId - + ", type=" + notificationType); - mServiceClient.sendNotification(notificationId, notificationType); - } - - protected String showToast() { - final Intent intent = new Intent(ACTION_SHOW_TOAST); - intent.setPackage(TEST_APP2_PKG); - Log.d(TAG, "Sending request to show toast"); - try { - return sendOrderedBroadcast(intent, 3 * SECOND_IN_MS); - } catch (Exception e) { - return ""; - } - } - - private ProcessState getProcessStateByUid(int uid) throws Exception { - return new ProcessState(executeShellCommand("cmd activity get-uid-state " + uid)); - } - - private static class ProcessState { - private final String fullState; - final int state; - - ProcessState(String fullState) { - this.fullState = fullState; - try { - this.state = Integer.parseInt(fullState.split(" ")[0]); - } catch (Exception e) { - throw new IllegalArgumentException("Could not parse " + fullState); - } - } - - @Override - public String toString() { - return fullState; - } - } - - /** - * Helper class used to assert the result of a Shell command. - */ - protected static interface ExpectResultChecker { - /** - * Checkes whether the result of the command matched the expectation. - */ - boolean isExpected(String result); - /** - * Gets the expected result so it's displayed on log and failure messages. - */ - String getExpected(); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AppIdleMeteredTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AppIdleMeteredTest.java deleted file mode 100644 index f1858d65a5..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AppIdleMeteredTest.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.Property.METERED_NETWORK; - -@RequiredProperties({METERED_NETWORK}) -public class AppIdleMeteredTest extends AbstractAppIdleTestCase { -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AppIdleNonMeteredTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AppIdleNonMeteredTest.java deleted file mode 100644 index e737a6dabe..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AppIdleNonMeteredTest.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK; - -@RequiredProperties({NON_METERED_NETWORK}) -public class AppIdleNonMeteredTest extends AbstractAppIdleTestCase { -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/BatterySaverModeMeteredTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/BatterySaverModeMeteredTest.java deleted file mode 100644 index c78ca2ec77..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/BatterySaverModeMeteredTest.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.Property.METERED_NETWORK; - -@RequiredProperties({METERED_NETWORK}) -public class BatterySaverModeMeteredTest extends AbstractBatterySaverModeTestCase { -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java deleted file mode 100644 index fb52a540d8..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - - -import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK; - -@RequiredProperties({NON_METERED_NETWORK}) -public class BatterySaverModeNonMeteredTest extends AbstractBatterySaverModeTestCase { -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java deleted file mode 100644 index aa2c914e02..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataSaverModeTest.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED; -import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED; -import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED; - -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground; -import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE; -import static com.android.cts.net.hostside.Property.METERED_NETWORK; -import static com.android.cts.net.hostside.Property.NO_DATA_SAVER_MODE; - -import static org.junit.Assert.fail; - -import com.android.compatibility.common.util.CddTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import androidx.test.filters.LargeTest; - -@RequiredProperties({DATA_SAVER_MODE, METERED_NETWORK}) -@LargeTest -public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase { - - private static final String[] REQUIRED_WHITELISTED_PACKAGES = { - "com.android.providers.downloads" - }; - - @Before - public void setUp() throws Exception { - super.setUp(); - - // Set initial state. - setRestrictBackground(false); - removeRestrictBackgroundWhitelist(mUid); - removeRestrictBackgroundBlacklist(mUid); - - registerBroadcastReceiver(); - assertRestrictBackgroundChangedReceived(0); - } - - @After - public void tearDown() throws Exception { - super.tearDown(); - - setRestrictBackground(false); - } - - @Test - public void testGetRestrictBackgroundStatus_disabled() throws Exception { - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED); - - // Sanity check: make sure status is always disabled, never whitelisted - addRestrictBackgroundWhitelist(mUid); - assertRestrictBackgroundChangedReceived(0); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED); - - assertsForegroundAlwaysHasNetworkAccess(); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED); - } - - @Test - public void testGetRestrictBackgroundStatus_whitelisted() throws Exception { - setRestrictBackground(true); - assertRestrictBackgroundChangedReceived(1); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - - addRestrictBackgroundWhitelist(mUid); - assertRestrictBackgroundChangedReceived(2); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_WHITELISTED); - - removeRestrictBackgroundWhitelist(mUid); - assertRestrictBackgroundChangedReceived(3); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - - assertsForegroundAlwaysHasNetworkAccess(); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - } - - @Test - public void testGetRestrictBackgroundStatus_enabled() throws Exception { - setRestrictBackground(true); - assertRestrictBackgroundChangedReceived(1); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - - assertsForegroundAlwaysHasNetworkAccess(); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - - // Make sure foreground app doesn't lose access upon enabling Data Saver. - setRestrictBackground(false); - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY); - setRestrictBackground(true); - assertForegroundNetworkAccess(); - - // Although it should not have access while the screen is off. - turnScreenOff(); - assertBackgroundNetworkAccess(false); - turnScreenOn(); - assertForegroundNetworkAccess(); - - // Goes back to background state. - finishActivity(); - assertBackgroundNetworkAccess(false); - - // Make sure foreground service doesn't lose access upon enabling Data Saver. - setRestrictBackground(false); - launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_FOREGROUND_SERVICE); - setRestrictBackground(true); - assertForegroundNetworkAccess(); - stopForegroundService(); - assertBackgroundNetworkAccess(false); - } - - @Test - public void testGetRestrictBackgroundStatus_blacklisted() throws Exception { - addRestrictBackgroundBlacklist(mUid); - assertRestrictBackgroundChangedReceived(1); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - - assertsForegroundAlwaysHasNetworkAccess(); - assertRestrictBackgroundChangedReceived(1); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - - // UID policies live by the Highlander rule: "There can be only one". - // Hence, if app is whitelisted, it should not be blacklisted anymore. - setRestrictBackground(true); - assertRestrictBackgroundChangedReceived(2); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - addRestrictBackgroundWhitelist(mUid); - assertRestrictBackgroundChangedReceived(3); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_WHITELISTED); - - // Check status after removing blacklist. - // ...re-enables first - addRestrictBackgroundBlacklist(mUid); - assertRestrictBackgroundChangedReceived(4); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - assertsForegroundAlwaysHasNetworkAccess(); - // ... remove blacklist - access's still rejected because Data Saver is on - removeRestrictBackgroundBlacklist(mUid); - assertRestrictBackgroundChangedReceived(4); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED); - assertsForegroundAlwaysHasNetworkAccess(); - // ... finally, disable Data Saver - setRestrictBackground(false); - assertRestrictBackgroundChangedReceived(5); - assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED); - assertsForegroundAlwaysHasNetworkAccess(); - } - - @Test - public void testGetRestrictBackgroundStatus_requiredWhitelistedPackages() throws Exception { - final StringBuilder error = new StringBuilder(); - for (String packageName : REQUIRED_WHITELISTED_PACKAGES) { - int uid = -1; - try { - uid = getUid(packageName); - assertRestrictBackgroundWhitelist(uid, true); - } catch (Throwable t) { - error.append("\nFailed for '").append(packageName).append("'"); - if (uid > 0) { - error.append(" (uid ").append(uid).append(")"); - } - error.append(": ").append(t).append("\n"); - } - } - if (error.length() > 0) { - fail(error.toString()); - } - } - - @RequiredProperties({NO_DATA_SAVER_MODE}) - @CddTest(requirement="7.4.7/C-2-2") - @Test - public void testBroadcastNotSentOnUnsupportedDevices() throws Exception { - setRestrictBackground(true); - assertRestrictBackgroundChangedReceived(0); - - setRestrictBackground(false); - assertRestrictBackgroundChangedReceived(0); - - setRestrictBackground(true); - assertRestrictBackgroundChangedReceived(0); - } - - private void assertDataSaverStatusOnBackground(int expectedStatus) throws Exception { - assertRestrictBackgroundStatus(expectedStatus); - assertBackgroundNetworkAccess(expectedStatus != RESTRICT_BACKGROUND_STATUS_ENABLED); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DozeModeMeteredTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DozeModeMeteredTest.java deleted file mode 100644 index 4306c991c2..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DozeModeMeteredTest.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.Property.METERED_NETWORK; - -@RequiredProperties({METERED_NETWORK}) -public class DozeModeMeteredTest extends AbstractDozeModeTestCase { -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DozeModeNonMeteredTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DozeModeNonMeteredTest.java deleted file mode 100644 index 1e89f158a3..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DozeModeNonMeteredTest.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK; - -@RequiredProperties({NON_METERED_NETWORK}) -public class DozeModeNonMeteredTest extends AbstractDozeModeTestCase { -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java deleted file mode 100644 index 5ecb399da0..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TAG; -import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TEST_APP2_PKG; -import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TEST_PKG; - -import android.os.Environment; -import android.os.FileUtils; -import android.os.ParcelFileDescriptor; -import android.util.Log; - -import com.android.compatibility.common.util.OnFailureRule; - -import org.junit.AssumptionViolatedException; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import androidx.test.platform.app.InstrumentationRegistry; - -public class DumpOnFailureRule extends OnFailureRule { - private File mDumpDir = new File(Environment.getExternalStorageDirectory(), - "CtsHostsideNetworkTests"); - - @Override - public void onTestFailure(Statement base, Description description, Throwable throwable) { - final String testName = description.getClassName() + "_" + description.getMethodName(); - - if (throwable instanceof AssumptionViolatedException) { - Log.d(TAG, "Skipping test " + testName + ": " + throwable); - return; - } - - prepareDumpRootDir(); - final File dumpFile = new File(mDumpDir, "dump-" + testName); - Log.i(TAG, "Dumping debug info for " + description + ": " + dumpFile.getPath()); - try (FileOutputStream out = new FileOutputStream(dumpFile)) { - for (String cmd : new String[] { - "dumpsys netpolicy", - "dumpsys network_management", - "dumpsys usagestats " + TEST_PKG + " " + TEST_APP2_PKG, - "dumpsys usagestats appstandby", - }) { - dumpCommandOutput(out, cmd); - } - } catch (FileNotFoundException e) { - Log.e(TAG, "Error opening file: " + dumpFile, e); - } catch (IOException e) { - Log.e(TAG, "Error closing file: " + dumpFile, e); - } - } - - void dumpCommandOutput(FileOutputStream out, String cmd) { - final ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation() - .getUiAutomation().executeShellCommand(cmd); - try (FileInputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) { - out.write(("Output of '" + cmd + "':\n").getBytes(StandardCharsets.UTF_8)); - FileUtils.copy(in, out); - out.write("\n\n=================================================================\n\n" - .getBytes(StandardCharsets.UTF_8)); - } catch (IOException e) { - Log.e(TAG, "Error dumping '" + cmd + "'", e); - } - } - - void prepareDumpRootDir() { - if (!mDumpDir.exists() && !mDumpDir.mkdir()) { - Log.e(TAG, "Error creating " + mDumpDir); - } - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MeterednessConfigurationRule.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MeterednessConfigurationRule.java deleted file mode 100644 index 8fadf9e295..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MeterednessConfigurationRule.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.resetMeteredNetwork; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setupMeteredNetwork; -import static com.android.cts.net.hostside.Property.METERED_NETWORK; -import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK; - -import android.util.ArraySet; -import android.util.Pair; - -import com.android.compatibility.common.util.BeforeAfterRule; - -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -public class MeterednessConfigurationRule extends BeforeAfterRule { - private Pair mSsidAndInitialMeteredness; - - @Override - public void onBefore(Statement base, Description description) throws Throwable { - final ArraySet requiredProperties - = RequiredPropertiesRule.getRequiredProperties(); - if (requiredProperties.contains(METERED_NETWORK)) { - configureNetworkMeteredness(true); - } else if (requiredProperties.contains(NON_METERED_NETWORK)) { - configureNetworkMeteredness(false); - } - } - - @Override - public void onAfter(Statement base, Description description) throws Throwable { - resetNetworkMeteredness(); - } - - public void configureNetworkMeteredness(boolean metered) throws Exception { - mSsidAndInitialMeteredness = setupMeteredNetwork(metered); - } - - public void resetNetworkMeteredness() throws Exception { - if (mSsidAndInitialMeteredness != null) { - resetMeteredNetwork(mSsidAndInitialMeteredness.first, - mSsidAndInitialMeteredness.second); - } - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java deleted file mode 100644 index c9edda6e0b..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MixedModesTest.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground; -import static com.android.cts.net.hostside.Property.APP_STANDBY_MODE; -import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE; -import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE; -import static com.android.cts.net.hostside.Property.DOZE_MODE; -import static com.android.cts.net.hostside.Property.METERED_NETWORK; -import static com.android.cts.net.hostside.Property.NON_METERED_NETWORK; - -import android.os.SystemClock; -import android.util.Log; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Test cases for the more complex scenarios where multiple restrictions (like Battery Saver Mode - * and Data Saver Mode) are applied simultaneously. - *

- * NOTE: it might sound like the test methods on this class are testing too much, - * which would make it harder to diagnose individual failures, but the assumption is that such - * failure most likely will happen when the restriction is tested individually as well. - */ -public class MixedModesTest extends AbstractRestrictBackgroundNetworkTestCase { - private static final String TAG = "MixedModesTest"; - - @Before - public void setUp() throws Exception { - super.setUp(); - - // Set initial state. - removeRestrictBackgroundWhitelist(mUid); - removeRestrictBackgroundBlacklist(mUid); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - - registerBroadcastReceiver(); - } - - @After - public void tearDown() throws Exception { - super.tearDown(); - - try { - setRestrictBackground(false); - } finally { - setBatterySaverMode(false); - } - } - - /** - * Tests all DS ON and BS ON scenarios from network-policy-restrictions.md on metered networks. - */ - @RequiredProperties({DATA_SAVER_MODE, BATTERY_SAVER_MODE, METERED_NETWORK}) - @Test - public void testDataAndBatterySaverModes_meteredNetwork() throws Exception { - final MeterednessConfigurationRule meterednessConfiguration - = new MeterednessConfigurationRule(); - meterednessConfiguration.configureNetworkMeteredness(true); - try { - setRestrictBackground(true); - setBatterySaverMode(true); - - Log.v(TAG, "Not whitelisted for any."); - assertBackgroundNetworkAccess(false); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - - Log.v(TAG, "Whitelisted for Data Saver but not for Battery Saver."); - addRestrictBackgroundWhitelist(mUid); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - removeRestrictBackgroundWhitelist(mUid); - - Log.v(TAG, "Whitelisted for Battery Saver but not for Data Saver."); - addPowerSaveModeWhitelist(TEST_APP2_PKG); - removeRestrictBackgroundWhitelist(mUid); - assertBackgroundNetworkAccess(false); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - - Log.v(TAG, "Whitelisted for both."); - addRestrictBackgroundWhitelist(mUid); - addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(true); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(true); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - removeRestrictBackgroundWhitelist(mUid); - - Log.v(TAG, "Blacklisted for Data Saver, not whitelisted for Battery Saver."); - addRestrictBackgroundBlacklist(mUid); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - removeRestrictBackgroundBlacklist(mUid); - - Log.v(TAG, "Blacklisted for Data Saver, whitelisted for Battery Saver."); - addRestrictBackgroundBlacklist(mUid); - addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - removeRestrictBackgroundBlacklist(mUid); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - } finally { - meterednessConfiguration.resetNetworkMeteredness(); - } - } - - /** - * Tests all DS ON and BS ON scenarios from network-policy-restrictions.md on non-metered - * networks. - */ - @RequiredProperties({DATA_SAVER_MODE, BATTERY_SAVER_MODE, NON_METERED_NETWORK}) - @Test - public void testDataAndBatterySaverModes_nonMeteredNetwork() throws Exception { - final MeterednessConfigurationRule meterednessConfiguration - = new MeterednessConfigurationRule(); - meterednessConfiguration.configureNetworkMeteredness(false); - try { - setRestrictBackground(true); - setBatterySaverMode(true); - - Log.v(TAG, "Not whitelisted for any."); - assertBackgroundNetworkAccess(false); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - - Log.v(TAG, "Whitelisted for Data Saver but not for Battery Saver."); - addRestrictBackgroundWhitelist(mUid); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - removeRestrictBackgroundWhitelist(mUid); - - Log.v(TAG, "Whitelisted for Battery Saver but not for Data Saver."); - addPowerSaveModeWhitelist(TEST_APP2_PKG); - removeRestrictBackgroundWhitelist(mUid); - assertBackgroundNetworkAccess(true); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(true); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - - Log.v(TAG, "Whitelisted for both."); - addRestrictBackgroundWhitelist(mUid); - addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(true); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(true); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - removeRestrictBackgroundWhitelist(mUid); - - Log.v(TAG, "Blacklisted for Data Saver, not whitelisted for Battery Saver."); - addRestrictBackgroundBlacklist(mUid); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(false); - removeRestrictBackgroundBlacklist(mUid); - - Log.v(TAG, "Blacklisted for Data Saver, whitelisted for Battery Saver."); - addRestrictBackgroundBlacklist(mUid); - addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(true); - assertsForegroundAlwaysHasNetworkAccess(); - assertBackgroundNetworkAccess(true); - removeRestrictBackgroundBlacklist(mUid); - removePowerSaveModeWhitelist(TEST_APP2_PKG); - } finally { - meterednessConfiguration.resetNetworkMeteredness(); - } - } - - /** - * Tests that powersave whitelists works as expected when doze and battery saver modes - * are enabled. - */ - @RequiredProperties({DOZE_MODE, BATTERY_SAVER_MODE}) - @Test - public void testDozeAndBatterySaverMode_powerSaveWhitelists() throws Exception { - setBatterySaverMode(true); - setDozeMode(true); - - try { - addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(true); - - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - - addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - - removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - } finally { - setBatterySaverMode(false); - setDozeMode(false); - } - } - - /** - * Tests that powersave whitelists works as expected when doze and appIdle modes - * are enabled. - */ - @RequiredProperties({DOZE_MODE, APP_STANDBY_MODE}) - @Test - public void testDozeAndAppIdle_powerSaveWhitelists() throws Exception { - setDozeMode(true); - setAppIdle(true); - - try { - addPowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(true); - - removePowerSaveModeWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - - addPowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - - removePowerSaveModeExceptIdleWhitelist(TEST_APP2_PKG); - assertBackgroundNetworkAccess(false); - } finally { - setAppIdle(false); - setDozeMode(false); - } - } - - @RequiredProperties({APP_STANDBY_MODE, DOZE_MODE}) - @Test - public void testAppIdleAndDoze_tempPowerSaveWhitelists() throws Exception { - setDozeMode(true); - setAppIdle(true); - - try { - assertBackgroundNetworkAccess(false); - - addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(true); - - // Wait until the whitelist duration is expired. - SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(false); - } finally { - setAppIdle(false); - setDozeMode(false); - } - } - - @RequiredProperties({APP_STANDBY_MODE, BATTERY_SAVER_MODE}) - @Test - public void testAppIdleAndBatterySaver_tempPowerSaveWhitelists() throws Exception { - setBatterySaverMode(true); - setAppIdle(true); - - try { - assertBackgroundNetworkAccess(false); - - addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(true); - - // Wait until the whitelist duration is expired. - SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(false); - } finally { - setAppIdle(false); - setBatterySaverMode(false); - } - } - - /** - * Tests that the app idle whitelist works as expected when doze and appIdle mode are enabled. - */ - @RequiredProperties({DOZE_MODE, APP_STANDBY_MODE}) - @Test - public void testDozeAndAppIdle_appIdleWhitelist() throws Exception { - setDozeMode(true); - setAppIdle(true); - - try { - assertBackgroundNetworkAccess(false); - - // UID still shouldn't have access because of Doze. - addAppIdleWhitelist(mUid); - assertBackgroundNetworkAccess(false); - - removeAppIdleWhitelist(mUid); - assertBackgroundNetworkAccess(false); - } finally { - setAppIdle(false); - setDozeMode(false); - } - } - - @RequiredProperties({APP_STANDBY_MODE, DOZE_MODE}) - @Test - public void testAppIdleAndDoze_tempPowerSaveAndAppIdleWhitelists() throws Exception { - setDozeMode(true); - setAppIdle(true); - - try { - assertBackgroundNetworkAccess(false); - - addAppIdleWhitelist(mUid); - assertBackgroundNetworkAccess(false); - - addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(true); - - // Wait until the whitelist duration is expired. - SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(false); - } finally { - setAppIdle(false); - setDozeMode(false); - removeAppIdleWhitelist(mUid); - } - } - - @RequiredProperties({APP_STANDBY_MODE, BATTERY_SAVER_MODE}) - @Test - public void testAppIdleAndBatterySaver_tempPowerSaveAndAppIdleWhitelists() throws Exception { - setBatterySaverMode(true); - setAppIdle(true); - - try { - assertBackgroundNetworkAccess(false); - - addAppIdleWhitelist(mUid); - assertBackgroundNetworkAccess(false); - - addTempPowerSaveModeWhitelist(TEST_APP2_PKG, TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(true); - - // Wait until the whitelist duration is expired. - SystemClock.sleep(TEMP_POWERSAVE_WHITELIST_DURATION_MS); - assertBackgroundNetworkAccess(false); - } finally { - setAppIdle(false); - setBatterySaverMode(false); - removeAppIdleWhitelist(mUid); - } - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyActivity.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyActivity.java deleted file mode 100644 index 0d0bc58504..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyActivity.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.WindowManager; - -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -public class MyActivity extends Activity { - private final LinkedBlockingQueue mResult = new LinkedBlockingQueue<>(1); - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON - | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON - | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (mResult.offer(resultCode) == false) { - throw new RuntimeException("Queue is full! This should never happen"); - } - } - - public Integer getResult(int timeoutMs) throws InterruptedException { - return mResult.poll(timeoutMs, TimeUnit.MILLISECONDS); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyNotificationListenerService.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyNotificationListenerService.java deleted file mode 100644 index 013253670a..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyNotificationListenerService.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside; - -import android.app.Notification; -import android.app.PendingIntent; -import android.app.PendingIntent.CanceledException; -import android.app.RemoteInput; -import android.content.ComponentName; -import android.os.Bundle; -import android.service.notification.NotificationListenerService; -import android.service.notification.StatusBarNotification; -import android.util.Log; - -/** - * NotificationListenerService implementation that executes the notification actions once they're - * created. - */ -public class MyNotificationListenerService extends NotificationListenerService { - private static final String TAG = "MyNotificationListenerService"; - - @Override - public void onListenerConnected() { - Log.d(TAG, "onListenerConnected()"); - } - - @Override - public void onNotificationPosted(StatusBarNotification sbn) { - Log.d(TAG, "onNotificationPosted(): " + sbn); - if (!sbn.getPackageName().startsWith(getPackageName())) { - Log.v(TAG, "ignoring notification from a different package"); - return; - } - final PendingIntentSender sender = new PendingIntentSender(); - final Notification notification = sbn.getNotification(); - if (notification.contentIntent != null) { - sender.send("content", notification.contentIntent); - } - if (notification.deleteIntent != null) { - sender.send("delete", notification.deleteIntent); - } - if (notification.fullScreenIntent != null) { - sender.send("full screen", notification.fullScreenIntent); - } - if (notification.actions != null) { - for (Notification.Action action : notification.actions) { - sender.send("action", action.actionIntent); - sender.send("action extras", action.getExtras()); - final RemoteInput[] remoteInputs = action.getRemoteInputs(); - if (remoteInputs != null && remoteInputs.length > 0) { - for (RemoteInput remoteInput : remoteInputs) { - sender.send("remote input extras", remoteInput.getExtras()); - } - } - } - } - sender.send("notification extras", notification.extras); - } - - static String getId() { - return String.format("%s/%s", MyNotificationListenerService.class.getPackage().getName(), - MyNotificationListenerService.class.getName()); - } - - static ComponentName getComponentName() { - return new ComponentName(MyNotificationListenerService.class.getPackage().getName(), - MyNotificationListenerService.class.getName()); - } - - private static final class PendingIntentSender { - private PendingIntent mSentIntent = null; - private String mReason = null; - - private void send(String reason, PendingIntent pendingIntent) { - if (pendingIntent == null) { - // Could happen on action that only has extras - Log.v(TAG, "Not sending null pending intent for " + reason); - return; - } - if (mSentIntent != null || mReason != null) { - // Sanity check: make sure test case set up just one pending intent in the - // notification, otherwise it could pass because another pending intent caused the - // whitelisting. - throw new IllegalStateException("Already sent a PendingIntent (" + mSentIntent - + ") for reason '" + mReason + "' when requested another for '" + reason - + "' (" + pendingIntent + ")"); - } - Log.i(TAG, "Sending pending intent for " + reason + ":" + pendingIntent); - try { - pendingIntent.send(); - mSentIntent = pendingIntent; - mReason = reason; - } catch (CanceledException e) { - Log.w(TAG, "Pending intent " + pendingIntent + " canceled"); - } - } - - private void send(String reason, Bundle extras) { - if (extras != null) { - for (String key : extras.keySet()) { - Object value = extras.get(key); - if (value instanceof PendingIntent) { - send(reason + " with key '" + key + "'", (PendingIntent) value); - } - } - } - } - - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java deleted file mode 100644 index 6546e26ba7..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyServiceClient.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.ConditionVariable; -import android.os.IBinder; -import android.os.RemoteException; - -import com.android.cts.net.hostside.IMyService; - -public class MyServiceClient { - private static final int TIMEOUT_MS = 5000; - private static final String PACKAGE = MyServiceClient.class.getPackage().getName(); - private static final String APP2_PACKAGE = PACKAGE + ".app2"; - private static final String SERVICE_NAME = APP2_PACKAGE + ".MyService"; - - private Context mContext; - private ServiceConnection mServiceConnection; - private IMyService mService; - - public MyServiceClient(Context context) { - mContext = context; - } - - public void bind() { - if (mService != null) { - throw new IllegalStateException("Already bound"); - } - - final ConditionVariable cv = new ConditionVariable(); - mServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - mService = IMyService.Stub.asInterface(service); - cv.open(); - } - @Override - public void onServiceDisconnected(ComponentName name) { - mService = null; - } - }; - - final Intent intent = new Intent(); - intent.setComponent(new ComponentName(APP2_PACKAGE, SERVICE_NAME)); - // Needs to use BIND_NOT_FOREGROUND so app2 does not run in - // the same process state as app - mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE - | Context.BIND_NOT_FOREGROUND); - cv.block(TIMEOUT_MS); - if (mService == null) { - throw new IllegalStateException( - "Could not bind to MyService service after " + TIMEOUT_MS + "ms"); - } - } - - public void unbind() { - if (mService != null) { - mContext.unbindService(mServiceConnection); - } - } - - public void registerBroadcastReceiver() throws RemoteException { - mService.registerBroadcastReceiver(); - } - - public int getCounters(String receiverName, String action) throws RemoteException { - return mService.getCounters(receiverName, action); - } - - public String checkNetworkStatus() throws RemoteException { - return mService.checkNetworkStatus(); - } - - public String getRestrictBackgroundStatus() throws RemoteException { - return mService.getRestrictBackgroundStatus(); - } - - public void sendNotification(int notificationId, String notificationType) throws RemoteException { - mService.sendNotification(notificationId, notificationType); - } - - public void registerNetworkCallback(INetworkCallback cb) throws RemoteException { - mService.registerNetworkCallback(cb); - } - - public void unregisterNetworkCallback() throws RemoteException { - mService.unregisterNetworkCallback(); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyVpnService.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyVpnService.java deleted file mode 100644 index 7d3d4fce74..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyVpnService.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import android.content.Intent; -import android.net.Network; -import android.net.ProxyInfo; -import android.net.VpnService; -import android.os.ParcelFileDescriptor; -import android.content.pm.PackageManager.NameNotFoundException; -import android.text.TextUtils; -import android.util.Log; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; - -public class MyVpnService extends VpnService { - - private static String TAG = "MyVpnService"; - private static int MTU = 1799; - - public static final String ACTION_ESTABLISHED = "com.android.cts.net.hostside.ESTABNLISHED"; - public static final String EXTRA_ALWAYS_ON = "is-always-on"; - public static final String EXTRA_LOCKDOWN_ENABLED = "is-lockdown-enabled"; - - private ParcelFileDescriptor mFd = null; - private PacketReflector mPacketReflector = null; - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - String packageName = getPackageName(); - String cmd = intent.getStringExtra(packageName + ".cmd"); - if ("disconnect".equals(cmd)) { - stop(); - } else if ("connect".equals(cmd)) { - start(packageName, intent); - } - - return START_NOT_STICKY; - } - - private void start(String packageName, Intent intent) { - Builder builder = new Builder(); - - String addresses = intent.getStringExtra(packageName + ".addresses"); - if (addresses != null) { - String[] addressArray = addresses.split(","); - for (int i = 0; i < addressArray.length; i++) { - String[] prefixAndMask = addressArray[i].split("/"); - try { - InetAddress address = InetAddress.getByName(prefixAndMask[0]); - int prefixLength = Integer.parseInt(prefixAndMask[1]); - builder.addAddress(address, prefixLength); - } catch (UnknownHostException|NumberFormatException| - ArrayIndexOutOfBoundsException e) { - continue; - } - } - } - - String routes = intent.getStringExtra(packageName + ".routes"); - if (routes != null) { - String[] routeArray = routes.split(","); - for (int i = 0; i < routeArray.length; i++) { - String[] prefixAndMask = routeArray[i].split("/"); - try { - InetAddress address = InetAddress.getByName(prefixAndMask[0]); - int prefixLength = Integer.parseInt(prefixAndMask[1]); - builder.addRoute(address, prefixLength); - } catch (UnknownHostException|NumberFormatException| - ArrayIndexOutOfBoundsException e) { - continue; - } - } - } - - String allowed = intent.getStringExtra(packageName + ".allowedapplications"); - if (allowed != null) { - String[] packageArray = allowed.split(","); - for (int i = 0; i < packageArray.length; i++) { - String allowedPackage = packageArray[i]; - if (!TextUtils.isEmpty(allowedPackage)) { - try { - builder.addAllowedApplication(allowedPackage); - } catch(NameNotFoundException e) { - continue; - } - } - } - } - - String disallowed = intent.getStringExtra(packageName + ".disallowedapplications"); - if (disallowed != null) { - String[] packageArray = disallowed.split(","); - for (int i = 0; i < packageArray.length; i++) { - String disallowedPackage = packageArray[i]; - if (!TextUtils.isEmpty(disallowedPackage)) { - try { - builder.addDisallowedApplication(disallowedPackage); - } catch(NameNotFoundException e) { - continue; - } - } - } - } - - ArrayList underlyingNetworks = - intent.getParcelableArrayListExtra(packageName + ".underlyingNetworks"); - if (underlyingNetworks == null) { - // VPN tracks default network - builder.setUnderlyingNetworks(null); - } else { - builder.setUnderlyingNetworks(underlyingNetworks.toArray(new Network[0])); - } - - boolean isAlwaysMetered = intent.getBooleanExtra(packageName + ".isAlwaysMetered", false); - builder.setMetered(isAlwaysMetered); - - ProxyInfo vpnProxy = intent.getParcelableExtra(packageName + ".httpProxy"); - builder.setHttpProxy(vpnProxy); - builder.setMtu(MTU); - builder.setBlocking(true); - builder.setSession("MyVpnService"); - - Log.i(TAG, "Establishing VPN," - + " addresses=" + addresses - + " routes=" + routes - + " allowedApplications=" + allowed - + " disallowedApplications=" + disallowed); - - mFd = builder.establish(); - Log.i(TAG, "Established, fd=" + (mFd == null ? "null" : mFd.getFd())); - - broadcastEstablished(); - - mPacketReflector = new PacketReflector(mFd.getFileDescriptor(), MTU); - mPacketReflector.start(); - } - - private void broadcastEstablished() { - final Intent bcIntent = new Intent(ACTION_ESTABLISHED); - bcIntent.putExtra(EXTRA_ALWAYS_ON, isAlwaysOn()); - bcIntent.putExtra(EXTRA_LOCKDOWN_ENABLED, isLockdownEnabled()); - sendBroadcast(bcIntent); - } - - private void stop() { - if (mPacketReflector != null) { - mPacketReflector.interrupt(); - mPacketReflector = null; - } - try { - if (mFd != null) { - Log.i(TAG, "Closing filedescriptor"); - mFd.close(); - } - } catch(IOException e) { - } finally { - mFd = null; - } - } - - @Override - public void onDestroy() { - stop(); - super.onDestroy(); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkCallbackTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkCallbackTest.java deleted file mode 100644 index 2ac29e77ff..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkCallbackTest.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.canChangeActiveNetworkMeteredness; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isActiveNetworkMetered; -import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE; -import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import android.net.Network; -import android.net.NetworkCapabilities; -import android.util.Log; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.util.Objects; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -public class NetworkCallbackTest extends AbstractRestrictBackgroundNetworkTestCase { - private Network mNetwork; - private final TestNetworkCallback mTestNetworkCallback = new TestNetworkCallback(); - @Rule - public final MeterednessConfigurationRule mMeterednessConfiguration - = new MeterednessConfigurationRule(); - - enum CallbackState { - NONE, - AVAILABLE, - LOST, - BLOCKED_STATUS, - CAPABILITIES - } - - private static class CallbackInfo { - public final CallbackState state; - public final Network network; - public final Object arg; - - CallbackInfo(CallbackState s, Network n, Object o) { - state = s; network = n; arg = o; - } - - public String toString() { - return String.format("%s (%s) (%s)", state, network, arg); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof CallbackInfo)) return false; - // Ignore timeMs, since it's unpredictable. - final CallbackInfo other = (CallbackInfo) o; - return (state == other.state) && Objects.equals(network, other.network) - && Objects.equals(arg, other.arg); - } - - @Override - public int hashCode() { - return Objects.hash(state, network, arg); - } - } - - private class TestNetworkCallback extends INetworkCallback.Stub { - private static final int TEST_CONNECT_TIMEOUT_MS = 30_000; - private static final int TEST_CALLBACK_TIMEOUT_MS = 5_000; - - private final LinkedBlockingQueue mCallbacks = new LinkedBlockingQueue<>(); - - protected void setLastCallback(CallbackState state, Network network, Object o) { - mCallbacks.offer(new CallbackInfo(state, network, o)); - } - - CallbackInfo nextCallback(int timeoutMs) { - CallbackInfo cb = null; - try { - cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - } - if (cb == null) { - fail("Did not receive callback after " + timeoutMs + "ms"); - } - return cb; - } - - CallbackInfo expectCallback(CallbackState state, Network expectedNetwork, Object o) { - final CallbackInfo expected = new CallbackInfo(state, expectedNetwork, o); - final CallbackInfo actual = nextCallback(TEST_CALLBACK_TIMEOUT_MS); - assertEquals("Unexpected callback:", expected, actual); - return actual; - } - - @Override - public void onAvailable(Network network) { - setLastCallback(CallbackState.AVAILABLE, network, null); - } - - @Override - public void onLost(Network network) { - setLastCallback(CallbackState.LOST, network, null); - } - - @Override - public void onBlockedStatusChanged(Network network, boolean blocked) { - setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked); - } - - @Override - public void onCapabilitiesChanged(Network network, NetworkCapabilities cap) { - setLastCallback(CallbackState.CAPABILITIES, network, cap); - } - - public Network expectAvailableCallbackAndGetNetwork() { - final CallbackInfo cb = nextCallback(TEST_CONNECT_TIMEOUT_MS); - if (cb.state != CallbackState.AVAILABLE) { - fail("Network is not available. Instead obtained the following callback :" - + cb); - } - return cb.network; - } - - public void expectBlockedStatusCallback(Network expectedNetwork, boolean expectBlocked) { - expectCallback(CallbackState.BLOCKED_STATUS, expectedNetwork, expectBlocked); - } - - public void expectBlockedStatusCallbackEventually(Network expectedNetwork, - boolean expectBlocked) { - final long deadline = System.currentTimeMillis() + TEST_CALLBACK_TIMEOUT_MS; - do { - final CallbackInfo cb = nextCallback((int) (deadline - System.currentTimeMillis())); - if (cb.state == CallbackState.BLOCKED_STATUS - && cb.network.equals(expectedNetwork)) { - assertEquals(expectBlocked, cb.arg); - return; - } - } while (System.currentTimeMillis() <= deadline); - fail("Didn't receive onBlockedStatusChanged()"); - } - - public void expectCapabilitiesCallbackEventually(Network expectedNetwork, boolean hasCap, - int cap) { - final long deadline = System.currentTimeMillis() + TEST_CALLBACK_TIMEOUT_MS; - do { - final CallbackInfo cb = nextCallback((int) (deadline - System.currentTimeMillis())); - if (cb.state != CallbackState.CAPABILITIES - || !expectedNetwork.equals(cb.network) - || (hasCap != ((NetworkCapabilities) cb.arg).hasCapability(cap))) { - Log.i("NetworkCallbackTest#expectCapabilitiesCallback", - "Ignoring non-matching callback : " + cb); - continue; - } - // Found a match, return - return; - } while (System.currentTimeMillis() <= deadline); - fail("Didn't receive the expected callback to onCapabilitiesChanged(). Check the " - + "log for a list of received callbacks, if any."); - } - } - - @Before - public void setUp() throws Exception { - super.setUp(); - - assumeTrue(isActiveNetworkMetered(true) || canChangeActiveNetworkMeteredness()); - - registerBroadcastReceiver(); - - removeRestrictBackgroundWhitelist(mUid); - removeRestrictBackgroundBlacklist(mUid); - assertRestrictBackgroundChangedReceived(0); - - // Initial state - setBatterySaverMode(false); - setRestrictBackground(false); - - // Make wifi a metered network. - mMeterednessConfiguration.configureNetworkMeteredness(true); - - // Register callback - registerNetworkCallback((INetworkCallback.Stub) mTestNetworkCallback); - // Once the wifi is marked as metered, the wifi will reconnect. Wait for onAvailable() - // callback to ensure wifi is connected before the test and store the default network. - mNetwork = mTestNetworkCallback.expectAvailableCallbackAndGetNetwork(); - // Check that the network is metered. - mTestNetworkCallback.expectCapabilitiesCallbackEventually(mNetwork, - false /* hasCapability */, NET_CAPABILITY_NOT_METERED); - mTestNetworkCallback.expectBlockedStatusCallback(mNetwork, false); - } - - @After - public void tearDown() throws Exception { - super.tearDown(); - - setRestrictBackground(false); - setBatterySaverMode(false); - unregisterNetworkCallback(); - } - - @RequiredProperties({DATA_SAVER_MODE}) - @Test - public void testOnBlockedStatusChanged_dataSaver() throws Exception { - try { - // Enable restrict background - setRestrictBackground(true); - assertBackgroundNetworkAccess(false); - mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, true); - - // Add to whitelist - addRestrictBackgroundWhitelist(mUid); - assertBackgroundNetworkAccess(true); - mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, false); - - // Remove from whitelist - removeRestrictBackgroundWhitelist(mUid); - assertBackgroundNetworkAccess(false); - mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, true); - } finally { - mMeterednessConfiguration.resetNetworkMeteredness(); - } - - // Set to non-metered network - mMeterednessConfiguration.configureNetworkMeteredness(false); - mTestNetworkCallback.expectCapabilitiesCallbackEventually(mNetwork, - true /* hasCapability */, NET_CAPABILITY_NOT_METERED); - try { - assertBackgroundNetworkAccess(true); - mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, false); - - // Disable restrict background, should not trigger callback - setRestrictBackground(false); - assertBackgroundNetworkAccess(true); - } finally { - mMeterednessConfiguration.resetNetworkMeteredness(); - } - } - - @RequiredProperties({BATTERY_SAVER_MODE}) - @Test - public void testOnBlockedStatusChanged_powerSaver() throws Exception { - try { - // Enable Power Saver - setBatterySaverMode(true); - assertBackgroundNetworkAccess(false); - mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, true); - - // Disable Power Saver - setBatterySaverMode(false); - assertBackgroundNetworkAccess(true); - mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, false); - } finally { - mMeterednessConfiguration.resetNetworkMeteredness(); - } - - // Set to non-metered network - mMeterednessConfiguration.configureNetworkMeteredness(false); - mTestNetworkCallback.expectCapabilitiesCallbackEventually(mNetwork, - true /* hasCapability */, NET_CAPABILITY_NOT_METERED); - try { - // Enable Power Saver - setBatterySaverMode(true); - assertBackgroundNetworkAccess(false); - mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, true); - - // Disable Power Saver - setBatterySaverMode(false); - assertBackgroundNetworkAccess(true); - mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, false); - } finally { - mMeterednessConfiguration.resetNetworkMeteredness(); - } - } - - // TODO: 1. test against VPN lockdown. - // 2. test against multiple networks. -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestRunner.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestRunner.java deleted file mode 100644 index f340907ae5..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestRunner.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 com.android.cts.net.hostside; - -import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner; - -import org.junit.rules.RunRules; -import org.junit.rules.TestRule; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.InitializationError; -import org.junit.runners.model.Statement; - -import java.util.List; - -/** - * Custom runner to allow dumping logs after a test failure before the @After methods get to run. - */ -public class NetworkPolicyTestRunner extends AndroidJUnit4ClassRunner { - private TestRule mDumpOnFailureRule = new DumpOnFailureRule(); - - public NetworkPolicyTestRunner(Class klass) throws InitializationError { - super(klass); - } - - @Override - public Statement methodInvoker(FrameworkMethod method, Object test) { - return new RunRules(super.methodInvoker(method, test), List.of(mDumpOnFailureRule), - describeChild(method)); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java deleted file mode 100644 index 3807d79c35..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyTestUtils.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED; -import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED; -import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; - -import static com.android.compatibility.common.util.SystemUtil.runShellCommand; -import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TAG; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.app.ActivityManager; -import android.app.Instrumentation; -import android.content.Context; -import android.location.LocationManager; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.wifi.WifiManager; -import android.os.Process; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import com.android.compatibility.common.util.AppStandbyUtils; -import com.android.compatibility.common.util.BatteryUtils; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import androidx.test.platform.app.InstrumentationRegistry; - -public class NetworkPolicyTestUtils { - - private static final int TIMEOUT_CHANGE_METEREDNESS_MS = 5000; - - private static ConnectivityManager mCm; - private static WifiManager mWm; - - private static Boolean mBatterySaverSupported; - private static Boolean mDataSaverSupported; - private static Boolean mDozeModeSupported; - private static Boolean mAppStandbySupported; - - private NetworkPolicyTestUtils() {} - - public static boolean isBatterySaverSupported() { - if (mBatterySaverSupported == null) { - mBatterySaverSupported = BatteryUtils.isBatterySaverSupported(); - } - return mBatterySaverSupported; - } - - /** - * As per CDD requirements, if the device doesn't support data saver mode then - * ConnectivityManager.getRestrictBackgroundStatus() will always return - * RESTRICT_BACKGROUND_STATUS_DISABLED. So, enable the data saver mode and check if - * ConnectivityManager.getRestrictBackgroundStatus() for an app in background returns - * RESTRICT_BACKGROUND_STATUS_DISABLED or not. - */ - public static boolean isDataSaverSupported() { - if (mDataSaverSupported == null) { - assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED); - try { - setRestrictBackground(true); - mDataSaverSupported = !isMyRestrictBackgroundStatus( - RESTRICT_BACKGROUND_STATUS_DISABLED); - } finally { - setRestrictBackground(false); - } - } - return mDataSaverSupported; - } - - public static boolean isDozeModeSupported() { - if (mDozeModeSupported == null) { - final String result = executeShellCommand("cmd deviceidle enabled deep"); - mDozeModeSupported = result.equals("1"); - } - return mDozeModeSupported; - } - - public static boolean isAppStandbySupported() { - if (mAppStandbySupported == null) { - mAppStandbySupported = AppStandbyUtils.isAppStandbyEnabled(); - } - return mAppStandbySupported; - } - - public static boolean isLowRamDevice() { - final ActivityManager am = (ActivityManager) getContext().getSystemService( - Context.ACTIVITY_SERVICE); - return am.isLowRamDevice(); - } - - public static boolean isLocationEnabled() { - final LocationManager lm = (LocationManager) getContext().getSystemService( - Context.LOCATION_SERVICE); - return lm.isLocationEnabled(); - } - - public static void setLocationEnabled(boolean enabled) { - final LocationManager lm = (LocationManager) getContext().getSystemService( - Context.LOCATION_SERVICE); - lm.setLocationEnabledForUser(enabled, Process.myUserHandle()); - assertEquals("Couldn't change location enabled state", lm.isLocationEnabled(), enabled); - Log.d(TAG, "Changed location enabled state to " + enabled); - } - - public static boolean isActiveNetworkMetered(boolean metered) { - return getConnectivityManager().isActiveNetworkMetered() == metered; - } - - public static boolean canChangeActiveNetworkMeteredness() { - final Network activeNetwork = getConnectivityManager().getActiveNetwork(); - final NetworkCapabilities networkCapabilities - = getConnectivityManager().getNetworkCapabilities(activeNetwork); - return networkCapabilities.hasTransport(TRANSPORT_WIFI); - } - - public static Pair setupMeteredNetwork(boolean metered) throws Exception { - if (isActiveNetworkMetered(metered)) { - return null; - } - final boolean isLocationEnabled = isLocationEnabled(); - try { - if (!isLocationEnabled) { - setLocationEnabled(true); - } - final String ssid = unquoteSSID(getWifiManager().getConnectionInfo().getSSID()); - assertNotEquals(WifiManager.UNKNOWN_SSID, ssid); - setWifiMeteredStatus(ssid, metered); - return Pair.create(ssid, !metered); - } finally { - // Reset the location enabled state - if (!isLocationEnabled) { - setLocationEnabled(false); - } - } - } - - public static void resetMeteredNetwork(String ssid, boolean metered) throws Exception { - setWifiMeteredStatus(ssid, metered); - } - - public static void setWifiMeteredStatus(String ssid, boolean metered) throws Exception { - assertFalse("SSID should not be empty", TextUtils.isEmpty(ssid)); - final String cmd = "cmd netpolicy set metered-network " + ssid + " " + metered; - executeShellCommand(cmd); - assertWifiMeteredStatus(ssid, metered); - assertActiveNetworkMetered(metered); - } - - public static void assertWifiMeteredStatus(String ssid, boolean expectedMeteredStatus) { - final String result = executeShellCommand("cmd netpolicy list wifi-networks"); - final String expectedLine = ssid + ";" + expectedMeteredStatus; - assertTrue("Expected line: " + expectedLine + "; Actual result: " + result, - result.contains(expectedLine)); - } - - // Copied from cts/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java - public static void assertActiveNetworkMetered(boolean expectedMeteredStatus) throws Exception { - final CountDownLatch latch = new CountDownLatch(1); - final NetworkCallback networkCallback = new NetworkCallback() { - @Override - public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) { - final boolean metered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED); - if (metered == expectedMeteredStatus) { - latch.countDown(); - } - } - }; - // Registering a callback here guarantees onCapabilitiesChanged is called immediately - // with the current setting. Therefore, if the setting has already been changed, - // this method will return right away, and if not it will wait for the setting to change. - getConnectivityManager().registerDefaultNetworkCallback(networkCallback); - if (!latch.await(TIMEOUT_CHANGE_METEREDNESS_MS, TimeUnit.MILLISECONDS)) { - fail("Timed out waiting for active network metered status to change to " - + expectedMeteredStatus + " ; network = " - + getConnectivityManager().getActiveNetwork()); - } - getConnectivityManager().unregisterNetworkCallback(networkCallback); - } - - public static void setRestrictBackground(boolean enabled) { - executeShellCommand("cmd netpolicy set restrict-background " + enabled); - final String output = executeShellCommand("cmd netpolicy get restrict-background"); - final String expectedSuffix = enabled ? "enabled" : "disabled"; - assertTrue("output '" + output + "' should end with '" + expectedSuffix + "'", - output.endsWith(expectedSuffix)); - } - - public static boolean isMyRestrictBackgroundStatus(int expectedStatus) { - final int actualStatus = getConnectivityManager().getRestrictBackgroundStatus(); - if (expectedStatus != actualStatus) { - Log.d(TAG, "MyRestrictBackgroundStatus: " - + "Expected: " + restrictBackgroundValueToString(expectedStatus) - + "; Actual: " + restrictBackgroundValueToString(actualStatus)); - return false; - } - return true; - } - - // Copied from cts/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java - private static String unquoteSSID(String ssid) { - // SSID is returned surrounded by quotes if it can be decoded as UTF-8. - // Otherwise it's guaranteed not to start with a quote. - if (ssid.charAt(0) == '"') { - return ssid.substring(1, ssid.length() - 1); - } else { - return ssid; - } - } - - public static String restrictBackgroundValueToString(int status) { - switch (status) { - case RESTRICT_BACKGROUND_STATUS_DISABLED: - return "DISABLED"; - case RESTRICT_BACKGROUND_STATUS_WHITELISTED: - return "WHITELISTED"; - case RESTRICT_BACKGROUND_STATUS_ENABLED: - return "ENABLED"; - default: - return "UNKNOWN_STATUS_" + status; - } - } - - public static String executeShellCommand(String command) { - final String result = runShellCommand(command).trim(); - Log.d(TAG, "Output of '" + command + "': '" + result + "'"); - return result; - } - - public static void assertMyRestrictBackgroundStatus(int expectedStatus) { - final int actualStatus = getConnectivityManager().getRestrictBackgroundStatus(); - assertEquals(restrictBackgroundValueToString(expectedStatus), - restrictBackgroundValueToString(actualStatus)); - } - - public static ConnectivityManager getConnectivityManager() { - if (mCm == null) { - mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE); - } - return mCm; - } - - public static WifiManager getWifiManager() { - if (mWm == null) { - mWm = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); - } - return mWm; - } - - public static Context getContext() { - return getInstrumentation().getContext(); - } - - public static Instrumentation getInstrumentation() { - return InstrumentationRegistry.getInstrumentation(); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/PacketReflector.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/PacketReflector.java deleted file mode 100644 index 124c2c3862..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/PacketReflector.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static android.system.OsConstants.ICMP6_ECHO_REPLY; -import static android.system.OsConstants.ICMP6_ECHO_REQUEST; -import static android.system.OsConstants.ICMP_ECHO; -import static android.system.OsConstants.ICMP_ECHOREPLY; - -import android.system.ErrnoException; -import android.system.Os; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.IOException; - -public class PacketReflector extends Thread { - - private static int IPV4_HEADER_LENGTH = 20; - private static int IPV6_HEADER_LENGTH = 40; - - private static int IPV4_ADDR_OFFSET = 12; - private static int IPV6_ADDR_OFFSET = 8; - private static int IPV4_ADDR_LENGTH = 4; - private static int IPV6_ADDR_LENGTH = 16; - - private static int IPV4_PROTO_OFFSET = 9; - private static int IPV6_PROTO_OFFSET = 6; - - private static final byte IPPROTO_ICMP = 1; - private static final byte IPPROTO_TCP = 6; - private static final byte IPPROTO_UDP = 17; - private static final byte IPPROTO_ICMPV6 = 58; - - private static int ICMP_HEADER_LENGTH = 8; - private static int TCP_HEADER_LENGTH = 20; - private static int UDP_HEADER_LENGTH = 8; - - private static final byte ICMP_ECHO = 8; - private static final byte ICMP_ECHOREPLY = 0; - - private static String TAG = "PacketReflector"; - - private FileDescriptor mFd; - private byte[] mBuf; - - public PacketReflector(FileDescriptor fd, int mtu) { - super("PacketReflector"); - mFd = fd; - mBuf = new byte[mtu]; - } - - private static void swapBytes(byte[] buf, int pos1, int pos2, int len) { - for (int i = 0; i < len; i++) { - byte b = buf[pos1 + i]; - buf[pos1 + i] = buf[pos2 + i]; - buf[pos2 + i] = b; - } - } - - private static void swapAddresses(byte[] buf, int version) { - int addrPos, addrLen; - switch(version) { - case 4: - addrPos = IPV4_ADDR_OFFSET; - addrLen = IPV4_ADDR_LENGTH; - break; - case 6: - addrPos = IPV6_ADDR_OFFSET; - addrLen = IPV6_ADDR_LENGTH; - break; - default: - throw new IllegalArgumentException(); - } - swapBytes(buf, addrPos, addrPos + addrLen, addrLen); - } - - // Reflect TCP packets: swap the source and destination addresses, but don't change the ports. - // This is used by the test to "connect to itself" through the VPN. - private void processTcpPacket(byte[] buf, int version, int len, int hdrLen) { - if (len < hdrLen + TCP_HEADER_LENGTH) { - return; - } - - // Swap src and dst IP addresses. - swapAddresses(buf, version); - - // Send the packet back. - writePacket(buf, len); - } - - // Echo UDP packets: swap source and destination addresses, and source and destination ports. - // This is used by the test to check that the bytes it sends are echoed back. - private void processUdpPacket(byte[] buf, int version, int len, int hdrLen) { - if (len < hdrLen + UDP_HEADER_LENGTH) { - return; - } - - // Swap src and dst IP addresses. - swapAddresses(buf, version); - - // Swap dst and src ports. - int portOffset = hdrLen; - swapBytes(buf, portOffset, portOffset + 2, 2); - - // Send the packet back. - writePacket(buf, len); - } - - private void processIcmpPacket(byte[] buf, int version, int len, int hdrLen) { - if (len < hdrLen + ICMP_HEADER_LENGTH) { - return; - } - - byte type = buf[hdrLen]; - if (!(version == 4 && type == ICMP_ECHO) && - !(version == 6 && type == (byte) ICMP6_ECHO_REQUEST)) { - return; - } - - // Save the ping packet we received. - byte[] request = buf.clone(); - - // Swap src and dst IP addresses, and send the packet back. - // This effectively pings the device to see if it replies. - swapAddresses(buf, version); - writePacket(buf, len); - - // The device should have replied, and buf should now contain a ping response. - int received = readPacket(buf); - if (received != len) { - Log.i(TAG, "Reflecting ping did not result in ping response: " + - "read=" + received + " expected=" + len); - return; - } - - byte replyType = buf[hdrLen]; - if ((type == ICMP_ECHO && replyType != ICMP_ECHOREPLY) - || (type == (byte) ICMP6_ECHO_REQUEST && replyType != (byte) ICMP6_ECHO_REPLY)) { - Log.i(TAG, "Received unexpected ICMP reply: original " + type - + ", reply " + replyType); - return; - } - - // Compare the response we got with the original packet. - // The only thing that should have changed are addresses, type and checksum. - // Overwrite them with the received bytes and see if the packet is otherwise identical. - request[hdrLen] = buf[hdrLen]; // Type - request[hdrLen + 2] = buf[hdrLen + 2]; // Checksum byte 1. - request[hdrLen + 3] = buf[hdrLen + 3]; // Checksum byte 2. - - // Since Linux kernel 4.2, net.ipv6.auto_flowlabels is set by default, and therefore - // the request and reply may have different IPv6 flow label: ignore that as well. - if (version == 6) { - request[1] = (byte)(request[1] & 0xf0 | buf[1] & 0x0f); - request[2] = buf[2]; - request[3] = buf[3]; - } - - for (int i = 0; i < len; i++) { - if (buf[i] != request[i]) { - Log.i(TAG, "Received non-matching packet when expecting ping response."); - return; - } - } - - // Now swap the addresses again and reflect the packet. This sends a ping reply. - swapAddresses(buf, version); - writePacket(buf, len); - } - - private void writePacket(byte[] buf, int len) { - try { - Os.write(mFd, buf, 0, len); - } catch (ErrnoException|IOException e) { - Log.e(TAG, "Error writing packet: " + e.getMessage()); - } - } - - private int readPacket(byte[] buf) { - int len; - try { - len = Os.read(mFd, buf, 0, buf.length); - } catch (ErrnoException|IOException e) { - Log.e(TAG, "Error reading packet: " + e.getMessage()); - len = -1; - } - return len; - } - - // Reads one packet from our mFd, and possibly writes the packet back. - private void processPacket() { - int len = readPacket(mBuf); - if (len < 1) { - return; - } - - int version = mBuf[0] >> 4; - int addrPos, protoPos, hdrLen, addrLen; - if (version == 4) { - hdrLen = IPV4_HEADER_LENGTH; - protoPos = IPV4_PROTO_OFFSET; - addrPos = IPV4_ADDR_OFFSET; - addrLen = IPV4_ADDR_LENGTH; - } else if (version == 6) { - hdrLen = IPV6_HEADER_LENGTH; - protoPos = IPV6_PROTO_OFFSET; - addrPos = IPV6_ADDR_OFFSET; - addrLen = IPV6_ADDR_LENGTH; - } else { - return; - } - - if (len < hdrLen) { - return; - } - - byte proto = mBuf[protoPos]; - switch (proto) { - case IPPROTO_ICMP: - case IPPROTO_ICMPV6: - processIcmpPacket(mBuf, version, len, hdrLen); - break; - case IPPROTO_TCP: - processTcpPacket(mBuf, version, len, hdrLen); - break; - case IPPROTO_UDP: - processUdpPacket(mBuf, version, len, hdrLen); - break; - } - } - - public void run() { - Log.i(TAG, "PacketReflector starting fd=" + mFd + " valid=" + mFd.valid()); - while (!interrupted() && mFd.valid()) { - processPacket(); - } - Log.i(TAG, "PacketReflector exiting fd=" + mFd + " valid=" + mFd.valid()); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/Property.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/Property.java deleted file mode 100644 index 18805f9613..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/Property.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.canChangeActiveNetworkMeteredness; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isActiveNetworkMetered; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isAppStandbySupported; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isBatterySaverSupported; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isDataSaverSupported; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isDozeModeSupported; -import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isLowRamDevice; - -public enum Property { - BATTERY_SAVER_MODE(1 << 0) { - public boolean isSupported() { return isBatterySaverSupported(); } - }, - - DATA_SAVER_MODE(1 << 1) { - public boolean isSupported() { return isDataSaverSupported(); } - }, - - NO_DATA_SAVER_MODE(~DATA_SAVER_MODE.getValue()) { - public boolean isSupported() { return !isDataSaverSupported(); } - }, - - DOZE_MODE(1 << 2) { - public boolean isSupported() { return isDozeModeSupported(); } - }, - - APP_STANDBY_MODE(1 << 3) { - public boolean isSupported() { return isAppStandbySupported(); } - }, - - NOT_LOW_RAM_DEVICE(1 << 4) { - public boolean isSupported() { return !isLowRamDevice(); } - }, - - METERED_NETWORK(1 << 5) { - public boolean isSupported() { - return isActiveNetworkMetered(true) || canChangeActiveNetworkMeteredness(); - } - }, - - NON_METERED_NETWORK(~METERED_NETWORK.getValue()) { - public boolean isSupported() { - return isActiveNetworkMetered(false) || canChangeActiveNetworkMeteredness(); - } - }; - - private int mValue; - - Property(int value) { mValue = value; } - - public int getValue() { return mValue; } - - abstract boolean isSupported(); -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java deleted file mode 100644 index 80f99b6605..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.ConditionVariable; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.system.ErrnoException; -import android.system.Os; - -import com.android.cts.net.hostside.IRemoteSocketFactory; - -import java.io.FileDescriptor; -import java.io.IOException; - -public class RemoteSocketFactoryClient { - private static final int TIMEOUT_MS = 5000; - private static final String PACKAGE = RemoteSocketFactoryClient.class.getPackage().getName(); - private static final String APP2_PACKAGE = PACKAGE + ".app2"; - private static final String SERVICE_NAME = APP2_PACKAGE + ".RemoteSocketFactoryService"; - - private Context mContext; - private ServiceConnection mServiceConnection; - private IRemoteSocketFactory mService; - - public RemoteSocketFactoryClient(Context context) { - mContext = context; - } - - public void bind() { - if (mService != null) { - throw new IllegalStateException("Already bound"); - } - - final ConditionVariable cv = new ConditionVariable(); - mServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - mService = IRemoteSocketFactory.Stub.asInterface(service); - cv.open(); - } - @Override - public void onServiceDisconnected(ComponentName name) { - mService = null; - } - }; - - final Intent intent = new Intent(); - intent.setComponent(new ComponentName(APP2_PACKAGE, SERVICE_NAME)); - mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); - cv.block(TIMEOUT_MS); - if (mService == null) { - throw new IllegalStateException( - "Could not bind to RemoteSocketFactory service after " + TIMEOUT_MS + "ms"); - } - } - - public void unbind() { - if (mService != null) { - mContext.unbindService(mServiceConnection); - } - } - - public FileDescriptor openSocketFd(String host, int port, int timeoutMs) - throws RemoteException, ErrnoException, IOException { - // Dup the filedescriptor so ParcelFileDescriptor's finalizer doesn't garbage collect it - // and cause our fd to become invalid. http://b/35927643 . - ParcelFileDescriptor pfd = mService.openSocketFd(host, port, timeoutMs); - FileDescriptor fd = Os.dup(pfd.getFileDescriptor()); - pfd.close(); - return fd; - } - - public String getPackageName() throws RemoteException { - return mService.getPackageName(); - } - - public int getUid() throws RemoteException { - return mService.getUid(); - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RequiredProperties.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/RequiredProperties.java deleted file mode 100644 index 96838bba0a..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RequiredProperties.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -@Retention(RUNTIME) -@Target({METHOD, TYPE}) -@Inherited -public @interface RequiredProperties { - Property[] value(); -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RequiredPropertiesRule.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/RequiredPropertiesRule.java deleted file mode 100644 index 01f9f3ea81..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RequiredPropertiesRule.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside; - -import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TAG; - -import android.text.TextUtils; -import android.util.ArraySet; -import android.util.Log; - -import com.android.compatibility.common.util.BeforeAfterRule; - -import org.junit.Assume; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import java.util.ArrayList; -import java.util.Collections; - -public class RequiredPropertiesRule extends BeforeAfterRule { - - private static ArraySet mRequiredProperties; - - @Override - public void onBefore(Statement base, Description description) { - mRequiredProperties = getAllRequiredProperties(description); - - final String testName = description.getClassName() + "#" + description.getMethodName(); - assertTestIsValid(testName, mRequiredProperties); - Log.i(TAG, "Running test " + testName + " with required properties: " - + propertiesToString(mRequiredProperties)); - } - - private ArraySet getAllRequiredProperties(Description description) { - final ArraySet allRequiredProperties = new ArraySet<>(); - RequiredProperties requiredProperties = description.getAnnotation(RequiredProperties.class); - if (requiredProperties != null) { - Collections.addAll(allRequiredProperties, requiredProperties.value()); - } - - for (Class clazz = description.getTestClass(); - clazz != null; clazz = clazz.getSuperclass()) { - requiredProperties = clazz.getDeclaredAnnotation(RequiredProperties.class); - if (requiredProperties == null) { - continue; - } - for (Property requiredProperty : requiredProperties.value()) { - for (Property p : Property.values()) { - if (p.getValue() == ~requiredProperty.getValue() - && allRequiredProperties.contains(p)) { - continue; - } - } - allRequiredProperties.add(requiredProperty); - } - } - return allRequiredProperties; - } - - private void assertTestIsValid(String testName, ArraySet requiredProperies) { - if (requiredProperies == null) { - return; - } - final ArrayList unsupportedProperties = new ArrayList<>(); - for (Property property : requiredProperies) { - if (!property.isSupported()) { - unsupportedProperties.add(property); - } - } - Assume.assumeTrue("Unsupported properties: " - + propertiesToString(unsupportedProperties), unsupportedProperties.isEmpty()); - } - - public static ArraySet getRequiredProperties() { - return mRequiredProperties; - } - - private static String propertiesToString(Iterable properties) { - return "[" + TextUtils.join(",", properties) + "]"; - } -} diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java deleted file mode 100755 index a451ea8585..0000000000 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside; - -import static android.os.Process.INVALID_UID; -import static android.system.OsConstants.*; - -import android.annotation.Nullable; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.Proxy; -import android.net.ProxyInfo; -import android.net.VpnService; -import android.net.wifi.WifiManager; -import android.provider.Settings; -import android.os.ParcelFileDescriptor; -import android.os.Process; -import android.os.SystemProperties; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiSelector; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; -import android.system.StructPollfd; -import android.test.InstrumentationTestCase; -import android.test.MoreAsserts; -import android.text.TextUtils; -import android.util.Log; - -import com.android.compatibility.common.util.BlockingBroadcastReceiver; - -import java.io.Closeable; -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Objects; -import java.util.Random; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * Tests for the VpnService API. - * - * These tests establish a VPN via the VpnService API, and have the service reflect the packets back - * to the device without causing any network traffic. This allows testing the local VPN data path - * without a network connection or a VPN server. - * - * Note: in Lollipop, VPN functionality relies on kernel support for UID-based routing. If these - * tests fail, it may be due to the lack of kernel support. The necessary patches can be - * cherry-picked from the Android common kernel trees: - * - * android-3.10: - * https://android-review.googlesource.com/#/c/99220/ - * https://android-review.googlesource.com/#/c/100545/ - * - * android-3.4: - * https://android-review.googlesource.com/#/c/99225/ - * https://android-review.googlesource.com/#/c/100557/ - * - * To ensure that the kernel has the required commits, run the kernel unit - * tests described at: - * - * https://source.android.com/devices/tech/config/kernel_network_tests.html - * - */ -public class VpnTest extends InstrumentationTestCase { - - // These are neither public nor @TestApi. - // TODO: add them to @TestApi. - private static final String PRIVATE_DNS_MODE_SETTING = "private_dns_mode"; - private static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; - private static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; - private static final String PRIVATE_DNS_SPECIFIER_SETTING = "private_dns_specifier"; - - public static String TAG = "VpnTest"; - public static int TIMEOUT_MS = 3 * 1000; - public static int SOCKET_TIMEOUT_MS = 100; - public static String TEST_HOST = "connectivitycheck.gstatic.com"; - - private UiDevice mDevice; - private MyActivity mActivity; - private String mPackageName; - private ConnectivityManager mCM; - private WifiManager mWifiManager; - private RemoteSocketFactoryClient mRemoteSocketFactoryClient; - - Network mNetwork; - NetworkCallback mCallback; - final Object mLock = new Object(); - final Object mLockShutdown = new Object(); - - private String mOldPrivateDnsMode; - private String mOldPrivateDnsSpecifier; - - private boolean supportedHardware() { - final PackageManager pm = getInstrumentation().getContext().getPackageManager(); - return !pm.hasSystemFeature("android.hardware.type.watch"); - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - mNetwork = null; - mCallback = null; - storePrivateDnsSetting(); - - mDevice = UiDevice.getInstance(getInstrumentation()); - mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(), - MyActivity.class, null); - mPackageName = mActivity.getPackageName(); - mCM = (ConnectivityManager) mActivity.getSystemService(Context.CONNECTIVITY_SERVICE); - mWifiManager = (WifiManager) mActivity.getSystemService(Context.WIFI_SERVICE); - mRemoteSocketFactoryClient = new RemoteSocketFactoryClient(mActivity); - mRemoteSocketFactoryClient.bind(); - mDevice.waitForIdle(); - } - - @Override - public void tearDown() throws Exception { - restorePrivateDnsSetting(); - mRemoteSocketFactoryClient.unbind(); - if (mCallback != null) { - mCM.unregisterNetworkCallback(mCallback); - } - Log.i(TAG, "Stopping VPN"); - stopVpn(); - mActivity.finish(); - super.tearDown(); - } - - private void prepareVpn() throws Exception { - final int REQUEST_ID = 42; - - // Attempt to prepare. - Log.i(TAG, "Preparing VPN"); - Intent intent = VpnService.prepare(mActivity); - - if (intent != null) { - // Start the confirmation dialog and click OK. - mActivity.startActivityForResult(intent, REQUEST_ID); - mDevice.waitForIdle(); - - String packageName = intent.getComponent().getPackageName(); - String resourceIdRegex = "android:id/button1$|button_start_vpn"; - final UiObject okButton = new UiObject(new UiSelector() - .className("android.widget.Button") - .packageName(packageName) - .resourceIdMatches(resourceIdRegex)); - if (okButton.waitForExists(TIMEOUT_MS) == false) { - mActivity.finishActivity(REQUEST_ID); - fail("VpnService.prepare returned an Intent for '" + intent.getComponent() + "' " + - "to display the VPN confirmation dialog, but this test could not find the " + - "button to allow the VPN application to connect. Please ensure that the " + - "component displays a button with a resource ID matching the regexp: '" + - resourceIdRegex + "'."); - } - - // Click the button and wait for RESULT_OK. - okButton.click(); - try { - int result = mActivity.getResult(TIMEOUT_MS); - if (result != MyActivity.RESULT_OK) { - fail("The VPN confirmation dialog did not return RESULT_OK when clicking on " + - "the button matching the regular expression '" + resourceIdRegex + - "' of " + intent.getComponent() + "'. Please ensure that clicking on " + - "that button allows the VPN application to connect. " + - "Return value: " + result); - } - } catch (InterruptedException e) { - fail("VPN confirmation dialog did not return after " + TIMEOUT_MS + "ms"); - } - - // Now we should be prepared. - intent = VpnService.prepare(mActivity); - if (intent != null) { - fail("VpnService.prepare returned non-null even after the VPN dialog " + - intent.getComponent() + "returned RESULT_OK."); - } - } - } - - // TODO: Consider replacing arguments with a Builder. - private void startVpn( - String[] addresses, String[] routes, String allowedApplications, - String disallowedApplications, @Nullable ProxyInfo proxyInfo, - @Nullable ArrayList underlyingNetworks, boolean isAlwaysMetered) throws Exception { - prepareVpn(); - - // Register a callback so we will be notified when our VPN comes up. - final NetworkRequest request = new NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_VPN) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build(); - mCallback = new NetworkCallback() { - public void onAvailable(Network network) { - synchronized (mLock) { - Log.i(TAG, "Got available callback for network=" + network); - mNetwork = network; - mLock.notify(); - } - } - }; - mCM.registerNetworkCallback(request, mCallback); // Unregistered in tearDown. - - // Start the service and wait up for TIMEOUT_MS ms for the VPN to come up. - Intent intent = new Intent(mActivity, MyVpnService.class) - .putExtra(mPackageName + ".cmd", "connect") - .putExtra(mPackageName + ".addresses", TextUtils.join(",", addresses)) - .putExtra(mPackageName + ".routes", TextUtils.join(",", routes)) - .putExtra(mPackageName + ".allowedapplications", allowedApplications) - .putExtra(mPackageName + ".disallowedapplications", disallowedApplications) - .putExtra(mPackageName + ".httpProxy", proxyInfo) - .putParcelableArrayListExtra( - mPackageName + ".underlyingNetworks", underlyingNetworks) - .putExtra(mPackageName + ".isAlwaysMetered", isAlwaysMetered); - - mActivity.startService(intent); - synchronized (mLock) { - if (mNetwork == null) { - Log.i(TAG, "bf mLock"); - mLock.wait(TIMEOUT_MS); - Log.i(TAG, "af mLock"); - } - } - - if (mNetwork == null) { - fail("VPN did not become available after " + TIMEOUT_MS + "ms"); - } - - // Unfortunately, when the available callback fires, the VPN UID ranges are not yet - // configured. Give the system some time to do so. http://b/18436087 . - try { Thread.sleep(3000); } catch(InterruptedException e) {} - } - - private void stopVpn() { - // Register a callback so we will be notified when our VPN comes up. - final NetworkRequest request = new NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_VPN) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build(); - mCallback = new NetworkCallback() { - public void onLost(Network network) { - synchronized (mLockShutdown) { - Log.i(TAG, "Got lost callback for network=" + network - + ",mNetwork = " + mNetwork); - if( mNetwork == network){ - mLockShutdown.notify(); - } - } - } - }; - mCM.registerNetworkCallback(request, mCallback); // Unregistered in tearDown. - // Simply calling mActivity.stopService() won't stop the service, because the system binds - // to the service for the purpose of sending it a revoke command if another VPN comes up, - // and stopping a bound service has no effect. Instead, "start" the service again with an - // Intent that tells it to disconnect. - Intent intent = new Intent(mActivity, MyVpnService.class) - .putExtra(mPackageName + ".cmd", "disconnect"); - mActivity.startService(intent); - synchronized (mLockShutdown) { - try { - Log.i(TAG, "bf mLockShutdown"); - mLockShutdown.wait(TIMEOUT_MS); - Log.i(TAG, "af mLockShutdown"); - } catch(InterruptedException e) {} - } - } - - private static void closeQuietly(Closeable c) { - if (c != null) { - try { - c.close(); - } catch (IOException e) { - } - } - } - - private static void checkPing(String to) throws IOException, ErrnoException { - InetAddress address = InetAddress.getByName(to); - FileDescriptor s; - final int LENGTH = 64; - byte[] packet = new byte[LENGTH]; - byte[] header; - - // Construct a ping packet. - Random random = new Random(); - random.nextBytes(packet); - if (address instanceof Inet6Address) { - s = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); - header = new byte[] { (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - } else { - // Note that this doesn't actually work due to http://b/18558481 . - s = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); - header = new byte[] { (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; - } - System.arraycopy(header, 0, packet, 0, header.length); - - // Send the packet. - int port = random.nextInt(65534) + 1; - Os.connect(s, address, port); - Os.write(s, packet, 0, packet.length); - - // Expect a reply. - StructPollfd pollfd = new StructPollfd(); - pollfd.events = (short) POLLIN; // "error: possible loss of precision" - pollfd.fd = s; - int ret = Os.poll(new StructPollfd[] { pollfd }, SOCKET_TIMEOUT_MS); - assertEquals("Expected reply after sending ping", 1, ret); - - byte[] reply = new byte[LENGTH]; - int read = Os.read(s, reply, 0, LENGTH); - assertEquals(LENGTH, read); - - // Find out what the kernel set the ICMP ID to. - InetSocketAddress local = (InetSocketAddress) Os.getsockname(s); - port = local.getPort(); - packet[4] = (byte) ((port >> 8) & 0xff); - packet[5] = (byte) (port & 0xff); - - // Check the contents. - if (packet[0] == (byte) 0x80) { - packet[0] = (byte) 0x81; - } else { - packet[0] = 0; - } - // Zero out the checksum in the reply so it matches the uninitialized checksum in packet. - reply[2] = reply[3] = 0; - MoreAsserts.assertEquals(packet, reply); - } - - // Writes data to out and checks that it appears identically on in. - private static void writeAndCheckData( - OutputStream out, InputStream in, byte[] data) throws IOException { - out.write(data, 0, data.length); - out.flush(); - - byte[] read = new byte[data.length]; - int bytesRead = 0, totalRead = 0; - do { - bytesRead = in.read(read, totalRead, read.length - totalRead); - totalRead += bytesRead; - } while (bytesRead >= 0 && totalRead < data.length); - assertEquals(totalRead, data.length); - MoreAsserts.assertEquals(data, read); - } - - private void checkTcpReflection(String to, String expectedFrom) throws IOException { - // Exercise TCP over the VPN by "connecting to ourselves". We open a server socket and a - // client socket, and connect the client socket to a remote host, with the port of the - // server socket. The PacketReflector reflects the packets, changing the source addresses - // but not the ports, so our client socket is connected to our server socket, though both - // sockets think their peers are on the "remote" IP address. - - // Open a listening socket. - ServerSocket listen = new ServerSocket(0, 10, InetAddress.getByName("::")); - - // Connect the client socket to it. - InetAddress toAddr = InetAddress.getByName(to); - Socket client = new Socket(); - try { - client.connect(new InetSocketAddress(toAddr, listen.getLocalPort()), SOCKET_TIMEOUT_MS); - if (expectedFrom == null) { - closeQuietly(listen); - closeQuietly(client); - fail("Expected connection to fail, but it succeeded."); - } - } catch (IOException e) { - if (expectedFrom != null) { - closeQuietly(listen); - fail("Expected connection to succeed, but it failed."); - } else { - // We expected the connection to fail, and it did, so there's nothing more to test. - return; - } - } - - // The connection succeeded, and we expected it to succeed. Send some data; if things are - // working, the data will be sent to the VPN, reflected by the PacketReflector, and arrive - // at our server socket. For good measure, send some data in the other direction. - Socket server = null; - try { - // Accept the connection on the server side. - listen.setSoTimeout(SOCKET_TIMEOUT_MS); - server = listen.accept(); - checkConnectionOwnerUidTcp(client); - checkConnectionOwnerUidTcp(server); - // Check that the source and peer addresses are as expected. - assertEquals(expectedFrom, client.getLocalAddress().getHostAddress()); - assertEquals(expectedFrom, server.getLocalAddress().getHostAddress()); - assertEquals( - new InetSocketAddress(toAddr, client.getLocalPort()), - server.getRemoteSocketAddress()); - assertEquals( - new InetSocketAddress(toAddr, server.getLocalPort()), - client.getRemoteSocketAddress()); - - // Now write some data. - final int LENGTH = 32768; - byte[] data = new byte[LENGTH]; - new Random().nextBytes(data); - - // Make sure our writes don't block or time out, because we're single-threaded and can't - // read and write at the same time. - server.setReceiveBufferSize(LENGTH * 2); - client.setSendBufferSize(LENGTH * 2); - client.setSoTimeout(SOCKET_TIMEOUT_MS); - server.setSoTimeout(SOCKET_TIMEOUT_MS); - - // Send some data from client to server, then from server to client. - writeAndCheckData(client.getOutputStream(), server.getInputStream(), data); - writeAndCheckData(server.getOutputStream(), client.getInputStream(), data); - } finally { - closeQuietly(listen); - closeQuietly(client); - closeQuietly(server); - } - } - - private void checkConnectionOwnerUidUdp(DatagramSocket s, boolean expectSuccess) { - final int expectedUid = expectSuccess ? Process.myUid() : INVALID_UID; - InetSocketAddress loc = new InetSocketAddress(s.getLocalAddress(), s.getLocalPort()); - InetSocketAddress rem = new InetSocketAddress(s.getInetAddress(), s.getPort()); - int uid = mCM.getConnectionOwnerUid(OsConstants.IPPROTO_UDP, loc, rem); - assertEquals(expectedUid, uid); - } - - private void checkConnectionOwnerUidTcp(Socket s) { - final int expectedUid = Process.myUid(); - InetSocketAddress loc = new InetSocketAddress(s.getLocalAddress(), s.getLocalPort()); - InetSocketAddress rem = new InetSocketAddress(s.getInetAddress(), s.getPort()); - int uid = mCM.getConnectionOwnerUid(OsConstants.IPPROTO_TCP, loc, rem); - assertEquals(expectedUid, uid); - } - - private void checkUdpEcho(String to, String expectedFrom) throws IOException { - DatagramSocket s; - InetAddress address = InetAddress.getByName(to); - if (address instanceof Inet6Address) { // http://b/18094870 - s = new DatagramSocket(0, InetAddress.getByName("::")); - } else { - s = new DatagramSocket(); - } - s.setSoTimeout(SOCKET_TIMEOUT_MS); - - Random random = new Random(); - byte[] data = new byte[random.nextInt(1650)]; - random.nextBytes(data); - DatagramPacket p = new DatagramPacket(data, data.length); - s.connect(address, 7); - - if (expectedFrom != null) { - assertEquals("Unexpected source address: ", - expectedFrom, s.getLocalAddress().getHostAddress()); - } - - try { - if (expectedFrom != null) { - s.send(p); - checkConnectionOwnerUidUdp(s, true); - s.receive(p); - MoreAsserts.assertEquals(data, p.getData()); - } else { - try { - s.send(p); - s.receive(p); - fail("Received unexpected reply"); - } catch (IOException expected) { - checkConnectionOwnerUidUdp(s, false); - } - } - } finally { - s.close(); - } - } - - private void checkTrafficOnVpn() throws Exception { - checkUdpEcho("192.0.2.251", "192.0.2.2"); - checkUdpEcho("2001:db8:dead:beef::f00", "2001:db8:1:2::ffe"); - checkPing("2001:db8:dead:beef::f00"); - checkTcpReflection("192.0.2.252", "192.0.2.2"); - checkTcpReflection("2001:db8:dead:beef::f00", "2001:db8:1:2::ffe"); - } - - private void checkNoTrafficOnVpn() throws Exception { - checkUdpEcho("192.0.2.251", null); - checkUdpEcho("2001:db8:dead:beef::f00", null); - checkTcpReflection("192.0.2.252", null); - checkTcpReflection("2001:db8:dead:beef::f00", null); - } - - private FileDescriptor openSocketFd(String host, int port, int timeoutMs) throws Exception { - Socket s = new Socket(host, port); - s.setSoTimeout(timeoutMs); - // Dup the filedescriptor so ParcelFileDescriptor's finalizer doesn't garbage collect it - // and cause our fd to become invalid. http://b/35927643 . - FileDescriptor fd = Os.dup(ParcelFileDescriptor.fromSocket(s).getFileDescriptor()); - s.close(); - return fd; - } - - private FileDescriptor openSocketFdInOtherApp( - String host, int port, int timeoutMs) throws Exception { - Log.d(TAG, String.format("Creating test socket in UID=%d, my UID=%d", - mRemoteSocketFactoryClient.getUid(), Os.getuid())); - FileDescriptor fd = mRemoteSocketFactoryClient.openSocketFd(host, port, TIMEOUT_MS); - return fd; - } - - private void sendRequest(FileDescriptor fd, String host) throws Exception { - String request = "GET /generate_204 HTTP/1.1\r\n" + - "Host: " + host + "\r\n" + - "Connection: keep-alive\r\n\r\n"; - byte[] requestBytes = request.getBytes(StandardCharsets.UTF_8); - int ret = Os.write(fd, requestBytes, 0, requestBytes.length); - Log.d(TAG, "Wrote " + ret + "bytes"); - - String expected = "HTTP/1.1 204 No Content\r\n"; - byte[] response = new byte[expected.length()]; - Os.read(fd, response, 0, response.length); - - String actual = new String(response, StandardCharsets.UTF_8); - assertEquals(expected, actual); - Log.d(TAG, "Got response: " + actual); - } - - private void assertSocketStillOpen(FileDescriptor fd, String host) throws Exception { - try { - assertTrue(fd.valid()); - sendRequest(fd, host); - assertTrue(fd.valid()); - } finally { - Os.close(fd); - } - } - - private void assertSocketClosed(FileDescriptor fd, String host) throws Exception { - try { - assertTrue(fd.valid()); - sendRequest(fd, host); - fail("Socket opened before VPN connects should be closed when VPN connects"); - } catch (ErrnoException expected) { - assertEquals(ECONNABORTED, expected.errno); - assertTrue(fd.valid()); - } finally { - Os.close(fd); - } - } - - private ContentResolver getContentResolver() { - return getInstrumentation().getContext().getContentResolver(); - } - - private boolean isPrivateDnsInStrictMode() { - return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals( - Settings.Global.getString(getContentResolver(), PRIVATE_DNS_MODE_SETTING)); - } - - private void storePrivateDnsSetting() { - mOldPrivateDnsMode = Settings.Global.getString(getContentResolver(), - PRIVATE_DNS_MODE_SETTING); - mOldPrivateDnsSpecifier = Settings.Global.getString(getContentResolver(), - PRIVATE_DNS_SPECIFIER_SETTING); - } - - private void restorePrivateDnsSetting() { - Settings.Global.putString(getContentResolver(), PRIVATE_DNS_MODE_SETTING, - mOldPrivateDnsMode); - Settings.Global.putString(getContentResolver(), PRIVATE_DNS_SPECIFIER_SETTING, - mOldPrivateDnsSpecifier); - } - - // TODO: replace with CtsNetUtils.awaitPrivateDnsSetting in Q or above. - private void expectPrivateDnsHostname(final String hostname) throws Exception { - final NetworkRequest request = new NetworkRequest.Builder() - .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - .build(); - final CountDownLatch latch = new CountDownLatch(1); - final NetworkCallback callback = new NetworkCallback() { - @Override - public void onLinkPropertiesChanged(Network network, LinkProperties lp) { - if (network.equals(mNetwork) && - Objects.equals(lp.getPrivateDnsServerName(), hostname)) { - latch.countDown(); - } - } - }; - - mCM.registerNetworkCallback(request, callback); - - try { - assertTrue("Private DNS hostname was not " + hostname + " after " + TIMEOUT_MS + "ms", - latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - mCM.unregisterNetworkCallback(callback); - } - } - - private void setAndVerifyPrivateDns(boolean strictMode) throws Exception { - final ContentResolver cr = getInstrumentation().getContext().getContentResolver(); - String privateDnsHostname; - - if (strictMode) { - privateDnsHostname = "vpncts-nx.metric.gstatic.com"; - Settings.Global.putString(cr, PRIVATE_DNS_SPECIFIER_SETTING, privateDnsHostname); - Settings.Global.putString(cr, PRIVATE_DNS_MODE_SETTING, - PRIVATE_DNS_MODE_PROVIDER_HOSTNAME); - } else { - Settings.Global.putString(cr, PRIVATE_DNS_MODE_SETTING, PRIVATE_DNS_MODE_OPPORTUNISTIC); - privateDnsHostname = null; - } - - expectPrivateDnsHostname(privateDnsHostname); - - String randomName = "vpncts-" + new Random().nextInt(1000000000) + "-ds.metric.gstatic.com"; - if (strictMode) { - // Strict mode private DNS is enabled. DNS lookups should fail, because the private DNS - // server name is invalid. - try { - InetAddress.getByName(randomName); - fail("VPN DNS lookup should fail with private DNS enabled"); - } catch (UnknownHostException expected) { - } - } else { - // Strict mode private DNS is disabled. DNS lookup should succeed, because the VPN - // provides no DNS servers, and thus DNS falls through to the default network. - assertNotNull("VPN DNS lookup should succeed with private DNS disabled", - InetAddress.getByName(randomName)); - } - } - - // Tests that strict mode private DNS is used on VPNs. - private void checkStrictModePrivateDns() throws Exception { - final boolean initialMode = isPrivateDnsInStrictMode(); - setAndVerifyPrivateDns(!initialMode); - setAndVerifyPrivateDns(initialMode); - } - - public void testDefault() throws Exception { - if (!supportedHardware()) return; - // If adb TCP port opened, this test may running by adb over network. - // All of socket would be destroyed in this test. So this test don't - // support adb over network, see b/119382723. - if (SystemProperties.getInt("persist.adb.tcp.port", -1) > -1 - || SystemProperties.getInt("service.adb.tcp.port", -1) > -1) { - Log.i(TAG, "adb is running over the network, so skip this test"); - return; - } - - final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver( - getInstrumentation().getTargetContext(), MyVpnService.ACTION_ESTABLISHED); - receiver.register(); - - FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS); - - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, - "", "", null, null /* underlyingNetworks */, false /* isAlwaysMetered */); - - final Intent intent = receiver.awaitForBroadcast(TimeUnit.MINUTES.toMillis(1)); - assertNotNull("Failed to receive broadcast from VPN service", intent); - assertFalse("Wrong VpnService#isAlwaysOn", - intent.getBooleanExtra(MyVpnService.EXTRA_ALWAYS_ON, true)); - assertFalse("Wrong VpnService#isLockdownEnabled", - intent.getBooleanExtra(MyVpnService.EXTRA_LOCKDOWN_ENABLED, true)); - - assertSocketClosed(fd, TEST_HOST); - - checkTrafficOnVpn(); - - checkStrictModePrivateDns(); - - receiver.unregisterQuietly(); - } - - public void testAppAllowed() throws Exception { - if (!supportedHardware()) return; - - FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS); - - // Shell app must not be put in here or it would kill the ADB-over-network use case - String allowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName; - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"192.0.2.0/24", "2001:db8::/32"}, - allowedApps, "", null, null /* underlyingNetworks */, false /* isAlwaysMetered */); - - assertSocketClosed(fd, TEST_HOST); - - checkTrafficOnVpn(); - - checkStrictModePrivateDns(); - } - - public void testAppDisallowed() throws Exception { - if (!supportedHardware()) return; - - FileDescriptor localFd = openSocketFd(TEST_HOST, 80, TIMEOUT_MS); - FileDescriptor remoteFd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS); - - String disallowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName; - // If adb TCP port opened, this test may running by adb over TCP. - // Add com.android.shell appllication into blacklist to exclude adb socket for VPN test, - // see b/119382723. - // Note: The test don't support running adb over network for root device - disallowedApps = disallowedApps + ",com.android.shell"; - Log.i(TAG, "Append shell app to disallowedApps: " + disallowedApps); - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"192.0.2.0/24", "2001:db8::/32"}, - "", disallowedApps, null, null /* underlyingNetworks */, - false /* isAlwaysMetered */); - - assertSocketStillOpen(localFd, TEST_HOST); - assertSocketStillOpen(remoteFd, TEST_HOST); - - checkNoTrafficOnVpn(); - } - - public void testGetConnectionOwnerUidSecurity() throws Exception { - if (!supportedHardware()) return; - - DatagramSocket s; - InetAddress address = InetAddress.getByName("localhost"); - s = new DatagramSocket(); - s.setSoTimeout(SOCKET_TIMEOUT_MS); - s.connect(address, 7); - InetSocketAddress loc = new InetSocketAddress(s.getLocalAddress(), s.getLocalPort()); - InetSocketAddress rem = new InetSocketAddress(s.getInetAddress(), s.getPort()); - try { - int uid = mCM.getConnectionOwnerUid(OsConstants.IPPROTO_TCP, loc, rem); - fail("Only an active VPN app may call this API."); - } catch (SecurityException expected) { - return; - } - } - - public void testSetProxy() throws Exception { - if (!supportedHardware()) return; - ProxyInfo initialProxy = mCM.getDefaultProxy(); - // Receiver for the proxy change broadcast. - BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver(); - proxyBroadcastReceiver.register(); - - String allowedApps = mPackageName; - ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("10.0.0.1", 8888); - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "", - testProxyInfo, null /* underlyingNetworks */, false /* isAlwaysMetered */); - - // Check that the proxy change broadcast is received - try { - assertNotNull("No proxy change was broadcast when VPN is connected.", - proxyBroadcastReceiver.awaitForBroadcast()); - } finally { - proxyBroadcastReceiver.unregisterQuietly(); - } - - // Proxy is set correctly in network and in link properties. - assertNetworkHasExpectedProxy(testProxyInfo, mNetwork); - assertDefaultProxy(testProxyInfo); - - proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver(); - proxyBroadcastReceiver.register(); - stopVpn(); - try { - assertNotNull("No proxy change was broadcast when VPN was disconnected.", - proxyBroadcastReceiver.awaitForBroadcast()); - } finally { - proxyBroadcastReceiver.unregisterQuietly(); - } - - // After disconnecting from VPN, the proxy settings are the ones of the initial network. - assertDefaultProxy(initialProxy); - } - - public void testSetProxyDisallowedApps() throws Exception { - if (!supportedHardware()) return; - ProxyInfo initialProxy = mCM.getDefaultProxy(); - - // If adb TCP port opened, this test may running by adb over TCP. - // Add com.android.shell appllication into blacklist to exclude adb socket for VPN test, - // see b/119382723. - // Note: The test don't support running adb over network for root device - String disallowedApps = mPackageName + ",com.android.shell"; - ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("10.0.0.1", 8888); - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, "", disallowedApps, - testProxyInfo, null /* underlyingNetworks */, false /* isAlwaysMetered */); - - // The disallowed app does has the proxy configs of the default network. - assertNetworkHasExpectedProxy(initialProxy, mCM.getActiveNetwork()); - assertDefaultProxy(initialProxy); - } - - public void testNoProxy() throws Exception { - if (!supportedHardware()) return; - ProxyInfo initialProxy = mCM.getDefaultProxy(); - BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver(); - proxyBroadcastReceiver.register(); - String allowedApps = mPackageName; - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "", null, - null /* underlyingNetworks */, false /* isAlwaysMetered */); - - try { - assertNotNull("No proxy change was broadcast.", - proxyBroadcastReceiver.awaitForBroadcast()); - } finally { - proxyBroadcastReceiver.unregisterQuietly(); - } - - // The VPN network has no proxy set. - assertNetworkHasExpectedProxy(null, mNetwork); - - proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver(); - proxyBroadcastReceiver.register(); - stopVpn(); - try { - assertNotNull("No proxy change was broadcast.", - proxyBroadcastReceiver.awaitForBroadcast()); - } finally { - proxyBroadcastReceiver.unregisterQuietly(); - } - // After disconnecting from VPN, the proxy settings are the ones of the initial network. - assertDefaultProxy(initialProxy); - assertNetworkHasExpectedProxy(initialProxy, mCM.getActiveNetwork()); - } - - public void testBindToNetworkWithProxy() throws Exception { - if (!supportedHardware()) return; - String allowedApps = mPackageName; - Network initialNetwork = mCM.getActiveNetwork(); - ProxyInfo initialProxy = mCM.getDefaultProxy(); - ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("10.0.0.1", 8888); - // Receiver for the proxy change broadcast. - BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver(); - proxyBroadcastReceiver.register(); - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "", - testProxyInfo, null /* underlyingNetworks */, false /* isAlwaysMetered */); - - assertDefaultProxy(testProxyInfo); - mCM.bindProcessToNetwork(initialNetwork); - try { - assertNotNull("No proxy change was broadcast.", - proxyBroadcastReceiver.awaitForBroadcast()); - } finally { - proxyBroadcastReceiver.unregisterQuietly(); - } - assertDefaultProxy(initialProxy); - } - - public void testVpnMeterednessWithNoUnderlyingNetwork() throws Exception { - if (!supportedHardware()) { - return; - } - // VPN is not routing any traffic i.e. its underlying networks is an empty array. - ArrayList underlyingNetworks = new ArrayList<>(); - String allowedApps = mPackageName; - - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "", null, - underlyingNetworks, false /* isAlwaysMetered */); - - // VPN should now be the active network. - assertEquals(mNetwork, mCM.getActiveNetwork()); - assertVpnTransportContains(NetworkCapabilities.TRANSPORT_VPN); - // VPN with no underlying networks should be metered by default. - assertTrue(isNetworkMetered(mNetwork)); - assertTrue(mCM.isActiveNetworkMetered()); - } - - public void testVpnMeterednessWithNullUnderlyingNetwork() throws Exception { - if (!supportedHardware()) { - return; - } - Network underlyingNetwork = mCM.getActiveNetwork(); - if (underlyingNetwork == null) { - Log.i(TAG, "testVpnMeterednessWithNullUnderlyingNetwork cannot execute" - + " unless there is an active network"); - return; - } - // VPN tracks platform default. - ArrayList underlyingNetworks = null; - String allowedApps = mPackageName; - - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "", null, - underlyingNetworks, false /*isAlwaysMetered */); - - // Ensure VPN transports contains underlying network's transports. - assertVpnTransportContains(underlyingNetwork); - // Its meteredness should be same as that of underlying network. - assertEquals(isNetworkMetered(underlyingNetwork), isNetworkMetered(mNetwork)); - // Meteredness based on VPN capabilities and CM#isActiveNetworkMetered should be in sync. - assertEquals(isNetworkMetered(mNetwork), mCM.isActiveNetworkMetered()); - } - - public void testVpnMeterednessWithNonNullUnderlyingNetwork() throws Exception { - if (!supportedHardware()) { - return; - } - Network underlyingNetwork = mCM.getActiveNetwork(); - if (underlyingNetwork == null) { - Log.i(TAG, "testVpnMeterednessWithNonNullUnderlyingNetwork cannot execute" - + " unless there is an active network"); - return; - } - // VPN explicitly declares WiFi to be its underlying network. - ArrayList underlyingNetworks = new ArrayList<>(1); - underlyingNetworks.add(underlyingNetwork); - String allowedApps = mPackageName; - - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "", null, - underlyingNetworks, false /* isAlwaysMetered */); - - // Ensure VPN transports contains underlying network's transports. - assertVpnTransportContains(underlyingNetwork); - // Its meteredness should be same as that of underlying network. - assertEquals(isNetworkMetered(underlyingNetwork), isNetworkMetered(mNetwork)); - // Meteredness based on VPN capabilities and CM#isActiveNetworkMetered should be in sync. - assertEquals(isNetworkMetered(mNetwork), mCM.isActiveNetworkMetered()); - } - - public void testAlwaysMeteredVpnWithNullUnderlyingNetwork() throws Exception { - if (!supportedHardware()) { - return; - } - Network underlyingNetwork = mCM.getActiveNetwork(); - if (underlyingNetwork == null) { - Log.i(TAG, "testAlwaysMeteredVpnWithNullUnderlyingNetwork cannot execute" - + " unless there is an active network"); - return; - } - // VPN tracks platform default. - ArrayList underlyingNetworks = null; - String allowedApps = mPackageName; - boolean isAlwaysMetered = true; - - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "", null, - underlyingNetworks, isAlwaysMetered); - - // VPN's meteredness does not depend on underlying network since it is always metered. - assertTrue(isNetworkMetered(mNetwork)); - assertTrue(mCM.isActiveNetworkMetered()); - } - - public void testAlwaysMeteredVpnWithNonNullUnderlyingNetwork() throws Exception { - if (!supportedHardware()) { - return; - } - Network underlyingNetwork = mCM.getActiveNetwork(); - if (underlyingNetwork == null) { - Log.i(TAG, "testAlwaysMeteredVpnWithNonNullUnderlyingNetwork cannot execute" - + " unless there is an active network"); - return; - } - // VPN explicitly declares its underlying network. - ArrayList underlyingNetworks = new ArrayList<>(1); - underlyingNetworks.add(underlyingNetwork); - String allowedApps = mPackageName; - boolean isAlwaysMetered = true; - - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "", null, - underlyingNetworks, isAlwaysMetered); - - // VPN's meteredness does not depend on underlying network since it is always metered. - assertTrue(isNetworkMetered(mNetwork)); - assertTrue(mCM.isActiveNetworkMetered()); - } - - public void testB141603906() throws Exception { - final InetSocketAddress src = new InetSocketAddress(0); - final InetSocketAddress dst = new InetSocketAddress(0); - final int NUM_THREADS = 8; - final int NUM_SOCKETS = 5000; - final Thread[] threads = new Thread[NUM_THREADS]; - startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"}, - new String[] {"0.0.0.0/0", "::/0"}, - "" /* allowedApplications */, "com.android.shell" /* disallowedApplications */, - null /* proxyInfo */, null /* underlyingNetworks */, false /* isAlwaysMetered */); - - for (int i = 0; i < NUM_THREADS; i++) { - threads[i] = new Thread(() -> { - for (int j = 0; j < NUM_SOCKETS; j++) { - mCM.getConnectionOwnerUid(IPPROTO_TCP, src, dst); - } - }); - } - for (Thread thread : threads) { - thread.start(); - } - for (Thread thread : threads) { - thread.join(); - } - stopVpn(); - } - - private boolean isNetworkMetered(Network network) { - NetworkCapabilities nc = mCM.getNetworkCapabilities(network); - return !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - } - - private void assertVpnTransportContains(Network underlyingNetwork) { - int[] transports = mCM.getNetworkCapabilities(underlyingNetwork).getTransportTypes(); - assertVpnTransportContains(transports); - } - - private void assertVpnTransportContains(int... transports) { - NetworkCapabilities vpnCaps = mCM.getNetworkCapabilities(mNetwork); - for (int transport : transports) { - assertTrue(vpnCaps.hasTransport(transport)); - } - } - - private void assertDefaultProxy(ProxyInfo expected) { - assertEquals("Incorrect proxy config.", expected, mCM.getDefaultProxy()); - String expectedHost = expected == null ? null : expected.getHost(); - String expectedPort = expected == null ? null : String.valueOf(expected.getPort()); - assertEquals("Incorrect proxy host system property.", expectedHost, - System.getProperty("http.proxyHost")); - assertEquals("Incorrect proxy port system property.", expectedPort, - System.getProperty("http.proxyPort")); - } - - private void assertNetworkHasExpectedProxy(ProxyInfo expected, Network network) { - LinkProperties lp = mCM.getLinkProperties(network); - assertNotNull("The network link properties object is null.", lp); - assertEquals("Incorrect proxy config.", expected, lp.getHttpProxy()); - - assertEquals(expected, mCM.getProxyForNetwork(network)); - } - - class ProxyChangeBroadcastReceiver extends BlockingBroadcastReceiver { - private boolean received; - - public ProxyChangeBroadcastReceiver() { - super(VpnTest.this.getInstrumentation().getContext(), Proxy.PROXY_CHANGE_ACTION); - received = false; - } - - @Override - public void onReceive(Context context, Intent intent) { - if (!received) { - // Do not call onReceive() more than once. - super.onReceive(context, intent); - } - received = true; - } - } -} diff --git a/tests/cts/hostside/app2/Android.bp b/tests/cts/hostside/app2/Android.bp deleted file mode 100644 index a6e9b118ff..0000000000 --- a/tests/cts/hostside/app2/Android.bp +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -android_test_helper_app { - name: "CtsHostsideNetworkTestsApp2", - defaults: ["cts_support_defaults"], - sdk_version: "current", - static_libs: ["CtsHostsideNetworkTestsAidl"], - srcs: ["src/**/*.java"], - // Tag this module as a cts test artifact - test_suites: [ - "cts", - "vts10", - "general-tests", - ], - certificate: ":cts-net-app", -} diff --git a/tests/cts/hostside/app2/AndroidManifest.xml b/tests/cts/hostside/app2/AndroidManifest.xml deleted file mode 100644 index ad270b3170..0000000000 --- a/tests/cts/hostside/app2/AndroidManifest.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/cts/hostside/app2/res/drawable/ic_notification.png b/tests/cts/hostside/app2/res/drawable/ic_notification.png deleted file mode 100644 index 6ae570b4db4da165fada0650079061cb56aa8793..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3777 zcmV;y4nFaTP)<5O4m2Hnvj*wc>ks?G z2G34C@E_ZLZKgG#r9IGlue=QUde;x0&cEf}-^JJmm+rK2tvlk-Rei)^T;Dlp|J|h@ z^m+gPwY2+#Jp|DwyKZ{cr#D)vv<3?RYtkmp$A#M_scJjzTH4xNh5}{7UZcq4B{H*L zAbrC#D0V!CY|}%?3-2R&-YsP7u%Pze_gYZ0)AsviO2LRhr%`gXg-+>Ct8*6~gsguK z#ocE}dD{&cL$1D$Nahk|Gw0#KoMAkBPxj3Dsk7U=vbNLla&#_VG^p9{qm1aoZlq4X z^Cs&0V~Cl@NMI=QP@|Gq(}0&K#8vp=Jm%rVTTdK%=7x@k&di334&4O8uk5(sqd^Q_ zOZx$2J`a)j^giNo8q0Qj^e(~C7xVD# zBMhtX326_pU@IUwD0ag^9a#=8X??`t?%Wdb?IN60 zFU5H#fIN^s2jJ9e3jX;b?0@8i_S^2*cGVr<-K)a(^8r}3&jQ&SjUUMBc)a)44{XT~ zKlMpG`6^Vs@6j}zdy)c%>BZfb9XR-87LGiduL=0*b8mD$U4(;==VR}EFYLPIfh||3 zVcW$8=vDXN$A_m-+HT1LV5F7&O24xA)DN34P8+uS&iwD&Z+kG?ZaSg;#ynhn(2U*J z7o+`-JNDe0iH`fTu;=b9%D4zSZ+fEb+6-*E=!SLQIb-b!2XtJJqGfL^@-~|yYrPpH zDuess3cWG!rE%Avcd_4iaawO{mmOL!+JO`WtzC|EbjIc@u9RgrY^6+ZxiSr#F1cYt z*Hq9wXgcGBHOK8yeb|PmV}+va76iZo87&rwFVj~C$j1Kv_X7KXwa2GL)gQN2uQ_Rr zhSN5hW^6noMAKP&G@o-s%Q+|V$!I=1Src^QDMwA@bUv3^5H)(M zP^vZL9y0!PAE}eBBhux_lLe!GGl+Xg{I`3M7LZhacjB4%!EKjCzGcV#KFV+LG)%3v zI;ND*|Lq0kdwSp$Z!~oArwQR+?+d_E@5L2TL6@q&1o#akT(Z zndVr!!swDu+<3e83k&~x@|pkk9~tTM6EElYY`)@nyKIl?+yR4VyX-Qw{l?suT{mZ{ z*(PoMemYaUV^Z&mLId~RH+*9o4=!dxr6P}$-AS-}?D(>a?2OwLAAWHcK?T+U+_$Bd0H+2K@Gd&HJ$ zK4(wOI~lDPoJn0=(R6Yu>N}^R`de32>~TT)&M7Evb3nlsA@Vj^BY(3Mxh3+qS|V?Y zS)T$?52Vx^VMU=nGe2_lzTo7E%M}fVOhKEu=9<*CMoe%rr^|hz&R+)vpssD+Kj*gE zoK!aQ8D*m(lI!@IMw`3ro0N>T_T||djOZc8DBfj?(%oh#?=Xj|!-6<&si6w1GO7+M zjn0?06YqERQKxVl%Y9R1t~VwM89`oa2yq!7%hL^**`d070_B|8lzKkH2G1srz%hZc z-vXeM1z>wp(O|$R*76~zMvKYkFkT_Lsj1cWuKetqCS~lPR({m>_c<1>YplWIm~qkCnxIgemozS;3?C_$TSDl-C+CIqbEq zCX_fsCQz<-ZtC0-|1ux|s}J~mn%!!9EOm_mLm5F*l>q_Z!7FrBUUG$9S?XE?CUcz; zh+W9jM#wgUl9lC@J$q4J1?cr4@Xv zC^A5pf=2*!cl(LQ$CD~ia@YZ9!d8g!mvYVuy$9F>H9HpkDSMspa7w*ClU!#&57I|; z9v8DiM&-*^2@8_z^qKT#L$FoI-DHfStwL-&CZ*-U8CoX1!GAY~{=Iqo3RiC*M)Te% zDA$;id>WDp5j6|+5t7PNb`n)s9@BLZQJyhcxS9^XxCB1Yr?ld~MQ3=p1X3Q^FgE&dXYoUL}|I+_tJ#&iuIehCwfO`ksO(*Xf!Iu!m%R*UUE zc`c7&Ga^~VLu3w@nG>d4k)*QEOswKDiUvL{1B{Tj(Hi$2Uqb!HG^7>#;p~OOc=P79 zChz@$_w>BNkrTU-kg)*u>vM4V`UyzNjY!!H2ml`u>60+if7F(xV!hNvs&+;T+b6~v ziUmjwjtWJ?|2$v-+3W20CROujrO0C?6cJe*mZud`l`u20g3C~UKtrST7I@TsLlfxT zpRS;)H68_3;ka<=6nb9w;KbH)cE1ndBo=P5nsyo76C}JWC3gl zkZ|)7R`ck4S(P$IA`2jqf51ZY)h7cRWNo2CvsxUsCspx?K0I1%ar*#-=vF6`StTc| z=4yI_)CgJY`T+DB+q^gKoI_DyrXeZ{?DVDlFg` zpxfl1z|Bn{y0R*zXb@;9=AXddKX3q-^M_`)IJ8MCx%4Gm#FcQdJVTF}6FhpYq}WnU z=NLKl1}m|d&F23FK!4Ld>HZ1%bv}6cs{5C~`|aAz?+}rx&kisGV2EW3a}9tc@#FJY zx+*F7)U^UyW)lFh;cgcft)T+~P9Ff+?0|L;|Asv#_;@FTt0OHFyh%M6701yR@XhM%MVnb5s%)PZNAfoq&3TkEL;fEkdEzkO3~En?B5L zajKC}rsGQW5L2Ls5XCsgGjK$Mq}V!vK&jd0me&$r8_e+V>GgNy^9cdSsd^Ux+r$@t z1`w6QLrks(A{4f8U!q&(C*hQd2|!A{fWF%Z@g;^#fY_p$Li%998y97*V@6yFM;%+J zhsf-S2uK>I_E@4@oT74;usf*43Le-QL9+r%l?Z3fANpB7e+8iO*8mv2eobTfXUy;&SFz++{h$;;GQAtS4_Vq$VFUj<3*L;5#51F~?1#Tb8y zL3@D2^r?3g|EcHFi5)Jpzy7AMc}bkC!m1Ad^#NOjxKa*H%yGz41rWbaX%y#4_d^YU zS3S>YfW0Mvhat=L#{BRx@Jk$z@C-IFEC35cE8XDk!zmX^g+n5;Y^E!#yej1?&-!I4 z*7HL{U55VF4Vm_IpYfm03*qrZemoxgSt^x&P}~w2oLp(ECMgBm2W%DCBg%Eu?1ZCOGtXt46rC#51~p{aY#0c z`aGt9nm3n+@Jucu(`^teae7Gt>w0my z;V&Ln!n%O8UVy%9OsOf&5Lax5m^@RWkO0AQV|HnW#zhVNjC5 z&QD@+Hdsah<~Spv&<&Cz7l@0TATD-5La7szST==8DxV7Zs{bJOfUMjT(h?8E<+;)F z!Txoy+^oY-%AX;UzQ^EytyJMjQ?gy>e-5`rU&AY8B9^Q)L6}^K6uFI2=56;OsRLQ@nJU84FF?X+ZtcpuQhaRJtXG zD#wv5j=}th(WK?Nm^^zVY^Qx)p{04H1a1Eam)SPchpC-reSv9~ID z7K0BUr^!7&reGoynL827)AeXt>rs#sFm=wD@_tQ^l)HO)28`%k7(JSHS2WS3T=>T6 zVPTl%AOoP_((0%B#uRYWQ3QY;PNAthc*p87(-(~w_s@@*G!OGdG2?n@Z;MccKEjmj zCWXg%N1Cl3@FMN^ww3wT!Rl3Nx>pqNmCoPihHyw&svtvB z==>~sl?Ri&TGShnW^;H!%-D(l5HGuff;fK;5F6Qtr8xR6OL27eUe15#ClL1K1%cH| ruJZJht7Zygm5zVW`osRPe+>Ii)X|D+8y7?e00000NkvXXu0mjf#L-I; diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java deleted file mode 100644 index 351733edc5..0000000000 --- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/Common.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside.app2; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.RemoteException; -import android.util.Log; - -import com.android.cts.net.hostside.INetworkStateObserver; - -public final class Common { - - static final String TAG = "CtsNetApp2"; - - // Constants below must match values defined on app's - // AbstractRestrictBackgroundNetworkTestCase.java - static final String MANIFEST_RECEIVER = "ManifestReceiver"; - static final String DYNAMIC_RECEIVER = "DynamicReceiver"; - - static final String ACTION_RECEIVER_READY = - "com.android.cts.net.hostside.app2.action.RECEIVER_READY"; - static final String ACTION_FINISH_ACTIVITY = - "com.android.cts.net.hostside.app2.action.FINISH_ACTIVITY"; - static final String ACTION_SHOW_TOAST = - "com.android.cts.net.hostside.app2.action.SHOW_TOAST"; - - static final String NOTIFICATION_TYPE_CONTENT = "CONTENT"; - static final String NOTIFICATION_TYPE_DELETE = "DELETE"; - static final String NOTIFICATION_TYPE_FULL_SCREEN = "FULL_SCREEN"; - static final String NOTIFICATION_TYPE_BUNDLE = "BUNDLE"; - static final String NOTIFICATION_TYPE_ACTION = "ACTION"; - static final String NOTIFICATION_TYPE_ACTION_BUNDLE = "ACTION_BUNDLE"; - static final String NOTIFICATION_TYPE_ACTION_REMOTE_INPUT = "ACTION_REMOTE_INPUT"; - - static final String TEST_PKG = "com.android.cts.net.hostside"; - static final String KEY_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer"; - - static int getUid(Context context) { - final String packageName = context.getPackageName(); - try { - return context.getPackageManager().getPackageUid(packageName, 0); - } catch (NameNotFoundException e) { - throw new IllegalStateException("Could not get UID for " + packageName, e); - } - } - - static void notifyNetworkStateObserver(Context context, Intent intent) { - if (intent == null) { - return; - } - final Bundle extras = intent.getExtras(); - if (extras == null) { - return; - } - final INetworkStateObserver observer = INetworkStateObserver.Stub.asInterface( - extras.getBinder(KEY_NETWORK_STATE_OBSERVER)); - if (observer != null) { - try { - if (!observer.isForeground()) { - Log.e(TAG, "App didn't come to foreground"); - observer.onNetworkStateChecked(null); - return; - } - } catch (RemoteException e) { - Log.e(TAG, "Error occurred while reading the proc state: " + e); - } - AsyncTask.execute(() -> { - try { - observer.onNetworkStateChecked( - MyBroadcastReceiver.checkNetworkStatus(context)); - } catch (RemoteException e) { - Log.e(TAG, "Error occurred while notifying the observer: " + e); - } - }); - } - } -} diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java deleted file mode 100644 index 286cc2fb56..0000000000 --- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside.app2; - -import static com.android.cts.net.hostside.app2.Common.ACTION_FINISH_ACTIVITY; -import static com.android.cts.net.hostside.app2.Common.TAG; -import static com.android.cts.net.hostside.app2.Common.TEST_PKG; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.RemoteException; -import android.util.Log; - -import com.android.cts.net.hostside.INetworkStateObserver; - -/** - * Activity used to bring process to foreground. - */ -public class MyActivity extends Activity { - - private BroadcastReceiver finishCommandReceiver = null; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Log.d(TAG, "MyActivity.onCreate()"); - Common.notifyNetworkStateObserver(this, getIntent()); - finishCommandReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Log.d(TAG, "Finishing MyActivity"); - MyActivity.this.finish(); - } - }; - registerReceiver(finishCommandReceiver, new IntentFilter(ACTION_FINISH_ACTIVITY)); - } - - @Override - public void finish() { - if (finishCommandReceiver != null) { - unregisterReceiver(finishCommandReceiver); - } - super.finish(); - } - - @Override - protected void onStart() { - super.onStart(); - Log.d(TAG, "MyActivity.onStart()"); - } - - @Override - protected void onDestroy() { - Log.d(TAG, "MyActivity.onDestroy()"); - super.onDestroy(); - } -} diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java deleted file mode 100644 index aa54075783..0000000000 --- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyBroadcastReceiver.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside.app2; - -import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED; - -import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY; -import static com.android.cts.net.hostside.app2.Common.ACTION_SHOW_TOAST; -import static com.android.cts.net.hostside.app2.Common.MANIFEST_RECEIVER; -import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION; -import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION_BUNDLE; -import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_ACTION_REMOTE_INPUT; -import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_BUNDLE; -import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_CONTENT; -import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_DELETE; -import static com.android.cts.net.hostside.app2.Common.NOTIFICATION_TYPE_FULL_SCREEN; -import static com.android.cts.net.hostside.app2.Common.TAG; -import static com.android.cts.net.hostside.app2.Common.getUid; - -import android.app.Notification; -import android.app.Notification.Action; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.RemoteInput; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.os.Bundle; -import android.util.Log; -import android.widget.Toast; - -import java.net.HttpURLConnection; -import java.net.URL; - -/** - * Receiver used to: - *

    - *
  1. Count number of {@code RESTRICT_BACKGROUND_CHANGED} broadcasts received. - *
  2. Show a toast. - *
- */ -public class MyBroadcastReceiver extends BroadcastReceiver { - - private static final int NETWORK_TIMEOUT_MS = 5 * 1000; - - private final String mName; - - public MyBroadcastReceiver() { - this(MANIFEST_RECEIVER); - } - - MyBroadcastReceiver(String name) { - Log.d(TAG, "Constructing MyBroadcastReceiver named " + name); - mName = name; - } - - @Override - public void onReceive(Context context, Intent intent) { - Log.d(TAG, "onReceive() for " + mName + ": " + intent); - final String action = intent.getAction(); - switch (action) { - case ACTION_RESTRICT_BACKGROUND_CHANGED: - increaseCounter(context, action); - break; - case ACTION_RECEIVER_READY: - final String message = mName + " is ready to rumble"; - Log.d(TAG, message); - setResultData(message); - break; - case ACTION_SHOW_TOAST: - showToast(context); - break; - default: - Log.e(TAG, "received unexpected action: " + action); - } - } - - @Override - public String toString() { - return "[MyBroadcastReceiver: mName=" + mName + "]"; - } - - private void increaseCounter(Context context, String action) { - final SharedPreferences prefs = context.getApplicationContext() - .getSharedPreferences(mName, Context.MODE_PRIVATE); - final int value = prefs.getInt(action, 0) + 1; - Log.d(TAG, "increaseCounter('" + action + "'): setting '" + mName + "' to " + value); - prefs.edit().putInt(action, value).apply(); - } - - static int getCounter(Context context, String action, String receiverName) { - final SharedPreferences prefs = context.getSharedPreferences(receiverName, - Context.MODE_PRIVATE); - final int value = prefs.getInt(action, 0); - Log.d(TAG, "getCounter('" + action + "', '" + receiverName + "'): " + value); - return value; - } - - static String getRestrictBackgroundStatus(Context context) { - final ConnectivityManager cm = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - final int apiStatus = cm.getRestrictBackgroundStatus(); - Log.d(TAG, "getRestrictBackgroundStatus: returning " + apiStatus); - return String.valueOf(apiStatus); - } - - private static final String NETWORK_STATUS_TEMPLATE = "%s|%s|%s|%s|%s"; - /** - * Checks whether the network is available and return a string which can then be send as a - * result data for the ordered broadcast. - * - *

- * The string has the following format: - * - *


-     * NetinfoState|NetinfoDetailedState|RealConnectionCheck|RealConnectionCheckDetails|Netinfo
-     * 
- * - *

Where: - * - *

- * - * For example, if the connection was established fine, the result would be something like: - *


-     * CONNECTED|CONNECTED|true|200|[type: WIFI[], state: CONNECTED/CONNECTED, reason: ...]
-     * 
- * - */ - // TODO: now that it uses Binder, it counl return a Bundle with the data parts instead... - static String checkNetworkStatus(Context context) { - final ConnectivityManager cm = - (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - // TODO: connect to a hostside server instead - final String address = "http://example.com"; - final NetworkInfo networkInfo = cm.getActiveNetworkInfo(); - Log.d(TAG, "Running checkNetworkStatus() on thread " - + Thread.currentThread().getName() + " for UID " + getUid(context) - + "\n\tactiveNetworkInfo: " + networkInfo + "\n\tURL: " + address); - boolean checkStatus = false; - String checkDetails = "N/A"; - try { - final URL url = new URL(address); - final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setReadTimeout(NETWORK_TIMEOUT_MS); - conn.setConnectTimeout(NETWORK_TIMEOUT_MS / 2); - conn.setRequestMethod("GET"); - conn.setDoInput(true); - conn.connect(); - final int response = conn.getResponseCode(); - checkStatus = true; - checkDetails = "HTTP response for " + address + ": " + response; - } catch (Exception e) { - checkStatus = false; - checkDetails = "Exception getting " + address + ": " + e; - } - Log.d(TAG, checkDetails); - final String state, detailedState; - if (networkInfo != null) { - state = networkInfo.getState().name(); - detailedState = networkInfo.getDetailedState().name(); - } else { - state = detailedState = "null"; - } - final String status = String.format(NETWORK_STATUS_TEMPLATE, state, detailedState, - Boolean.valueOf(checkStatus), checkDetails, networkInfo); - Log.d(TAG, "Offering " + status); - return status; - } - - /** - * Sends a system notification containing actions with pending intents to launch the app's - * main activitiy or service. - */ - static void sendNotification(Context context, String channelId, int notificationId, - String notificationType ) { - Log.d(TAG, "sendNotification: id=" + notificationId + ", type=" + notificationType); - final Intent serviceIntent = new Intent(context, MyService.class); - final PendingIntent pendingIntent = PendingIntent.getService(context, 0, serviceIntent, - notificationId); - final Bundle bundle = new Bundle(); - bundle.putCharSequence("parcelable", "I am not"); - - final Notification.Builder builder = new Notification.Builder(context, channelId) - .setSmallIcon(R.drawable.ic_notification); - - Action action = null; - switch (notificationType) { - case NOTIFICATION_TYPE_CONTENT: - builder - .setContentTitle("Light, Cameras...") - .setContentIntent(pendingIntent); - break; - case NOTIFICATION_TYPE_DELETE: - builder.setDeleteIntent(pendingIntent); - break; - case NOTIFICATION_TYPE_FULL_SCREEN: - builder.setFullScreenIntent(pendingIntent, true); - break; - case NOTIFICATION_TYPE_BUNDLE: - bundle.putParcelable("Magnum P.I. (Pending Intent)", pendingIntent); - builder.setExtras(bundle); - break; - case NOTIFICATION_TYPE_ACTION: - action = new Action.Builder( - R.drawable.ic_notification, "ACTION", pendingIntent) - .build(); - builder.addAction(action); - break; - case NOTIFICATION_TYPE_ACTION_BUNDLE: - bundle.putParcelable("Magnum A.P.I. (Action Pending Intent)", pendingIntent); - action = new Action.Builder( - R.drawable.ic_notification, "ACTION WITH BUNDLE", null) - .addExtras(bundle) - .build(); - builder.addAction(action); - break; - case NOTIFICATION_TYPE_ACTION_REMOTE_INPUT: - bundle.putParcelable("Magnum R.I. (Remote Input)", null); - final RemoteInput remoteInput = new RemoteInput.Builder("RI") - .addExtras(bundle) - .build(); - action = new Action.Builder( - R.drawable.ic_notification, "ACTION WITH REMOTE INPUT", pendingIntent) - .addRemoteInput(remoteInput) - .build(); - builder.addAction(action); - break; - default: - Log.e(TAG, "Unknown notification type: " + notificationType); - return; - } - - final Notification notification = builder.build(); - ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)) - .notify(notificationId, notification); - } - - private void showToast(Context context) { - Toast.makeText(context, "Toast from CTS test", Toast.LENGTH_SHORT).show(); - setResultData("Shown"); - } -} diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java deleted file mode 100644 index ff4ba656b1..0000000000 --- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside.app2; - -import static com.android.cts.net.hostside.app2.Common.TAG; -import static com.android.cts.net.hostside.app2.Common.TEST_PKG; - -import android.R; -import android.app.Notification; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.Service; -import android.content.Intent; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -import com.android.cts.net.hostside.INetworkStateObserver; - -/** - * Service used to change app state to FOREGROUND_SERVICE. - */ -public class MyForegroundService extends Service { - private static final String NOTIFICATION_CHANNEL_ID = "cts/MyForegroundService"; - private static final int FLAG_START_FOREGROUND = 1; - private static final int FLAG_STOP_FOREGROUND = 2; - - @Override - public IBinder onBind(Intent intent) { - return null; - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Log.v(TAG, "MyForegroundService.onStartCommand(): " + intent); - NotificationManager notificationManager = getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(new NotificationChannel( - NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID, - NotificationManager.IMPORTANCE_DEFAULT)); - switch (intent.getFlags()) { - case FLAG_START_FOREGROUND: - Log.d(TAG, "Starting foreground"); - startForeground(42, new Notification.Builder(this, NOTIFICATION_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_dialog_alert) // any icon is fine - .build()); - Common.notifyNetworkStateObserver(this, intent); - break; - case FLAG_STOP_FOREGROUND: - Log.d(TAG, "Stopping foreground"); - stopForeground(true); - break; - default: - Log.wtf(TAG, "Invalid flag on intent " + intent); - } - return START_STICKY; - } -} diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java deleted file mode 100644 index 590e17e5e5..0000000000 --- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.net.hostside.app2; - -import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED; - -import static com.android.cts.net.hostside.app2.Common.ACTION_RECEIVER_READY; -import static com.android.cts.net.hostside.app2.Common.DYNAMIC_RECEIVER; -import static com.android.cts.net.hostside.app2.Common.TAG; - -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -import com.android.cts.net.hostside.IMyService; -import com.android.cts.net.hostside.INetworkCallback; - -/** - * Service used to dynamically register a broadcast receiver. - */ -public class MyService extends Service { - private static final String NOTIFICATION_CHANNEL_ID = "MyService"; - - ConnectivityManager mCm; - - private MyBroadcastReceiver mReceiver; - private ConnectivityManager.NetworkCallback mNetworkCallback; - - // TODO: move MyBroadcast static functions here - they were kept there to make git diff easier. - - private IMyService.Stub mBinder = - new IMyService.Stub() { - - @Override - public void registerBroadcastReceiver() { - if (mReceiver != null) { - Log.d(TAG, "receiver already registered: " + mReceiver); - return; - } - final Context context = getApplicationContext(); - mReceiver = new MyBroadcastReceiver(DYNAMIC_RECEIVER); - context.registerReceiver(mReceiver, new IntentFilter(ACTION_RECEIVER_READY)); - context.registerReceiver(mReceiver, - new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED)); - Log.d(TAG, "receiver registered"); - } - - @Override - public int getCounters(String receiverName, String action) { - return MyBroadcastReceiver.getCounter(getApplicationContext(), action, receiverName); - } - - @Override - public String checkNetworkStatus() { - return MyBroadcastReceiver.checkNetworkStatus(getApplicationContext()); - } - - @Override - public String getRestrictBackgroundStatus() { - return MyBroadcastReceiver.getRestrictBackgroundStatus(getApplicationContext()); - } - - @Override - public void sendNotification(int notificationId, String notificationType) { - MyBroadcastReceiver .sendNotification(getApplicationContext(), NOTIFICATION_CHANNEL_ID, - notificationId, notificationType); - } - - @Override - public void registerNetworkCallback(INetworkCallback cb) { - if (mNetworkCallback != null) { - Log.d(TAG, "unregister previous network callback: " + mNetworkCallback); - unregisterNetworkCallback(); - } - Log.d(TAG, "registering network callback"); - - mNetworkCallback = new ConnectivityManager.NetworkCallback() { - @Override - public void onBlockedStatusChanged(Network network, boolean blocked) { - try { - cb.onBlockedStatusChanged(network, blocked); - } catch (RemoteException e) { - Log.d(TAG, "Cannot send onBlockedStatusChanged: " + e); - unregisterNetworkCallback(); - } - } - - @Override - public void onAvailable(Network network) { - try { - cb.onAvailable(network); - } catch (RemoteException e) { - Log.d(TAG, "Cannot send onAvailable: " + e); - unregisterNetworkCallback(); - } - } - - @Override - public void onLost(Network network) { - try { - cb.onLost(network); - } catch (RemoteException e) { - Log.d(TAG, "Cannot send onLost: " + e); - unregisterNetworkCallback(); - } - } - - @Override - public void onCapabilitiesChanged(Network network, NetworkCapabilities cap) { - try { - cb.onCapabilitiesChanged(network, cap); - } catch (RemoteException e) { - Log.d(TAG, "Cannot send onCapabilitiesChanged: " + e); - unregisterNetworkCallback(); - } - } - }; - mCm.registerNetworkCallback(makeWifiNetworkRequest(), mNetworkCallback); - try { - cb.asBinder().linkToDeath(() -> unregisterNetworkCallback(), 0); - } catch (RemoteException e) { - unregisterNetworkCallback(); - } - } - - @Override - public void unregisterNetworkCallback() { - Log.d(TAG, "unregistering network callback"); - if (mNetworkCallback != null) { - mCm.unregisterNetworkCallback(mNetworkCallback); - mNetworkCallback = null; - } - } - }; - - private NetworkRequest makeWifiNetworkRequest() { - return new NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build(); - } - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - @Override - public void onCreate() { - final Context context = getApplicationContext(); - ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)) - .createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID, - NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT)); - mCm = (ConnectivityManager) getApplicationContext() - .getSystemService(Context.CONNECTIVITY_SERVICE); - } - - @Override - public void onDestroy() { - final Context context = getApplicationContext(); - ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)) - .deleteNotificationChannel(NOTIFICATION_CHANNEL_ID); - if (mReceiver != null) { - Log.d(TAG, "onDestroy(): unregistering " + mReceiver); - getApplicationContext().unregisterReceiver(mReceiver); - } - - super.onDestroy(); - } -} diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java deleted file mode 100644 index b1b7d77ae1..0000000000 --- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net.hostside.app2; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import android.os.Process; -import android.util.Log; - -import com.android.cts.net.hostside.IRemoteSocketFactory; - -import java.net.Socket; - - -public class RemoteSocketFactoryService extends Service { - - private static final String TAG = RemoteSocketFactoryService.class.getSimpleName(); - - private IRemoteSocketFactory.Stub mBinder = new IRemoteSocketFactory.Stub() { - @Override - public ParcelFileDescriptor openSocketFd(String host, int port, int timeoutMs) { - try { - Socket s = new Socket(host, port); - s.setSoTimeout(timeoutMs); - return ParcelFileDescriptor.fromSocket(s); - } catch (Exception e) { - throw new IllegalArgumentException(e); - } - } - - @Override - public String getPackageName() { - return RemoteSocketFactoryService.this.getPackageName(); - } - - @Override - public int getUid() { - return Process.myUid(); - } - }; - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } -} diff --git a/tests/cts/hostside/certs/Android.bp b/tests/cts/hostside/certs/Android.bp deleted file mode 100644 index ab4cf340d0..0000000000 --- a/tests/cts/hostside/certs/Android.bp +++ /dev/null @@ -1,4 +0,0 @@ -android_app_certificate { - name: "cts-net-app", - certificate: "cts-net-app", -} diff --git a/tests/cts/hostside/certs/README b/tests/cts/hostside/certs/README deleted file mode 100644 index b660a82dc8..0000000000 --- a/tests/cts/hostside/certs/README +++ /dev/null @@ -1,2 +0,0 @@ -# Generated with: -development/tools/make_key cts-net-app '/CN=cts-net-app' diff --git a/tests/cts/hostside/certs/cts-net-app.pk8 b/tests/cts/hostside/certs/cts-net-app.pk8 deleted file mode 100644 index 1703e4ee340b7c7ab818097cefbbf95fb86f3747..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1219 zcmV;!1U&mNf&{+;0RS)!1_>&LNQUrsW5^Br2+u}0)hbn0N#A&vRMl( z)K7&#gN-YqA(ePu&=E2o$Vjep&N^#?J+IQe_UD^8vWC4%PBxI-ME{s%p~72w0ZU@; zaXKTG43uCz5lGMl@ha*FIBFHPR{XV|cKf1`B_%f8?!Ujr zt-{>0C4_u?`%vIYq{z#o&|wc%#UbbC#EF~*3eXtI#Pu@b#2AEmesXH!;BA|+2B81W z!Zu8OMUNETxR$5$c?)i;hZYR4J*6YT$pCc&@}h3pQGsU#%?m@^a{>ba009Dm0RaHk zc>v0s8?m!kl+%O!>N@ze<-9;f(^2U#XFDru6^Rdi7GW7mTF+$(jvu=f&c6qwe0xQc z-YV8)osrJ&&LK`cr5XVSk|=+5h9S}kmdcGs++ig(JtFrKB&6at^XSEN7gbjf(l>>Q zW5q!7d>b5VnALd8DRw?XvqUfpAAaDQ)mpy#BAh*U&nzY5KA?dt?&F!_gTW_hO&aG? zFz!^L2yHTF#V@X&LqF|!Q4`{WkX^!rOP6AzE3-+ExKAD|AnK7^^w$v-bH;VQMuXQG z^wqpIj+;*3h|p36xkZ4_k2@ee;ehD~XA7iWt0O?}W4hlp!7008eHpZ&=5xtRJbcFmSVJik5H=O_+OcDr64K?)M2Tx(p#1Bj!W}szK*F#xG5_9njbtuN zvAj31ay#p;XUyF~^2T$(v1bpJYKX(0Hjh1=a0St$<@BH?5pD>(7CE0M%ug3w#-4iu zfq)5bl2l+u5>xWKztT8zHPHfrfdIA^X{1GXSD$}V6aG5WdD+aZ)3UOU)PA-Q{> z3qB8AR`51~p;B8g;f0T+gwBF{nn#RZ*xS3do08bdRK^ktwT+BuQ7nn@r4GbJz7x8u zX+HvifdH9pz)+xQ>TMce;8KGy?O90aj>ISS3b7$HM<}?=R_^2Dov>KX=fW4gZ0oL# z4TlXtL8u4+=w-H(!dkS=iZ?}Kj79RMiGFcJL@(@4Kz{D4>0IF9=(5M)>0ajZaHD0q hCv|>6qS`CJYwg-kjl|iF9l$*x resultEntry : - result.getTestResults().entrySet()) { - if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) { - errorBuilder.append(resultEntry.getKey().toString()); - errorBuilder.append(":\n"); - errorBuilder.append(resultEntry.getValue().getStackTrace()); - } - } - throw new AssertionError(errorBuilder.toString()); - } - } - - private static final Pattern UID_PATTERN = - Pattern.compile(".*userId=([0-9]+)$", Pattern.MULTILINE); - - protected int getUid(String packageName) throws DeviceNotAvailableException { - final String output = runCommand("dumpsys package " + packageName); - final Matcher matcher = UID_PATTERN.matcher(output); - while (matcher.find()) { - final String match = matcher.group(1); - return Integer.parseInt(match); - } - throw new RuntimeException("Did not find regexp '" + UID_PATTERN + "' on adb output\n" - + output); - } - - protected String runCommand(String command) throws DeviceNotAvailableException { - Log.d(TAG, "Command: '" + command + "'"); - final String output = getDevice().executeShellCommand(command); - if (DEBUG) Log.v(TAG, "Output: " + output.trim()); - return output; - } -} diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java deleted file mode 100644 index 4598c3936b..0000000000 --- a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net; - -import com.android.ddmlib.Log; -import com.android.tradefed.device.DeviceNotAvailableException; - -public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestCase { - - @Override - protected void setUp() throws Exception { - super.setUp(); - - uninstallPackage(TEST_APP2_PKG, false); - installPackage(TEST_APP2_APK); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - - uninstallPackage(TEST_APP2_PKG, true); - } - - /************************** - * Data Saver Mode tests. * - **************************/ - - public void testDataSaverMode_disabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DataSaverModeTest", - "testGetRestrictBackgroundStatus_disabled"); - } - - public void testDataSaverMode_whitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DataSaverModeTest", - "testGetRestrictBackgroundStatus_whitelisted"); - } - - public void testDataSaverMode_enabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DataSaverModeTest", - "testGetRestrictBackgroundStatus_enabled"); - } - - public void testDataSaverMode_blacklisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DataSaverModeTest", - "testGetRestrictBackgroundStatus_blacklisted"); - } - - public void testDataSaverMode_reinstall() throws Exception { - final int oldUid = getUid(TEST_APP2_PKG); - - // Make sure whitelist is revoked when package is removed - addRestrictBackgroundWhitelist(oldUid); - - uninstallPackage(TEST_APP2_PKG, true); - assertPackageUninstalled(TEST_APP2_PKG); - assertRestrictBackgroundWhitelist(oldUid, false); - - installPackage(TEST_APP2_APK); - final int newUid = getUid(TEST_APP2_PKG); - assertRestrictBackgroundWhitelist(oldUid, false); - assertRestrictBackgroundWhitelist(newUid, false); - } - - public void testDataSaverMode_requiredWhitelistedPackages() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DataSaverModeTest", - "testGetRestrictBackgroundStatus_requiredWhitelistedPackages"); - } - - public void testDataSaverMode_broadcastNotSentOnUnsupportedDevices() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DataSaverModeTest", - "testBroadcastNotSentOnUnsupportedDevices"); - } - - /***************************** - * Battery Saver Mode tests. * - *****************************/ - - public void testBatterySaverModeMetered_disabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".BatterySaverModeMeteredTest", - "testBackgroundNetworkAccess_disabled"); - } - - public void testBatterySaverModeMetered_whitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".BatterySaverModeMeteredTest", - "testBackgroundNetworkAccess_whitelisted"); - } - - public void testBatterySaverModeMetered_enabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".BatterySaverModeMeteredTest", - "testBackgroundNetworkAccess_enabled"); - } - - public void testBatterySaverMode_reinstall() throws Exception { - if (!isDozeModeEnabled()) { - Log.w(TAG, "testBatterySaverMode_reinstall() skipped because device does not support " - + "Doze Mode"); - return; - } - - addPowerSaveModeWhitelist(TEST_APP2_PKG); - - uninstallPackage(TEST_APP2_PKG, true); - assertPackageUninstalled(TEST_APP2_PKG); - assertPowerSaveModeWhitelist(TEST_APP2_PKG, false); - - installPackage(TEST_APP2_APK); - assertPowerSaveModeWhitelist(TEST_APP2_PKG, false); - } - - public void testBatterySaverModeNonMetered_disabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".BatterySaverModeNonMeteredTest", - "testBackgroundNetworkAccess_disabled"); - } - - public void testBatterySaverModeNonMetered_whitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".BatterySaverModeNonMeteredTest", - "testBackgroundNetworkAccess_whitelisted"); - } - - public void testBatterySaverModeNonMetered_enabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".BatterySaverModeNonMeteredTest", - "testBackgroundNetworkAccess_enabled"); - } - - /******************* - * App idle tests. * - *******************/ - - public void testAppIdleMetered_disabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest", - "testBackgroundNetworkAccess_disabled"); - } - - public void testAppIdleMetered_whitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest", - "testBackgroundNetworkAccess_whitelisted"); - } - - public void testAppIdleMetered_tempWhitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest", - "testBackgroundNetworkAccess_tempWhitelisted"); - } - - public void testAppIdleMetered_enabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest", - "testBackgroundNetworkAccess_enabled"); - } - - public void testAppIdleMetered_idleWhitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest", - "testAppIdleNetworkAccess_idleWhitelisted"); - } - - // TODO: currently power-save mode and idle uses the same whitelist, so this test would be - // redundant (as it would be testing the same as testBatterySaverMode_reinstall()) - // public void testAppIdle_reinstall() throws Exception { - // } - - public void testAppIdleNonMetered_disabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest", - "testBackgroundNetworkAccess_disabled"); - } - - public void testAppIdleNonMetered_whitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest", - "testBackgroundNetworkAccess_whitelisted"); - } - - public void testAppIdleNonMetered_tempWhitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest", - "testBackgroundNetworkAccess_tempWhitelisted"); - } - - public void testAppIdleNonMetered_enabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest", - "testBackgroundNetworkAccess_enabled"); - } - - public void testAppIdleNonMetered_idleWhitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest", - "testAppIdleNetworkAccess_idleWhitelisted"); - } - - public void testAppIdleNonMetered_whenCharging() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest", - "testAppIdleNetworkAccess_whenCharging"); - } - - public void testAppIdleMetered_whenCharging() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleMeteredTest", - "testAppIdleNetworkAccess_whenCharging"); - } - - public void testAppIdle_toast() throws Exception { - // Check that showing a toast doesn't bring an app out of standby - runDeviceTests(TEST_PKG, TEST_PKG + ".AppIdleNonMeteredTest", - "testAppIdle_toast"); - } - - /******************** - * Doze Mode tests. * - ********************/ - - public void testDozeModeMetered_disabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeMeteredTest", - "testBackgroundNetworkAccess_disabled"); - } - - public void testDozeModeMetered_whitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeMeteredTest", - "testBackgroundNetworkAccess_whitelisted"); - } - - public void testDozeModeMetered_enabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeMeteredTest", - "testBackgroundNetworkAccess_enabled"); - } - - public void testDozeModeMetered_enabledButWhitelistedOnNotificationAction() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeMeteredTest", - "testBackgroundNetworkAccess_enabledButWhitelistedOnNotificationAction"); - } - - // TODO: currently power-save mode and idle uses the same whitelist, so this test would be - // redundant (as it would be testing the same as testBatterySaverMode_reinstall()) - // public void testDozeMode_reinstall() throws Exception { - // } - - public void testDozeModeNonMetered_disabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeNonMeteredTest", - "testBackgroundNetworkAccess_disabled"); - } - - public void testDozeModeNonMetered_whitelisted() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeNonMeteredTest", - "testBackgroundNetworkAccess_whitelisted"); - } - - public void testDozeModeNonMetered_enabled() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeNonMeteredTest", - "testBackgroundNetworkAccess_enabled"); - } - - public void testDozeModeNonMetered_enabledButWhitelistedOnNotificationAction() - throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".DozeModeNonMeteredTest", - "testBackgroundNetworkAccess_enabledButWhitelistedOnNotificationAction"); - } - - /********************** - * Mixed modes tests. * - **********************/ - - public void testDataAndBatterySaverModes_meteredNetwork() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest", - "testDataAndBatterySaverModes_meteredNetwork"); - } - - public void testDataAndBatterySaverModes_nonMeteredNetwork() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest", - "testDataAndBatterySaverModes_nonMeteredNetwork"); - } - - public void testDozeAndBatterySaverMode_powerSaveWhitelists() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest", - "testDozeAndBatterySaverMode_powerSaveWhitelists"); - } - - public void testDozeAndAppIdle_powerSaveWhitelists() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest", - "testDozeAndAppIdle_powerSaveWhitelists"); - } - - public void testAppIdleAndDoze_tempPowerSaveWhitelists() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest", - "testAppIdleAndDoze_tempPowerSaveWhitelists"); - } - - public void testAppIdleAndBatterySaver_tempPowerSaveWhitelists() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest", - "testAppIdleAndBatterySaver_tempPowerSaveWhitelists"); - } - - public void testDozeAndAppIdle_appIdleWhitelist() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest", - "testDozeAndAppIdle_appIdleWhitelist"); - } - - public void testAppIdleAndDoze_tempPowerSaveAndAppIdleWhitelists() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest", - "testAppIdleAndDoze_tempPowerSaveAndAppIdleWhitelists"); - } - - public void testAppIdleAndBatterySaver_tempPowerSaveAndAppIdleWhitelists() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".MixedModesTest", - "testAppIdleAndBatterySaver_tempPowerSaveAndAppIdleWhitelists"); - } - - /******************* - * Helper methods. * - *******************/ - - private void assertRestrictBackgroundWhitelist(int uid, boolean expected) throws Exception { - final int max_tries = 5; - boolean actual = false; - for (int i = 1; i <= max_tries; i++) { - final String output = runCommand("cmd netpolicy list restrict-background-whitelist "); - actual = output.contains(Integer.toString(uid)); - if (expected == actual) { - return; - } - Log.v(TAG, "whitelist check for uid " + uid + " doesn't match yet (expected " - + expected + ", got " + actual + "); sleeping 1s before polling again"); - Thread.sleep(1000); - } - fail("whitelist check for uid " + uid + " failed: expected " - + expected + ", got " + actual); - } - - private void assertPowerSaveModeWhitelist(String packageName, boolean expected) - throws Exception { - // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll - // need to use netpolicy for whitelisting - assertDelayedCommand("dumpsys deviceidle whitelist =" + packageName, - Boolean.toString(expected)); - } - - /** - * Asserts the result of a command, wait and re-running it a couple times if necessary. - */ - private void assertDelayedCommand(String command, String expectedResult) - throws InterruptedException, DeviceNotAvailableException { - final int maxTries = 5; - for (int i = 1; i <= maxTries; i++) { - final String result = runCommand(command).trim(); - if (result.equals(expectedResult)) return; - Log.v(TAG, "Command '" + command + "' returned '" + result + " instead of '" - + expectedResult + "' on attempt #; sleeping 1s before polling again"); - Thread.sleep(1000); - } - fail("Command '" + command + "' did not return '" + expectedResult + "' after " + maxTries - + " attempts"); - } - - protected void addRestrictBackgroundWhitelist(int uid) throws Exception { - runCommand("cmd netpolicy add restrict-background-whitelist " + uid); - assertRestrictBackgroundWhitelist(uid, true); - } - - private void addPowerSaveModeWhitelist(String packageName) throws Exception { - Log.i(TAG, "Adding package " + packageName + " to power-save-mode whitelist"); - // TODO: currently the power-save mode is behaving like idle, but once it changes, we'll - // need to use netpolicy for whitelisting - runCommand("dumpsys deviceidle whitelist +" + packageName); - assertPowerSaveModeWhitelist(packageName, true); // Sanity check - } - - protected boolean isDozeModeEnabled() throws Exception { - final String result = runCommand("cmd deviceidle enabled deep").trim(); - return result.equals("1"); - } -} diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java deleted file mode 100644 index 62925ad6ab..0000000000 --- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.net; - -public class HostsideVpnTests extends HostsideNetworkTestCase { - - @Override - protected void setUp() throws Exception { - super.setUp(); - - uninstallPackage(TEST_APP2_PKG, false); - installPackage(TEST_APP2_APK); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - - uninstallPackage(TEST_APP2_PKG, true); - } - - public void testDefault() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testDefault"); - } - - public void testAppAllowed() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testAppAllowed"); - } - - public void testAppDisallowed() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testAppDisallowed"); - } - - public void testGetConnectionOwnerUidSecurity() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testGetConnectionOwnerUidSecurity"); - } - - public void testSetProxy() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testSetProxy"); - } - - public void testSetProxyDisallowedApps() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testSetProxyDisallowedApps"); - } - - public void testNoProxy() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testNoProxy"); - } - - public void testBindToNetworkWithProxy() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testBindToNetworkWithProxy"); - } - - public void testVpnMeterednessWithNoUnderlyingNetwork() throws Exception { - runDeviceTests( - TEST_PKG, TEST_PKG + ".VpnTest", "testVpnMeterednessWithNoUnderlyingNetwork"); - } - - public void testVpnMeterednessWithNullUnderlyingNetwork() throws Exception { - runDeviceTests( - TEST_PKG, TEST_PKG + ".VpnTest", "testVpnMeterednessWithNullUnderlyingNetwork"); - } - - public void testVpnMeterednessWithNonNullUnderlyingNetwork() throws Exception { - runDeviceTests( - TEST_PKG, TEST_PKG + ".VpnTest", "testVpnMeterednessWithNonNullUnderlyingNetwork"); - } - - public void testAlwaysMeteredVpnWithNullUnderlyingNetwork() throws Exception { - runDeviceTests( - TEST_PKG, TEST_PKG + ".VpnTest", "testAlwaysMeteredVpnWithNullUnderlyingNetwork"); - } - - public void testAlwaysMeteredVpnWithNonNullUnderlyingNetwork() throws Exception { - runDeviceTests( - TEST_PKG, - TEST_PKG + ".VpnTest", - "testAlwaysMeteredVpnWithNonNullUnderlyingNetwork"); - } - - public void testB141603906() throws Exception { - runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testB141603906"); - } -} diff --git a/tests/cts/hostside/src/com/android/cts/net/NetworkPolicyTestsPreparer.java b/tests/cts/hostside/src/com/android/cts/net/NetworkPolicyTestsPreparer.java deleted file mode 100644 index 23aca24788..0000000000 --- a/tests/cts/hostside/src/com/android/cts/net/NetworkPolicyTestsPreparer.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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 com.android.cts.net; - -import com.android.tradefed.device.DeviceNotAvailableException; -import com.android.tradefed.device.ITestDevice; -import com.android.tradefed.invoker.TestInformation; -import com.android.tradefed.log.LogUtil; -import com.android.tradefed.targetprep.ITargetPreparer; - -public class NetworkPolicyTestsPreparer implements ITargetPreparer { - private ITestDevice mDevice; - private boolean mOriginalAirplaneModeEnabled; - private String mOriginalAppStandbyEnabled; - private String mOriginalBatteryStatsConstants; - private final static String KEY_STABLE_CHARGING_DELAY_MS = "battery_charged_delay_ms"; - private final static int DESIRED_STABLE_CHARGING_DELAY_MS = 0; - - @Override - public void setUp(TestInformation testInformation) throws DeviceNotAvailableException { - mDevice = testInformation.getDevice(); - mOriginalAppStandbyEnabled = getAppStandbyEnabled(); - setAppStandbyEnabled("1"); - LogUtil.CLog.d("Original app_standby_enabled: " + mOriginalAppStandbyEnabled); - - mOriginalBatteryStatsConstants = getBatteryStatsConstants(); - setBatteryStatsConstants( - KEY_STABLE_CHARGING_DELAY_MS + "=" + DESIRED_STABLE_CHARGING_DELAY_MS); - LogUtil.CLog.d("Original battery_saver_constants: " + mOriginalBatteryStatsConstants); - - mOriginalAirplaneModeEnabled = getAirplaneModeEnabled(); - // Turn off airplane mode in case another test left the device in that state. - setAirplaneModeEnabled(false); - LogUtil.CLog.d("Original airplane mode state: " + mOriginalAirplaneModeEnabled); - } - - @Override - public void tearDown(TestInformation testInformation, Throwable e) - throws DeviceNotAvailableException { - setAirplaneModeEnabled(mOriginalAirplaneModeEnabled); - setAppStandbyEnabled(mOriginalAppStandbyEnabled); - setBatteryStatsConstants(mOriginalBatteryStatsConstants); - } - - private void setAirplaneModeEnabled(boolean enable) throws DeviceNotAvailableException { - executeCmd("cmd connectivity airplane-mode " + (enable ? "enable" : "disable")); - } - - private boolean getAirplaneModeEnabled() throws DeviceNotAvailableException { - return "enabled".equals(executeCmd("cmd connectivity airplane-mode").trim()); - } - - private void setAppStandbyEnabled(String appStandbyEnabled) throws DeviceNotAvailableException { - if ("null".equals(appStandbyEnabled)) { - executeCmd("settings delete global app_standby_enabled"); - } else { - executeCmd("settings put global app_standby_enabled " + appStandbyEnabled); - } - } - - private String getAppStandbyEnabled() throws DeviceNotAvailableException { - return executeCmd("settings get global app_standby_enabled").trim(); - } - - private void setBatteryStatsConstants(String batteryStatsConstants) - throws DeviceNotAvailableException { - executeCmd("settings put global battery_stats_constants \"" + batteryStatsConstants + "\""); - } - - private String getBatteryStatsConstants() throws DeviceNotAvailableException { - return executeCmd("settings get global battery_stats_constants"); - } - - private String executeCmd(String cmd) throws DeviceNotAvailableException { - final String output = mDevice.executeShellCommand(cmd).trim(); - LogUtil.CLog.d("Output for '%s': %s", cmd, output); - return output; - } -} diff --git a/tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java b/tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java deleted file mode 100644 index 19e61c62a0..0000000000 --- a/tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2018 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.security.cts; - -import com.android.tradefed.build.IBuildInfo; -import com.android.tradefed.device.ITestDevice; -import com.android.tradefed.testtype.DeviceTestCase; -import com.android.tradefed.testtype.IBuildReceiver; -import com.android.tradefed.testtype.IDeviceTest; - -import java.lang.Integer; -import java.lang.String; -import java.util.Arrays; -import java.util.List; -import java.util.ArrayList; - -/** - * Host-side tests for values in /proc/net. - * - * These tests analyze /proc/net to verify that certain networking properties are correct. - */ -public class ProcNetTest extends DeviceTestCase implements IBuildReceiver, IDeviceTest { - private static final String SPI_TIMEOUT_SYSCTL = "/proc/sys/net/core/xfrm_acq_expires"; - private static final int MIN_ACQ_EXPIRES = 3600; - // Global sysctls. Must be present and set to 1. - private static final String[] GLOBAL_SYSCTLS = { - "/proc/sys/net/ipv4/fwmark_reflect", - "/proc/sys/net/ipv6/fwmark_reflect", - "/proc/sys/net/ipv4/tcp_fwmark_accept", - }; - - // Per-interface IPv6 autoconf sysctls. - private static final String IPV6_SYSCTL_DIR = "/proc/sys/net/ipv6/conf"; - private static final String AUTOCONF_SYSCTL = "accept_ra_rt_table"; - - // Expected values for MIN|MAX_PLEN. - private static final String ACCEPT_RA_RT_INFO_MIN_PLEN_STRING = "accept_ra_rt_info_min_plen"; - private static final int ACCEPT_RA_RT_INFO_MIN_PLEN_VALUE = 48; - private static final String ACCEPT_RA_RT_INFO_MAX_PLEN_STRING = "accept_ra_rt_info_max_plen"; - private static final int ACCEPT_RA_RT_INFO_MAX_PLEN_VALUE = 64; - // Expected values for RFC 7559 router soliciations. - // Maximum number of router solicitations to send. -1 means no limit. - private static final int IPV6_WIFI_ROUTER_SOLICITATIONS = -1; - private ITestDevice mDevice; - private IBuildInfo mBuild; - private String[] mSysctlDirs; - - /** - * {@inheritDoc} - */ - @Override - public void setBuild(IBuildInfo build) { - mBuild = build; - } - - /** - * {@inheritDoc} - */ - @Override - public void setDevice(ITestDevice device) { - super.setDevice(device); - mDevice = device; - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - mSysctlDirs = getSysctlDirs(); - } - - private String[] getSysctlDirs() throws Exception { - String interfaceDirs[] = mDevice.executeAdbCommand("shell", "ls", "-1", - IPV6_SYSCTL_DIR).split("\n"); - List interfaceDirsList = new ArrayList(Arrays.asList(interfaceDirs)); - interfaceDirsList.remove("all"); - interfaceDirsList.remove("lo"); - return interfaceDirsList.toArray(new String[interfaceDirsList.size()]); - } - - - protected void assertLess(String sysctl, int a, int b) { - assertTrue("value of " + sysctl + ": expected < " + b + " but was: " + a, a < b); - } - - protected void assertAtLeast(String sysctl, int a, int b) { - assertTrue("value of " + sysctl + ": expected >= " + b + " but was: " + a, a >= b); - } - - public int readIntFromPath(String path) throws Exception { - String mode = mDevice.executeAdbCommand("shell", "stat", "-c", "%a", path).trim(); - String user = mDevice.executeAdbCommand("shell", "stat", "-c", "%u", path).trim(); - String group = mDevice.executeAdbCommand("shell", "stat", "-c", "%g", path).trim(); - assertEquals(mode, "644"); - assertEquals(user, "0"); - assertEquals(group, "0"); - return Integer.parseInt(mDevice.executeAdbCommand("shell", "cat", path).trim()); - } - - /** - * Checks that SPI default timeouts are overridden, and set to a reasonable length of time - */ - public void testMinAcqExpires() throws Exception { - int value = readIntFromPath(SPI_TIMEOUT_SYSCTL); - assertAtLeast(SPI_TIMEOUT_SYSCTL, value, MIN_ACQ_EXPIRES); - } - - /** - * Checks that the sysctls for multinetwork kernel features are present and - * enabled. - */ - public void testProcSysctls() throws Exception { - for (String sysctl : GLOBAL_SYSCTLS) { - int value = readIntFromPath(sysctl); - assertEquals(sysctl, 1, value); - } - - for (String interfaceDir : mSysctlDirs) { - String path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + AUTOCONF_SYSCTL; - int value = readIntFromPath(path); - assertLess(path, value, 0); - } - } - - /** - * Verify that accept_ra_rt_info_{min,max}_plen exists and is set to the expected value - */ - public void testAcceptRaRtInfoMinMaxPlen() throws Exception { - for (String interfaceDir : mSysctlDirs) { - String path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + "accept_ra_rt_info_min_plen"; - int value = readIntFromPath(path); - assertEquals(path, value, ACCEPT_RA_RT_INFO_MIN_PLEN_VALUE); - path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + "accept_ra_rt_info_max_plen"; - value = readIntFromPath(path); - assertEquals(path, value, ACCEPT_RA_RT_INFO_MAX_PLEN_VALUE); - } - } - - /** - * Verify that router_solicitations exists and is set to the expected value - * and verify that router_solicitation_max_interval exists and is in an acceptable interval. - */ - public void testRouterSolicitations() throws Exception { - for (String interfaceDir : mSysctlDirs) { - String path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + "router_solicitations"; - int value = readIntFromPath(path); - assertEquals(IPV6_WIFI_ROUTER_SOLICITATIONS, value); - path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + "router_solicitation_max_interval"; - int interval = readIntFromPath(path); - final int lowerBoundSec = 15 * 60; - final int upperBoundSec = 60 * 60; - assertTrue(lowerBoundSec <= interval); - assertTrue(interval <= upperBoundSec); - } - } -} diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp deleted file mode 100644 index 3b69602638..0000000000 --- a/tests/cts/net/Android.bp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2008 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. - -java_defaults { - name: "CtsNetTestCasesDefaults", - defaults: ["cts_defaults"], - - // Include both the 32 and 64 bit versions - compile_multilib: "both", - - libs: [ - "voip-common", - "android.test.base", - ], - - jni_libs: [ - "libcts_jni", - "libnativedns_jni", - "libnativemultinetwork_jni", - "libnativehelper_compat_libc++", - ], - - srcs: [ - "src/**/*.java", - "src/**/*.kt", - ], - jarjar_rules: "jarjar-rules-shared.txt", - static_libs: [ - "FrameworksNetCommonTests", - "TestNetworkStackLib", - "core-tests-support", - "cts-net-utils", - "ctstestrunner-axt", - "junit", - "junit-params", - "net-utils-framework-common", - "truth-prebuilt", - ], - - // uncomment when b/13249961 is fixed - // sdk_version: "current", - platform_apis: true, -} - -// Networking CTS tests for development and release. These tests always target the platform SDK -// version, and are subject to all the restrictions appropriate to that version. Before SDK -// finalization, these tests have a min_sdk_version of 10000, and cannot be installed on release -// devices. -android_test { - name: "CtsNetTestCases", - defaults: ["CtsNetTestCasesDefaults"], - test_suites: [ - "cts", - "vts10", - "general-tests", - ], - test_config_template: "AndroidTestTemplate.xml", -} - -// Networking CTS tests that target the latest released SDK. These tests can be installed on release -// devices at any point in the Android release cycle and are useful for qualifying mainline modules -// on release devices. -android_test { - name: "CtsNetTestCasesLatestSdk", - defaults: ["CtsNetTestCasesDefaults"], - jni_uses_sdk_apis: true, - min_sdk_version: "29", - target_sdk_version: "30", - test_suites: [ - "general-tests", - "mts", - ], - test_config_template: "AndroidTestTemplate.xml", -} diff --git a/tests/cts/net/AndroidManifest.xml b/tests/cts/net/AndroidManifest.xml deleted file mode 100644 index a7e2bd780a..0000000000 --- a/tests/cts/net/AndroidManifest.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/cts/net/AndroidTestTemplate.xml b/tests/cts/net/AndroidTestTemplate.xml deleted file mode 100644 index 4e937512ad..0000000000 --- a/tests/cts/net/AndroidTestTemplate.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - diff --git a/tests/cts/net/OWNERS b/tests/cts/net/OWNERS deleted file mode 100644 index d55855650f..0000000000 --- a/tests/cts/net/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -# Bug component: 31808 -lorenzo@google.com -satk@google.com diff --git a/tests/cts/net/TEST_MAPPING b/tests/cts/net/TEST_MAPPING deleted file mode 100644 index 3162e22378..0000000000 --- a/tests/cts/net/TEST_MAPPING +++ /dev/null @@ -1,23 +0,0 @@ -{ - // TODO: move to mainline-presubmit once supported - "postsubmit": [ - { - "name": "CtsNetTestCasesLatestSdk", - "options": [ - { - "exclude-annotation": "com.android.testutils.SkipPresubmit" - } - ] - } - ], - "mainline-presubmit": [ - { - "name": "CtsNetTestCasesLatestSdk[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk]", - "options": [ - { - "exclude-annotation": "com.android.testutils.SkipPresubmit" - } - ] - } - ] -} diff --git a/tests/cts/net/api23Test/Android.bp b/tests/cts/net/api23Test/Android.bp deleted file mode 100644 index 0ce9826a2b..0000000000 --- a/tests/cts/net/api23Test/Android.bp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2019 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 { - name: "CtsNetApi23TestCases", - defaults: ["cts_defaults"], - - // Include both the 32 and 64 bit versions - compile_multilib: "both", - - libs: [ - "android.test.base", - ], - - srcs: [ - "src/**/*.java", - "src/**/*.kt", - ], - - static_libs: [ - "core-tests-support", - "compatibility-device-util-axt", - "cts-net-utils", - "ctstestrunner-axt", - "ctstestserver", - "mockwebserver", - "junit", - "junit-params", - "truth-prebuilt", - ], - - platform_apis: true, - - // Tag this module as a cts test artifact - test_suites: [ - "cts", - "vts10", - "general-tests", - ], - -} diff --git a/tests/cts/net/api23Test/AndroidManifest.xml b/tests/cts/net/api23Test/AndroidManifest.xml deleted file mode 100644 index 4889660b97..0000000000 --- a/tests/cts/net/api23Test/AndroidManifest.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/cts/net/api23Test/AndroidTest.xml b/tests/cts/net/api23Test/AndroidTest.xml deleted file mode 100644 index 8042d5067d..0000000000 --- a/tests/cts/net/api23Test/AndroidTest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - diff --git a/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java b/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java deleted file mode 100644 index cdb66e3d5a..0000000000 --- a/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityManagerApi23Test.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2019 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.cts.api23test; - -import static android.content.pm.PackageManager.FEATURE_WIFI; - -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.cts.util.CtsNetUtils; -import android.os.Looper; -import android.test.AndroidTestCase; -import android.util.Log; - -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -public class ConnectivityManagerApi23Test extends AndroidTestCase { - private static final String TAG = ConnectivityManagerApi23Test.class.getSimpleName(); - private static final int SEND_BROADCAST_TIMEOUT = 30000; - // Intent string to get the number of wifi CONNECTIVITY_ACTION callbacks the test app has seen - public static final String GET_WIFI_CONNECTIVITY_ACTION_COUNT = - "android.net.cts.appForApi23.getWifiConnectivityActionCount"; - // Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent. - - private Context mContext; - private PackageManager mPackageManager; - private CtsNetUtils mCtsNetUtils; - - @Override - protected void setUp() throws Exception { - super.setUp(); - Looper.prepare(); - mContext = getContext(); - mPackageManager = mContext.getPackageManager(); - mCtsNetUtils = new CtsNetUtils(mContext); - } - - /** - * Tests reporting of connectivity changed. - */ - public void testConnectivityChanged_manifestRequestOnly_shouldNotReceiveIntent() { - if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { - Log.i(TAG, "testConnectivityChanged_manifestRequestOnly_shouldNotReceiveIntent cannot execute unless device supports WiFi"); - return; - } - ConnectivityReceiver.prepare(); - - mCtsNetUtils.toggleWifi(); - - // The connectivity broadcast has been sent; push through a terminal broadcast - // to wait for in the receive to confirm it didn't see the connectivity change. - Intent finalIntent = new Intent(ConnectivityReceiver.FINAL_ACTION); - finalIntent.setClass(mContext, ConnectivityReceiver.class); - mContext.sendBroadcast(finalIntent); - assertFalse(ConnectivityReceiver.waitForBroadcast()); - } - - public void testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent() - throws InterruptedException { - if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { - Log.i(TAG, "testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent cannot" - + "execute unless device supports WiFi"); - return; - } - mContext.startActivity(new Intent() - .setComponent(new ComponentName("android.net.cts.appForApi23", - "android.net.cts.appForApi23.ConnectivityListeningActivity")) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); - Thread.sleep(200); - - mCtsNetUtils.toggleWifi(); - - Intent getConnectivityCount = new Intent(GET_WIFI_CONNECTIVITY_ACTION_COUNT); - assertEquals(2, sendOrderedBroadcastAndReturnResultCode( - getConnectivityCount, SEND_BROADCAST_TIMEOUT)); - } - - public void testConnectivityChanged_whenRegistered_shouldReceiveIntent() { - if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { - Log.i(TAG, "testConnectivityChanged_whenRegistered_shouldReceiveIntent cannot execute unless device supports WiFi"); - return; - } - ConnectivityReceiver.prepare(); - ConnectivityReceiver receiver = new ConnectivityReceiver(); - IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - mContext.registerReceiver(receiver, filter); - - mCtsNetUtils.toggleWifi(); - Intent finalIntent = new Intent(ConnectivityReceiver.FINAL_ACTION); - finalIntent.setClass(mContext, ConnectivityReceiver.class); - mContext.sendBroadcast(finalIntent); - - assertTrue(ConnectivityReceiver.waitForBroadcast()); - } - - private int sendOrderedBroadcastAndReturnResultCode( - Intent intent, int timeoutMs) throws InterruptedException { - final LinkedBlockingQueue result = new LinkedBlockingQueue<>(1); - mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - result.offer(getResultCode()); - } - }, null, 0, null, null); - - Integer resultCode = result.poll(timeoutMs, TimeUnit.MILLISECONDS); - assertNotNull("Timed out (more than " + timeoutMs + - " milliseconds) waiting for result code for broadcast", resultCode); - return resultCode; - } - -} \ No newline at end of file diff --git a/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityReceiver.java b/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityReceiver.java deleted file mode 100644 index 9d2b8ad2f6..0000000000 --- a/tests/cts/net/api23Test/src/android/net/cts/api23test/ConnectivityReceiver.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.cts.api23test; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.util.Log; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -public class ConnectivityReceiver extends BroadcastReceiver { - static boolean sReceivedConnectivity; - static boolean sReceivedFinal; - static CountDownLatch sLatch; - - static void prepare() { - synchronized (ConnectivityReceiver.class) { - sReceivedConnectivity = sReceivedFinal = false; - sLatch = new CountDownLatch(1); - } - } - - static boolean waitForBroadcast() { - try { - sLatch.await(30, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new IllegalStateException(e); - } - synchronized (ConnectivityReceiver.class) { - sLatch = null; - if (!sReceivedFinal) { - throw new IllegalStateException("Never received final broadcast"); - } - return sReceivedConnectivity; - } - } - - static final String FINAL_ACTION = "android.net.cts.action.FINAL"; - - @Override - public void onReceive(Context context, Intent intent) { - Log.i("ConnectivityReceiver", "Received: " + intent.getAction()); - if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { - sReceivedConnectivity = true; - } else if (FINAL_ACTION.equals(intent.getAction())) { - sReceivedFinal = true; - if (sLatch != null) { - sLatch.countDown(); - } - } - } -} diff --git a/tests/cts/net/appForApi23/Android.bp b/tests/cts/net/appForApi23/Android.bp deleted file mode 100644 index 399c199508..0000000000 --- a/tests/cts/net/appForApi23/Android.bp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -android_test { - name: "CtsNetTestAppForApi23", - defaults: ["cts_defaults"], - - // Include both the 32 and 64 bit versions - compile_multilib: "both", - - srcs: ["src/**/*.java"], - - sdk_version: "23", - - // Tag this module as a cts test artifact - test_suites: [ - "cts", - "vts10", - "general-tests", - ], - -} diff --git a/tests/cts/net/appForApi23/AndroidManifest.xml b/tests/cts/net/appForApi23/AndroidManifest.xml deleted file mode 100644 index ed4cedbc1d..0000000000 --- a/tests/cts/net/appForApi23/AndroidManifest.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/cts/net/appForApi23/src/android/net/cts/appForApi23/ConnectivityListeningActivity.java b/tests/cts/net/appForApi23/src/android/net/cts/appForApi23/ConnectivityListeningActivity.java deleted file mode 100644 index 24fb68e8cd..0000000000 --- a/tests/cts/net/appForApi23/src/android/net/cts/appForApi23/ConnectivityListeningActivity.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.cts.appForApi23; - -import android.app.Activity; - -// Stub activity used to start the app -public class ConnectivityListeningActivity extends Activity { -} \ No newline at end of file diff --git a/tests/cts/net/appForApi23/src/android/net/cts/appForApi23/ConnectivityReceiver.java b/tests/cts/net/appForApi23/src/android/net/cts/appForApi23/ConnectivityReceiver.java deleted file mode 100644 index 8039a4f943..0000000000 --- a/tests/cts/net/appForApi23/src/android/net/cts/appForApi23/ConnectivityReceiver.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.cts.appForApi23; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; - -public class ConnectivityReceiver extends BroadcastReceiver { - public static String GET_WIFI_CONNECTIVITY_ACTION_COUNT = - "android.net.cts.appForApi23.getWifiConnectivityActionCount"; - - private static int sWifiConnectivityActionCount = 0; - - @Override - public void onReceive(Context context, Intent intent) { - if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { - int networkType = intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 0); - if (networkType == ConnectivityManager.TYPE_WIFI) { - sWifiConnectivityActionCount++; - } - } - if (GET_WIFI_CONNECTIVITY_ACTION_COUNT.equals(intent.getAction())) { - setResultCode(sWifiConnectivityActionCount); - } - } -} diff --git a/tests/cts/net/assets/network_watchlist_config_empty_for_test.xml b/tests/cts/net/assets/network_watchlist_config_empty_for_test.xml deleted file mode 100644 index 19628d14ed..0000000000 --- a/tests/cts/net/assets/network_watchlist_config_empty_for_test.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - diff --git a/tests/cts/net/assets/network_watchlist_config_for_test.xml b/tests/cts/net/assets/network_watchlist_config_for_test.xml deleted file mode 100644 index 835ae0fea2..0000000000 --- a/tests/cts/net/assets/network_watchlist_config_for_test.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - F0905DA7549614957B449034C281EF7BDEFDBC2B6E050AD1E78D6DE18FBD0D5F - - - 18DD41C9F2E8E4879A1575FB780514EF33CF6E1F66578C4AE7CCA31F49B9F2EC - - - AAAAAAAA - - - BBBBBBBB - - diff --git a/tests/cts/net/jarjar-rules-shared.txt b/tests/cts/net/jarjar-rules-shared.txt deleted file mode 100644 index 11dba74096..0000000000 --- a/tests/cts/net/jarjar-rules-shared.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Module library in frameworks/libs/net -rule com.android.net.module.util.** android.net.cts.util.@1 \ No newline at end of file diff --git a/tests/cts/net/jni/Android.bp b/tests/cts/net/jni/Android.bp deleted file mode 100644 index 3953aeb701..0000000000 --- a/tests/cts/net/jni/Android.bp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2013 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. - -cc_library_shared { - name: "libnativedns_jni", - - srcs: ["NativeDnsJni.c"], - sdk_version: "current", - - shared_libs: [ - "libnativehelper_compat_libc++", - "liblog", - ], - stl: "libc++_static", - - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - ], - -} - -cc_library_shared { - name: "libnativemultinetwork_jni", - - srcs: ["NativeMultinetworkJni.cpp"], - sdk_version: "current", - cflags: [ - "-Wall", - "-Werror", - "-Wno-format", - ], - shared_libs: [ - "libandroid", - "libnativehelper_compat_libc++", - "liblog", - ], - stl: "libc++_static", -} diff --git a/tests/cts/net/jni/NativeDnsJni.c b/tests/cts/net/jni/NativeDnsJni.c deleted file mode 100644 index 4ec800e555..0000000000 --- a/tests/cts/net/jni/NativeDnsJni.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2010 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. - */ - -#include -#include -#include -#include -#include - -#include - -#define LOG_TAG "NativeDns-JNI" -#define LOGD(fmt, ...) \ - __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##__VA_ARGS__) - -const char *GoogleDNSIpV4Address="8.8.8.8"; -const char *GoogleDNSIpV4Address2="8.8.4.4"; -const char *GoogleDNSIpV6Address="2001:4860:4860::8888"; -const char *GoogleDNSIpV6Address2="2001:4860:4860::8844"; - -JNIEXPORT jboolean Java_android_net_cts_DnsTest_testNativeDns(JNIEnv* env, jclass class) -{ - const char *node = "www.google.com"; - char *service = NULL; - struct addrinfo *answer; - - int res = getaddrinfo(node, service, NULL, &answer); - LOGD("getaddrinfo(www.google.com) gave res=%d (%s)", res, gai_strerror(res)); - if (res != 0) return JNI_FALSE; - - // check for v4 & v6 - { - int foundv4 = 0; - int foundv6 = 0; - struct addrinfo *current = answer; - while (current != NULL) { - char buf[256]; - if (current->ai_addr->sa_family == AF_INET) { - inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr, - buf, sizeof(buf)); - foundv4 = 1; - LOGD(" %s", buf); - } else if (current->ai_addr->sa_family == AF_INET6) { - inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr, - buf, sizeof(buf)); - foundv6 = 1; - LOGD(" %s", buf); - } - current = current->ai_next; - } - - freeaddrinfo(answer); - answer = NULL; - if (foundv4 != 1 && foundv6 != 1) { - LOGD("getaddrinfo(www.google.com) didn't find either v4 or v6 address"); - return JNI_FALSE; - } - } - - node = "ipv6.google.com"; - res = getaddrinfo(node, service, NULL, &answer); - LOGD("getaddrinfo(ipv6.google.com) gave res=%d", res); - if (res != 0) return JNI_FALSE; - - { - int foundv4 = 0; - int foundv6 = 0; - struct addrinfo *current = answer; - while (current != NULL) { - char buf[256]; - if (current->ai_addr->sa_family == AF_INET) { - inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr, - buf, sizeof(buf)); - LOGD(" %s", buf); - foundv4 = 1; - } else if (current->ai_addr->sa_family == AF_INET6) { - inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr, - buf, sizeof(buf)); - LOGD(" %s", buf); - foundv6 = 1; - } - current = current->ai_next; - } - - freeaddrinfo(answer); - answer = NULL; - if (foundv4 == 1 || foundv6 != 1) { - LOGD("getaddrinfo(ipv6.google.com) didn't find only v6"); - return JNI_FALSE; - } - } - - // getnameinfo - struct sockaddr_in sa4; - sa4.sin_family = AF_INET; - sa4.sin_port = 0; - inet_pton(AF_INET, GoogleDNSIpV4Address, &(sa4.sin_addr)); - - struct sockaddr_in6 sa6; - sa6.sin6_family = AF_INET6; - sa6.sin6_port = 0; - sa6.sin6_flowinfo = 0; - sa6.sin6_scope_id = 0; - inet_pton(AF_INET6, GoogleDNSIpV6Address2, &(sa6.sin6_addr)); - - char buf[NI_MAXHOST]; - int flags = NI_NAMEREQD; - - res = getnameinfo((const struct sockaddr*)&sa4, sizeof(sa4), buf, sizeof(buf), NULL, 0, flags); - if (res != 0) { - LOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV4Address, res, - gai_strerror(res)); - return JNI_FALSE; - } - if (strstr(buf, "google.com") == NULL && strstr(buf, "dns.google") == NULL) { - LOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s", - GoogleDNSIpV4Address, buf); - return JNI_FALSE; - } - - memset(buf, 0, sizeof(buf)); - res = getnameinfo((const struct sockaddr*)&sa6, sizeof(sa6), buf, sizeof(buf), NULL, 0, flags); - if (res != 0) { - LOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV6Address2, - res, gai_strerror(res)); - return JNI_FALSE; - } - if (strstr(buf, "google.com") == NULL && strstr(buf, "dns.google") == NULL) { - LOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s", - GoogleDNSIpV6Address2, buf); - return JNI_FALSE; - } - - // gethostbyname - struct hostent *my_hostent = gethostbyname("www.youtube.com"); - if (my_hostent == NULL) { - LOGD("gethostbyname(www.youtube.com) gave null response"); - return JNI_FALSE; - } - if ((my_hostent->h_addr_list == NULL) || (*my_hostent->h_addr_list == NULL)) { - LOGD("gethostbyname(www.youtube.com) gave 0 addresses"); - return JNI_FALSE; - } - { - char **current = my_hostent->h_addr_list; - while (*current != NULL) { - char buf[256]; - inet_ntop(my_hostent->h_addrtype, *current, buf, sizeof(buf)); - LOGD("gethostbyname(www.youtube.com) gave %s", buf); - current++; - } - } - - // gethostbyaddr - char addr6[16]; - inet_pton(AF_INET6, GoogleDNSIpV6Address, addr6); - my_hostent = gethostbyaddr(addr6, sizeof(addr6), AF_INET6); - if (my_hostent == NULL) { - LOGD("gethostbyaddr(%s (GoogleDNS) ) gave null response", GoogleDNSIpV6Address); - return JNI_FALSE; - } - - LOGD("gethostbyaddr(%s (GoogleDNS) ) gave %s for name", GoogleDNSIpV6Address, - my_hostent->h_name ? my_hostent->h_name : "null"); - - if (my_hostent->h_name == NULL) return JNI_FALSE; - return JNI_TRUE; -} diff --git a/tests/cts/net/jni/NativeMultinetworkJni.cpp b/tests/cts/net/jni/NativeMultinetworkJni.cpp deleted file mode 100644 index 60e31bc78a..0000000000 --- a/tests/cts/net/jni/NativeMultinetworkJni.cpp +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - - -#define LOG_TAG "MultinetworkApiTest" - -#include -#include -#include -#include -#include -#include -#include /* poll */ -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define LOGD(fmt, ...) \ - __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##__VA_ARGS__) - -#define EXPECT_GE(env, actual, expected, msg) \ - do { \ - if (actual < expected) { \ - jniThrowExceptionFmt(env, "java/lang/AssertionError", \ - "%s:%d: %s EXPECT_GE: expected %d, got %d", \ - __FILE__, __LINE__, msg, expected, actual); \ - } \ - } while (0) - -#define EXPECT_GT(env, actual, expected, msg) \ - do { \ - if (actual <= expected) { \ - jniThrowExceptionFmt(env, "java/lang/AssertionError", \ - "%s:%d: %s EXPECT_GT: expected %d, got %d", \ - __FILE__, __LINE__, msg, expected, actual); \ - } \ - } while (0) - -#define EXPECT_EQ(env, expected, actual, msg) \ - do { \ - if (actual != expected) { \ - jniThrowExceptionFmt(env, "java/lang/AssertionError", \ - "%s:%d: %s EXPECT_EQ: expected %d, got %d", \ - __FILE__, __LINE__, msg, expected, actual); \ - } \ - } while (0) - -static const int MAXPACKET = 8 * 1024; -static const int TIMEOUT_MS = 15000; -static const char kHostname[] = "connectivitycheck.android.com"; -static const char kNxDomainName[] = "test1-nx.metric.gstatic.com"; -static const char kGoogleName[] = "www.google.com"; - -int makeQuery(const char* name, int qtype, uint8_t* buf, size_t buflen) { - return res_mkquery(ns_o_query, name, ns_c_in, qtype, NULL, 0, NULL, buf, buflen); -} - -int getAsyncResponse(JNIEnv* env, int fd, int timeoutMs, int* rcode, uint8_t* buf, size_t bufLen) { - struct pollfd wait_fd = { .fd = fd, .events = POLLIN }; - - poll(&wait_fd, 1, timeoutMs); - if (wait_fd.revents & POLLIN) { - int n = android_res_nresult(fd, rcode, buf, bufLen); - // Verify that android_res_nresult() closed the fd - char dummy; - EXPECT_EQ(env, -1, read(fd, &dummy, sizeof(dummy)), "res_nresult check for closing fd"); - EXPECT_EQ(env, EBADF, errno, "res_nresult check for errno"); - return n; - } - - return -ETIMEDOUT; -} - -int extractIpAddressAnswers(uint8_t* buf, size_t bufLen, int family) { - ns_msg handle; - if (ns_initparse((const uint8_t*) buf, bufLen, &handle) < 0) { - return -errno; - } - const int ancount = ns_msg_count(handle, ns_s_an); - // Answer count = 0 is valid(e.g. response of query with root) - if (!ancount) { - return 0; - } - ns_rr rr; - bool hasValidAns = false; - for (int i = 0; i < ancount; i++) { - if (ns_parserr(&handle, ns_s_an, i, &rr) < 0) { - // If there is no valid answer, test will fail. - continue; - } - const uint8_t* rdata = ns_rr_rdata(rr); - char buffer[INET6_ADDRSTRLEN]; - if (inet_ntop(family, (const char*) rdata, buffer, sizeof(buffer)) == NULL) { - return -errno; - } - hasValidAns = true; - } - return hasValidAns ? 0 : -EBADMSG; -} - -int expectAnswersValid(JNIEnv* env, int fd, int family, int expectedRcode) { - int rcode = -1; - uint8_t buf[MAXPACKET] = {}; - int res = getAsyncResponse(env, fd, TIMEOUT_MS, &rcode, buf, MAXPACKET); - if (res < 0) { - return res; - } - - EXPECT_EQ(env, expectedRcode, rcode, "rcode is not expected"); - - if (expectedRcode == ns_r_noerror && res > 0) { - return extractIpAddressAnswers(buf, res, family); - } - return 0; -} - -int expectAnswersNotValid(JNIEnv* env, int fd, int expectedErrno) { - int rcode = -1; - uint8_t buf[MAXPACKET] = {}; - int res = getAsyncResponse(env, fd, TIMEOUT_MS, &rcode, buf, MAXPACKET); - if (res != expectedErrno) { - LOGD("res:%d, expectedErrno = %d", res, expectedErrno); - return (res > 0) ? -EREMOTEIO : res; - } - return 0; -} - -extern "C" -JNIEXPORT void Java_android_net_cts_MultinetworkApiTest_runResNqueryCheck( - JNIEnv* env, jclass, jlong nethandle) { - net_handle_t handle = (net_handle_t) nethandle; - - // V4 - int fd = android_res_nquery(handle, kHostname, ns_c_in, ns_t_a, 0); - EXPECT_GE(env, fd, 0, "v4 res_nquery"); - EXPECT_EQ(env, 0, expectAnswersValid(env, fd, AF_INET, ns_r_noerror), - "v4 res_nquery check answers"); - - // V6 - fd = android_res_nquery(handle, kHostname, ns_c_in, ns_t_aaaa, 0); - EXPECT_GE(env, fd, 0, "v6 res_nquery"); - EXPECT_EQ(env, 0, expectAnswersValid(env, fd, AF_INET, ns_r_noerror), - "v6 res_nquery check answers"); -} - -extern "C" -JNIEXPORT void Java_android_net_cts_MultinetworkApiTest_runResNsendCheck( - JNIEnv* env, jclass, jlong nethandle) { - net_handle_t handle = (net_handle_t) nethandle; - // V4 - uint8_t buf1[MAXPACKET] = {}; - - int len1 = makeQuery(kGoogleName, ns_t_a, buf1, sizeof(buf1)); - EXPECT_GT(env, len1, 0, "v4 res_mkquery 1st"); - - uint8_t buf2[MAXPACKET] = {}; - int len2 = makeQuery(kHostname, ns_t_a, buf2, sizeof(buf2)); - EXPECT_GT(env, len2, 0, "v4 res_mkquery 2nd"); - - int fd1 = android_res_nsend(handle, buf1, len1, 0); - EXPECT_GE(env, fd1, 0, "v4 res_nsend 1st"); - int fd2 = android_res_nsend(handle, buf2, len2, 0); - EXPECT_GE(env, fd2, 0, "v4 res_nsend 2nd"); - - EXPECT_EQ(env, 0, expectAnswersValid(env, fd2, AF_INET, ns_r_noerror), - "v4 res_nsend 2nd check answers"); - EXPECT_EQ(env, 0, expectAnswersValid(env, fd1, AF_INET, ns_r_noerror), - "v4 res_nsend 1st check answers"); - - // V6 - memset(buf1, 0, sizeof(buf1)); - memset(buf2, 0, sizeof(buf2)); - len1 = makeQuery(kGoogleName, ns_t_aaaa, buf1, sizeof(buf1)); - EXPECT_GT(env, len1, 0, "v6 res_mkquery 1st"); - len2 = makeQuery(kHostname, ns_t_aaaa, buf2, sizeof(buf2)); - EXPECT_GT(env, len2, 0, "v6 res_mkquery 2nd"); - - fd1 = android_res_nsend(handle, buf1, len1, 0); - EXPECT_GE(env, fd1, 0, "v6 res_nsend 1st"); - fd2 = android_res_nsend(handle, buf2, len2, 0); - EXPECT_GE(env, fd2, 0, "v6 res_nsend 2nd"); - - EXPECT_EQ(env, 0, expectAnswersValid(env, fd2, AF_INET6, ns_r_noerror), - "v6 res_nsend 2nd check answers"); - EXPECT_EQ(env, 0, expectAnswersValid(env, fd1, AF_INET6, ns_r_noerror), - "v6 res_nsend 1st check answers"); -} - -extern "C" -JNIEXPORT void Java_android_net_cts_MultinetworkApiTest_runResNnxDomainCheck( - JNIEnv* env, jclass, jlong nethandle) { - net_handle_t handle = (net_handle_t) nethandle; - - // res_nquery V4 NXDOMAIN - int fd = android_res_nquery(handle, kNxDomainName, ns_c_in, ns_t_a, 0); - EXPECT_GE(env, fd, 0, "v4 res_nquery NXDOMAIN"); - EXPECT_EQ(env, 0, expectAnswersValid(env, fd, AF_INET, ns_r_nxdomain), - "v4 res_nquery NXDOMAIN check answers"); - - // res_nquery V6 NXDOMAIN - fd = android_res_nquery(handle, kNxDomainName, ns_c_in, ns_t_aaaa, 0); - EXPECT_GE(env, fd, 0, "v6 res_nquery NXDOMAIN"); - EXPECT_EQ(env, 0, expectAnswersValid(env, fd, AF_INET6, ns_r_nxdomain), - "v6 res_nquery NXDOMAIN check answers"); - - uint8_t buf[MAXPACKET] = {}; - // res_nsend V4 NXDOMAIN - int len = makeQuery(kNxDomainName, ns_t_a, buf, sizeof(buf)); - EXPECT_GT(env, len, 0, "v4 res_mkquery NXDOMAIN"); - fd = android_res_nsend(handle, buf, len, 0); - EXPECT_GE(env, fd, 0, "v4 res_nsend NXDOMAIN"); - EXPECT_EQ(env, 0, expectAnswersValid(env, fd, AF_INET, ns_r_nxdomain), - "v4 res_nsend NXDOMAIN check answers"); - - // res_nsend V6 NXDOMAIN - memset(buf, 0, sizeof(buf)); - len = makeQuery(kNxDomainName, ns_t_aaaa, buf, sizeof(buf)); - EXPECT_GT(env, len, 0, "v6 res_mkquery NXDOMAIN"); - fd = android_res_nsend(handle, buf, len, 0); - EXPECT_GE(env, fd, 0, "v6 res_nsend NXDOMAIN"); - EXPECT_EQ(env, 0, expectAnswersValid(env, fd, AF_INET6, ns_r_nxdomain), - "v6 res_nsend NXDOMAIN check answers"); -} - - -extern "C" -JNIEXPORT void Java_android_net_cts_MultinetworkApiTest_runResNcancelCheck( - JNIEnv* env, jclass, jlong nethandle) { - net_handle_t handle = (net_handle_t) nethandle; - - int fd = android_res_nquery(handle, kGoogleName, ns_c_in, ns_t_a, 0); - errno = 0; - android_res_cancel(fd); - int err = errno; - EXPECT_EQ(env, 0, err, "res_cancel"); - // DO NOT call cancel or result with the same fd more than once, - // otherwise it will hit fdsan double-close fd. -} - -extern "C" -JNIEXPORT void Java_android_net_cts_MultinetworkApiTest_runResNapiMalformedCheck( - JNIEnv* env, jclass, jlong nethandle) { - net_handle_t handle = (net_handle_t) nethandle; - - // It is the equivalent of "dig . a", Query with an empty name. - int fd = android_res_nquery(handle, "", ns_c_in, ns_t_a, 0); - EXPECT_GE(env, fd, 0, "res_nquery root"); - EXPECT_EQ(env, 0, expectAnswersValid(env, fd, AF_INET, ns_r_noerror), - "res_nquery root check answers"); - - // Label limit 63 - std::string exceedingLabelQuery = "www." + std::string(70, 'g') + ".com"; - // Name limit 255 - std::string exceedingDomainQuery = "www." + std::string(255, 'g') + ".com"; - - fd = android_res_nquery(handle, exceedingLabelQuery.c_str(), ns_c_in, ns_t_a, 0); - EXPECT_EQ(env, -EMSGSIZE, fd, "res_nquery exceedingLabelQuery"); - fd = android_res_nquery(handle, exceedingDomainQuery.c_str(), ns_c_in, ns_t_aaaa, 0); - EXPECT_EQ(env, -EMSGSIZE, fd, "res_nquery exceedingDomainQuery"); - - uint8_t buf[10] = {}; - // empty BLOB - fd = android_res_nsend(handle, buf, 10, 0); - EXPECT_GE(env, fd, 0, "res_nsend empty BLOB"); - EXPECT_EQ(env, 0, expectAnswersNotValid(env, fd, -EINVAL), - "res_nsend empty BLOB check answers"); - - uint8_t largeBuf[2 * MAXPACKET] = {}; - // A buffer larger than 8KB - fd = android_res_nsend(handle, largeBuf, sizeof(largeBuf), 0); - EXPECT_EQ(env, -EMSGSIZE, fd, "res_nsend buffer larger than 8KB"); - - // 5000 bytes filled with 0. This returns EMSGSIZE because FrameworkListener limits the size of - // commands to 4096 bytes. - fd = android_res_nsend(handle, largeBuf, 5000, 0); - EXPECT_EQ(env, -EMSGSIZE, fd, "res_nsend 5000 bytes filled with 0"); - - // 500 bytes filled with 0 - fd = android_res_nsend(handle, largeBuf, 500, 0); - EXPECT_GE(env, fd, 0, "res_nsend 500 bytes filled with 0"); - EXPECT_EQ(env, 0, expectAnswersNotValid(env, fd, -EINVAL), - "res_nsend 500 bytes filled with 0 check answers"); - - // 5000 bytes filled with 0xFF - uint8_t ffBuf[5001] = {}; - memset(ffBuf, 0xFF, sizeof(ffBuf)); - ffBuf[5000] = '\0'; - fd = android_res_nsend(handle, ffBuf, sizeof(ffBuf), 0); - EXPECT_EQ(env, -EMSGSIZE, fd, "res_nsend 5000 bytes filled with 0xFF"); - - // 500 bytes filled with 0xFF - ffBuf[500] = '\0'; - fd = android_res_nsend(handle, ffBuf, 501, 0); - EXPECT_GE(env, fd, 0, "res_nsend 500 bytes filled with 0xFF"); - EXPECT_EQ(env, 0, expectAnswersNotValid(env, fd, -EINVAL), - "res_nsend 500 bytes filled with 0xFF check answers"); -} - -extern "C" -JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runGetaddrinfoCheck( - JNIEnv*, jclass, jlong nethandle) { - net_handle_t handle = (net_handle_t) nethandle; - struct addrinfo *res = NULL; - - errno = 0; - int rval = android_getaddrinfofornetwork(handle, kHostname, NULL, NULL, &res); - const int saved_errno = errno; - freeaddrinfo(res); - - LOGD("android_getaddrinfofornetwork(%" PRIu64 ", %s) returned rval=%d errno=%d", - handle, kHostname, rval, saved_errno); - return rval == 0 ? 0 : -saved_errno; -} - -extern "C" -JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runSetprocnetwork( - JNIEnv*, jclass, jlong nethandle) { - net_handle_t handle = (net_handle_t) nethandle; - - errno = 0; - int rval = android_setprocnetwork(handle); - const int saved_errno = errno; - LOGD("android_setprocnetwork(%" PRIu64 ") returned rval=%d errno=%d", - handle, rval, saved_errno); - return rval == 0 ? 0 : -saved_errno; -} - -extern "C" -JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runSetsocknetwork( - JNIEnv*, jclass, jlong nethandle) { - net_handle_t handle = (net_handle_t) nethandle; - - errno = 0; - int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) { - LOGD("socket() failed, errno=%d", errno); - return -errno; - } - - errno = 0; - int rval = android_setsocknetwork(handle, fd); - const int saved_errno = errno; - LOGD("android_setprocnetwork(%" PRIu64 ", %d) returned rval=%d errno=%d", - handle, fd, rval, saved_errno); - close(fd); - return rval == 0 ? 0 : -saved_errno; -} - -// Use sizeof("x") - 1 because we need a compile-time constant, and strlen("x") -// isn't guaranteed to fold to a constant. -static const int kSockaddrStrLen = INET6_ADDRSTRLEN + sizeof("[]:65535") - 1; - -void sockaddr_ntop(const struct sockaddr *sa, socklen_t salen, char *dst, const size_t size) { - char addrstr[INET6_ADDRSTRLEN]; - char portstr[sizeof("65535")]; - char buf[kSockaddrStrLen+1]; - - int ret = getnameinfo(sa, salen, - addrstr, sizeof(addrstr), - portstr, sizeof(portstr), - NI_NUMERICHOST | NI_NUMERICSERV); - if (ret == 0) { - snprintf(buf, sizeof(buf), - (sa->sa_family == AF_INET6) ? "[%s]:%s" : "%s:%s", - addrstr, portstr); - } else { - sprintf(buf, "???"); - } - - strlcpy(dst, buf, size); -} - -extern "C" -JNIEXPORT jint Java_android_net_cts_MultinetworkApiTest_runDatagramCheck( - JNIEnv*, jclass, jlong nethandle) { - const struct addrinfo kHints = { - .ai_flags = AI_ADDRCONFIG, - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_DGRAM, - .ai_protocol = IPPROTO_UDP, - }; - struct addrinfo *res = NULL; - net_handle_t handle = (net_handle_t) nethandle; - - static const char kPort[] = "443"; - int rval = android_getaddrinfofornetwork(handle, kHostname, kPort, &kHints, &res); - if (rval != 0) { - LOGD("android_getaddrinfofornetwork(%llu, %s) returned rval=%d errno=%d", - handle, kHostname, rval, errno); - freeaddrinfo(res); - return -errno; - } - - // Rely upon getaddrinfo sorting the best destination to the front. - int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (fd < 0) { - LOGD("socket(%d, %d, %d) failed, errno=%d", - res->ai_family, res->ai_socktype, res->ai_protocol, errno); - freeaddrinfo(res); - return -errno; - } - - rval = android_setsocknetwork(handle, fd); - LOGD("android_setprocnetwork(%llu, %d) returned rval=%d errno=%d", - handle, fd, rval, errno); - if (rval != 0) { - close(fd); - freeaddrinfo(res); - return -errno; - } - - char addrstr[kSockaddrStrLen+1]; - sockaddr_ntop(res->ai_addr, res->ai_addrlen, addrstr, sizeof(addrstr)); - LOGD("Attempting connect() to %s ...", addrstr); - - rval = connect(fd, res->ai_addr, res->ai_addrlen); - if (rval != 0) { - close(fd); - freeaddrinfo(res); - return -errno; - } - freeaddrinfo(res); - - struct sockaddr_storage src_addr; - socklen_t src_addrlen = sizeof(src_addr); - if (getsockname(fd, (struct sockaddr *)&src_addr, &src_addrlen) != 0) { - close(fd); - return -errno; - } - sockaddr_ntop((const struct sockaddr *)&src_addr, sizeof(src_addr), addrstr, sizeof(addrstr)); - LOGD("... from %s", addrstr); - - // Don't let reads or writes block indefinitely. - const struct timeval timeo = { 2, 0 }; // 2 seconds - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)); - setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo)); - - // For reference see: - // https://datatracker.ietf.org/doc/html/draft-ietf-quic-invariants - uint8_t quic_packet[1200] = { - 0xc0, // long header - 0xaa, 0xda, 0xca, 0xca, // reserved-space version number - 0x08, // destination connection ID length - 0, 0, 0, 0, 0, 0, 0, 0, // 64bit connection ID - 0x00, // source connection ID length - }; - - arc4random_buf(quic_packet + 6, 8); // random connection ID - - uint8_t response[1500]; - ssize_t sent, rcvd; - static const int MAX_RETRIES = 5; - int i, errnum = 0; - - for (i = 0; i < MAX_RETRIES; i++) { - sent = send(fd, quic_packet, sizeof(quic_packet), 0); - if (sent < (ssize_t)sizeof(quic_packet)) { - errnum = errno; - LOGD("send(QUIC packet) returned sent=%zd, errno=%d", sent, errnum); - close(fd); - return -errnum; - } - - rcvd = recv(fd, response, sizeof(response), 0); - if (rcvd > 0) { - break; - } else { - errnum = errno; - LOGD("[%d/%d] recv(QUIC response) returned rcvd=%zd, errno=%d", - i + 1, MAX_RETRIES, rcvd, errnum); - } - } - if (rcvd < 15) { - LOGD("QUIC UDP %s: sent=%zd but rcvd=%zd, errno=%d", kPort, sent, rcvd, errnum); - if (rcvd <= 0) { - LOGD("Does this network block UDP port %s?", kPort); - } - close(fd); - return -EPROTO; - } - - int conn_id_cmp = memcmp(quic_packet + 6, response + 7, 8); - if (conn_id_cmp != 0) { - LOGD("sent and received connection IDs do not match"); - close(fd); - return -EPROTO; - } - - // TODO: Replace this quick 'n' dirty test with proper QUIC-capable code. - - close(fd); - return 0; -} diff --git a/tests/cts/net/native/dns/Android.bp b/tests/cts/net/native/dns/Android.bp deleted file mode 100644 index 1704a2b8f4..0000000000 --- a/tests/cts/net/native/dns/Android.bp +++ /dev/null @@ -1,40 +0,0 @@ -cc_defaults { - name: "dns_async_defaults", - - cflags: [ - "-fstack-protector-all", - "-g", - "-Wall", - "-Wextra", - "-Werror", - "-Wnullable-to-nonnull-conversion", - "-Wsign-compare", - "-Wthread-safety", - "-Wunused-parameter", - ], - srcs: [ - "NativeDnsAsyncTest.cpp", - ], - shared_libs: [ - "libandroid", - "liblog", - "libutils", - ], -} - -cc_test { - name: "CtsNativeNetDnsTestCases", - defaults: ["dns_async_defaults"], - multilib: { - lib32: { - suffix: "32", - }, - lib64: { - suffix: "64", - }, - }, - test_suites: [ - "cts", - "mts", - ], -} diff --git a/tests/cts/net/native/dns/AndroidTest.xml b/tests/cts/net/native/dns/AndroidTest.xml deleted file mode 100644 index 6d03c23448..0000000000 --- a/tests/cts/net/native/dns/AndroidTest.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - diff --git a/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp b/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp deleted file mode 100644 index e501475996..0000000000 --- a/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include /* poll */ -#include -#include -#include - -#include -#include - -namespace { -constexpr int MAXPACKET = 8 * 1024; -constexpr int PTON_MAX = 16; -constexpr int TIMEOUT_MS = 10000; - -int getAsyncResponse(int fd, int timeoutMs, int* rcode, uint8_t* buf, size_t bufLen) { - struct pollfd wait_fd[1]; - wait_fd[0].fd = fd; - wait_fd[0].events = POLLIN; - short revents; - int ret; - ret = poll(wait_fd, 1, timeoutMs); - revents = wait_fd[0].revents; - if (revents & POLLIN) { - int n = android_res_nresult(fd, rcode, buf, bufLen); - // Verify that android_res_nresult() closed the fd - char dummy; - EXPECT_EQ(-1, read(fd, &dummy, sizeof dummy)); - EXPECT_EQ(EBADF, errno); - return n; - } - - return -1; -} - -std::vector extractIpAddressAnswers(uint8_t* buf, size_t bufLen, int ipType) { - ns_msg handle; - if (ns_initparse((const uint8_t*) buf, bufLen, &handle) < 0) { - return {}; - } - const int ancount = ns_msg_count(handle, ns_s_an); - ns_rr rr; - std::vector answers; - for (int i = 0; i < ancount; i++) { - if (ns_parserr(&handle, ns_s_an, i, &rr) < 0) { - continue; - } - const uint8_t* rdata = ns_rr_rdata(rr); - char buffer[INET6_ADDRSTRLEN]; - if (inet_ntop(ipType, (const char*) rdata, buffer, sizeof(buffer))) { - answers.push_back(buffer); - } - } - return answers; -} - -void expectAnswersValid(int fd, int ipType, int expectedRcode) { - int rcode = -1; - uint8_t buf[MAXPACKET] = {}; - int res = getAsyncResponse(fd, TIMEOUT_MS, &rcode, buf, MAXPACKET); - EXPECT_GE(res, 0); - EXPECT_EQ(rcode, expectedRcode); - - if (expectedRcode == ns_r_noerror) { - auto answers = extractIpAddressAnswers(buf, res, ipType); - EXPECT_GE(answers.size(), 0U); - for (auto &answer : answers) { - char pton[PTON_MAX]; - EXPECT_EQ(1, inet_pton(ipType, answer.c_str(), pton)); - } - } -} - -void expectAnswersNotValid(int fd, int expectedErrno) { - int rcode = -1; - uint8_t buf[MAXPACKET] = {}; - int res = getAsyncResponse(fd, TIMEOUT_MS, &rcode, buf, MAXPACKET); - EXPECT_EQ(expectedErrno, res); -} - -} // namespace - -TEST (NativeDnsAsyncTest, Async_Query) { - // V4 - int fd1 = android_res_nquery( - NETWORK_UNSPECIFIED, "www.google.com", ns_c_in, ns_t_a, 0); - EXPECT_GE(fd1, 0); - int fd2 = android_res_nquery( - NETWORK_UNSPECIFIED, "www.youtube.com", ns_c_in, ns_t_a, 0); - EXPECT_GE(fd2, 0); - expectAnswersValid(fd2, AF_INET, ns_r_noerror); - expectAnswersValid(fd1, AF_INET, ns_r_noerror); - - // V6 - fd1 = android_res_nquery( - NETWORK_UNSPECIFIED, "www.google.com", ns_c_in, ns_t_aaaa, 0); - EXPECT_GE(fd1, 0); - fd2 = android_res_nquery( - NETWORK_UNSPECIFIED, "www.youtube.com", ns_c_in, ns_t_aaaa, 0); - EXPECT_GE(fd2, 0); - expectAnswersValid(fd2, AF_INET6, ns_r_noerror); - expectAnswersValid(fd1, AF_INET6, ns_r_noerror); -} - -TEST (NativeDnsAsyncTest, Async_Send) { - // V4 - uint8_t buf1[MAXPACKET] = {}; - int len1 = res_mkquery(ns_o_query, "www.googleapis.com", - ns_c_in, ns_t_a, nullptr, 0, nullptr, buf1, sizeof(buf1)); - EXPECT_GT(len1, 0); - - uint8_t buf2[MAXPACKET] = {}; - int len2 = res_mkquery(ns_o_query, "play.googleapis.com", - ns_c_in, ns_t_a, nullptr, 0, nullptr, buf2, sizeof(buf2)); - EXPECT_GT(len2, 0); - - int fd1 = android_res_nsend(NETWORK_UNSPECIFIED, buf1, len1, 0); - EXPECT_GE(fd1, 0); - int fd2 = android_res_nsend(NETWORK_UNSPECIFIED, buf2, len2, 0); - EXPECT_GE(fd2, 0); - - expectAnswersValid(fd2, AF_INET, ns_r_noerror); - expectAnswersValid(fd1, AF_INET, ns_r_noerror); - - // V6 - memset(buf1, 0, sizeof(buf1)); - memset(buf2, 0, sizeof(buf2)); - len1 = res_mkquery(ns_o_query, "www.googleapis.com", - ns_c_in, ns_t_aaaa, nullptr, 0, nullptr, buf1, sizeof(buf1)); - EXPECT_GT(len1, 0); - len2 = res_mkquery(ns_o_query, "play.googleapis.com", - ns_c_in, ns_t_aaaa, nullptr, 0, nullptr, buf2, sizeof(buf2)); - EXPECT_GT(len2, 0); - - fd1 = android_res_nsend(NETWORK_UNSPECIFIED, buf1, len1, 0); - EXPECT_GE(fd1, 0); - fd2 = android_res_nsend(NETWORK_UNSPECIFIED, buf2, len2, 0); - EXPECT_GE(fd2, 0); - - expectAnswersValid(fd2, AF_INET6, ns_r_noerror); - expectAnswersValid(fd1, AF_INET6, ns_r_noerror); -} - -TEST (NativeDnsAsyncTest, Async_NXDOMAIN) { - uint8_t buf[MAXPACKET] = {}; - int len = res_mkquery(ns_o_query, "test1-nx.metric.gstatic.com", - ns_c_in, ns_t_a, nullptr, 0, nullptr, buf, sizeof(buf)); - EXPECT_GT(len, 0); - int fd1 = android_res_nsend(NETWORK_UNSPECIFIED, buf, len, ANDROID_RESOLV_NO_CACHE_LOOKUP); - EXPECT_GE(fd1, 0); - - len = res_mkquery(ns_o_query, "test2-nx.metric.gstatic.com", - ns_c_in, ns_t_a, nullptr, 0, nullptr, buf, sizeof(buf)); - EXPECT_GT(len, 0); - int fd2 = android_res_nsend(NETWORK_UNSPECIFIED, buf, len, ANDROID_RESOLV_NO_CACHE_LOOKUP); - EXPECT_GE(fd2, 0); - - expectAnswersValid(fd2, AF_INET, ns_r_nxdomain); - expectAnswersValid(fd1, AF_INET, ns_r_nxdomain); - - fd1 = android_res_nquery( - NETWORK_UNSPECIFIED, "test3-nx.metric.gstatic.com", - ns_c_in, ns_t_aaaa, ANDROID_RESOLV_NO_CACHE_LOOKUP); - EXPECT_GE(fd1, 0); - fd2 = android_res_nquery( - NETWORK_UNSPECIFIED, "test4-nx.metric.gstatic.com", - ns_c_in, ns_t_aaaa, ANDROID_RESOLV_NO_CACHE_LOOKUP); - EXPECT_GE(fd2, 0); - expectAnswersValid(fd2, AF_INET6, ns_r_nxdomain); - expectAnswersValid(fd1, AF_INET6, ns_r_nxdomain); -} - -TEST (NativeDnsAsyncTest, Async_Cancel) { - int fd = android_res_nquery( - NETWORK_UNSPECIFIED, "www.google.com", ns_c_in, ns_t_a, 0); - errno = 0; - android_res_cancel(fd); - int err = errno; - EXPECT_EQ(err, 0); - // DO NOT call cancel or result with the same fd more than once, - // otherwise it will hit fdsan double-close fd. -} - -TEST (NativeDnsAsyncTest, Async_Query_MALFORMED) { - // Empty string to create BLOB and query, we will get empty result and rcode = 0 - // on DNSTLS. - int fd = android_res_nquery( - NETWORK_UNSPECIFIED, "", ns_c_in, ns_t_a, 0); - EXPECT_GE(fd, 0); - expectAnswersValid(fd, AF_INET, ns_r_noerror); - - std::string exceedingLabelQuery = "www." + std::string(70, 'g') + ".com"; - std::string exceedingDomainQuery = "www." + std::string(255, 'g') + ".com"; - - fd = android_res_nquery(NETWORK_UNSPECIFIED, - exceedingLabelQuery.c_str(), ns_c_in, ns_t_a, 0); - EXPECT_EQ(-EMSGSIZE, fd); - fd = android_res_nquery(NETWORK_UNSPECIFIED, - exceedingDomainQuery.c_str(), ns_c_in, ns_t_a, 0); - EXPECT_EQ(-EMSGSIZE, fd); -} - -TEST (NativeDnsAsyncTest, Async_Send_MALFORMED) { - uint8_t buf[10] = {}; - // empty BLOB - int fd = android_res_nsend(NETWORK_UNSPECIFIED, buf, 10, 0); - EXPECT_GE(fd, 0); - expectAnswersNotValid(fd, -EINVAL); - - std::vector largeBuf(2 * MAXPACKET, 0); - // A buffer larger than 8KB - fd = android_res_nsend( - NETWORK_UNSPECIFIED, largeBuf.data(), largeBuf.size(), 0); - EXPECT_EQ(-EMSGSIZE, fd); - - // 5000 bytes filled with 0. This returns EMSGSIZE because FrameworkListener limits the size of - // commands to 4096 bytes. - fd = android_res_nsend(NETWORK_UNSPECIFIED, largeBuf.data(), 5000, 0); - EXPECT_EQ(-EMSGSIZE, fd); - - // 500 bytes filled with 0 - fd = android_res_nsend(NETWORK_UNSPECIFIED, largeBuf.data(), 500, 0); - EXPECT_GE(fd, 0); - expectAnswersNotValid(fd, -EINVAL); - - // 5000 bytes filled with 0xFF - std::vector ffBuf(5000, 0xFF); - fd = android_res_nsend( - NETWORK_UNSPECIFIED, ffBuf.data(), ffBuf.size(), 0); - EXPECT_EQ(-EMSGSIZE, fd); - - // 500 bytes filled with 0xFF - fd = android_res_nsend(NETWORK_UNSPECIFIED, ffBuf.data(), 500, 0); - EXPECT_GE(fd, 0); - expectAnswersNotValid(fd, -EINVAL); -} diff --git a/tests/cts/net/native/qtaguid/Android.bp b/tests/cts/net/native/qtaguid/Android.bp deleted file mode 100644 index 23a0cf764d..0000000000 --- a/tests/cts/net/native/qtaguid/Android.bp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2017 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. - -// Build the unit tests. - -cc_test { - name: "CtsNativeNetTestCases", - - compile_multilib: "both", - multilib: { - lib32: { - suffix: "32", - }, - lib64: { - suffix: "64", - }, - }, - - srcs: ["src/NativeQtaguidTest.cpp"], - - shared_libs: [ - "libutils", - "liblog", - ], - - static_libs: [ - "libgtest", - "libqtaguid", - ], - - // Tag this module as a cts test artifact - test_suites: [ - "cts", - "vts10", - ], - - cflags: [ - "-Werror", - "-Wall", - ], - -} diff --git a/tests/cts/net/native/qtaguid/AndroidTest.xml b/tests/cts/net/native/qtaguid/AndroidTest.xml deleted file mode 100644 index fa4b2cf577..0000000000 --- a/tests/cts/net/native/qtaguid/AndroidTest.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - diff --git a/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp b/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp deleted file mode 100644 index 7dc6240667..0000000000 --- a/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -int canAccessQtaguidFile() { - int fd = open("/proc/net/xt_qtaguid/ctrl", O_RDONLY | O_CLOEXEC); - close(fd); - return fd != -1; -} - -#define SKIP_IF_QTAGUID_NOT_SUPPORTED() \ - do { \ - int res = canAccessQtaguidFile(); \ - ASSERT_LE(0, res); \ - if (!res) { \ - GTEST_LOG_(INFO) << "This test is skipped since kernel may not have the module\n"; \ - return; \ - } \ - } while (0) - -int getCtrlSkInfo(int tag, uid_t uid, uint64_t* sk_addr, int* ref_cnt) { - FILE *fp; - fp = fopen("/proc/net/xt_qtaguid/ctrl", "r"); - if (!fp) - return -ENOENT; - uint64_t full_tag = (uint64_t)tag << 32 | uid; - char pattern[40]; - snprintf(pattern, sizeof(pattern), " tag=0x%" PRIx64 " (uid=%" PRIu32 ")", full_tag, uid); - - size_t len; - char *line_buffer = NULL; - while(getline(&line_buffer, &len, fp) != -1) { - if (strstr(line_buffer, pattern) == NULL) - continue; - int res; - pid_t dummy_pid; - uint64_t k_tag; - uint32_t k_uid; - const int TOTAL_PARAM = 5; - res = sscanf(line_buffer, "sock=%" PRIx64 " tag=0x%" PRIx64 " (uid=%" PRIu32 ") " - "pid=%u f_count=%u", sk_addr, &k_tag, &k_uid, - &dummy_pid, ref_cnt); - if (!(res == TOTAL_PARAM && k_tag == full_tag && k_uid == uid)) - return -EINVAL; - free(line_buffer); - return 0; - } - free(line_buffer); - return -ENOENT; -} - -void checkNoSocketPointerLeaks(int family) { - int sockfd = socket(family, SOCK_STREAM, 0); - uid_t uid = getuid(); - int tag = arc4random(); - int ref_cnt; - uint64_t sk_addr; - uint64_t expect_addr = 0; - - EXPECT_EQ(0, legacy_tagSocket(sockfd, tag, uid)); - EXPECT_EQ(0, getCtrlSkInfo(tag, uid, &sk_addr, &ref_cnt)); - EXPECT_EQ(expect_addr, sk_addr); - close(sockfd); - EXPECT_EQ(-ENOENT, getCtrlSkInfo(tag, uid, &sk_addr, &ref_cnt)); -} - -TEST (NativeQtaguidTest, close_socket_without_untag) { - SKIP_IF_QTAGUID_NOT_SUPPORTED(); - - int sockfd = socket(AF_INET, SOCK_STREAM, 0); - uid_t uid = getuid(); - int tag = arc4random(); - int ref_cnt; - uint64_t dummy_sk; - EXPECT_EQ(0, legacy_tagSocket(sockfd, tag, uid)); - EXPECT_EQ(0, getCtrlSkInfo(tag, uid, &dummy_sk, &ref_cnt)); - EXPECT_EQ(2, ref_cnt); - close(sockfd); - EXPECT_EQ(-ENOENT, getCtrlSkInfo(tag, uid, &dummy_sk, &ref_cnt)); -} - -TEST (NativeQtaguidTest, close_socket_without_untag_ipv6) { - SKIP_IF_QTAGUID_NOT_SUPPORTED(); - - int sockfd = socket(AF_INET6, SOCK_STREAM, 0); - uid_t uid = getuid(); - int tag = arc4random(); - int ref_cnt; - uint64_t dummy_sk; - EXPECT_EQ(0, legacy_tagSocket(sockfd, tag, uid)); - EXPECT_EQ(0, getCtrlSkInfo(tag, uid, &dummy_sk, &ref_cnt)); - EXPECT_EQ(2, ref_cnt); - close(sockfd); - EXPECT_EQ(-ENOENT, getCtrlSkInfo(tag, uid, &dummy_sk, &ref_cnt)); -} - -TEST (NativeQtaguidTest, no_socket_addr_leak) { - SKIP_IF_QTAGUID_NOT_SUPPORTED(); - - checkNoSocketPointerLeaks(AF_INET); - checkNoSocketPointerLeaks(AF_INET6); -} - -int main(int argc, char **argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/tests/cts/net/src/android/net/cts/AirplaneModeTest.java b/tests/cts/net/src/android/net/cts/AirplaneModeTest.java deleted file mode 100644 index 524e549ab7..0000000000 --- a/tests/cts/net/src/android/net/cts/AirplaneModeTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.cts; - -import android.content.ContentResolver; -import android.content.Context; -import android.platform.test.annotations.AppModeFull; -import android.provider.Settings; -import android.test.AndroidTestCase; -import android.util.Log; - -import java.lang.Thread; - -@AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps") -public class AirplaneModeTest extends AndroidTestCase { - private static final String TAG = "AirplaneModeTest"; - private static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth"; - private static final String FEATURE_WIFI = "android.hardware.wifi"; - private static final int TIMEOUT_MS = 10 * 1000; - private boolean mHasFeature; - private Context mContext; - private ContentResolver resolver; - - public void setup() { - mContext= getContext(); - resolver = mContext.getContentResolver(); - mHasFeature = (mContext.getPackageManager().hasSystemFeature(FEATURE_BLUETOOTH) - || mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI)); - } - - public void testAirplaneMode() { - setup(); - if (!mHasFeature) { - Log.i(TAG, "The device doesn't support network bluetooth or wifi feature"); - return; - } - - for (int testCount = 0; testCount < 2; testCount++) { - if (!doOneTest()) { - fail("Airplane mode failed to change in " + TIMEOUT_MS + "msec"); - return; - } - } - } - - private boolean doOneTest() { - boolean airplaneModeOn = isAirplaneModeOn(); - setAirplaneModeOn(!airplaneModeOn); - - try { - Thread.sleep(TIMEOUT_MS); - } catch (InterruptedException e) { - Log.e(TAG, "Sleep time interrupted.", e); - } - - if (airplaneModeOn == isAirplaneModeOn()) { - return false; - } - return true; - } - - private void setAirplaneModeOn(boolean enabling) { - // Change the system setting for airplane mode - Settings.Global.putInt(resolver, Settings.Global.AIRPLANE_MODE_ON, enabling ? 1 : 0); - } - - private boolean isAirplaneModeOn() { - // Read the system setting for airplane mode - return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.AIRPLANE_MODE_ON, 0) != 0; - } -} diff --git a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt deleted file mode 100644 index eb5048fa9b..0000000000 --- a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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.cts - -import android.Manifest.permission.CONNECTIVITY_INTERNAL -import android.Manifest.permission.NETWORK_SETTINGS -import android.Manifest.permission.READ_DEVICE_CONFIG -import android.content.pm.PackageManager.FEATURE_TELEPHONY -import android.content.pm.PackageManager.FEATURE_WIFI -import android.net.ConnectivityManager -import android.net.ConnectivityManager.NetworkCallback -import android.net.Network -import android.net.NetworkCapabilities -import android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL -import android.net.NetworkCapabilities.TRANSPORT_WIFI -import android.net.NetworkRequest -import android.net.Uri -import android.net.cts.NetworkValidationTestUtil.clearValidationTestUrlsDeviceConfig -import android.net.cts.NetworkValidationTestUtil.setHttpUrlDeviceConfig -import android.net.cts.NetworkValidationTestUtil.setHttpsUrlDeviceConfig -import android.net.cts.NetworkValidationTestUtil.setUrlExpirationDeviceConfig -import android.net.cts.util.CtsNetUtils -import android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL -import android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL -import android.net.wifi.WifiManager -import android.os.Build -import android.platform.test.annotations.AppModeFull -import android.provider.DeviceConfig -import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY -import android.text.TextUtils -import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.TestHttpServer -import com.android.testutils.TestHttpServer.Request -import com.android.testutils.isDevSdkInRange -import com.android.testutils.runAsShell -import fi.iki.elonen.NanoHTTPD.Response.Status -import junit.framework.AssertionFailedError -import org.junit.After -import org.junit.Assume.assumeTrue -import org.junit.Before -import org.junit.runner.RunWith -import java.util.concurrent.CompletableFuture -import java.util.concurrent.TimeUnit -import java.util.concurrent.TimeoutException -import kotlin.test.Test -import kotlin.test.assertNotEquals -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - -private const val TEST_HTTPS_URL_PATH = "/https_path" -private const val TEST_HTTP_URL_PATH = "/http_path" -private const val TEST_PORTAL_URL_PATH = "/portal_path" - -private const val LOCALHOST_HOSTNAME = "localhost" - -// Re-connecting to the AP, obtaining an IP address, revalidating can take a long time -private const val WIFI_CONNECT_TIMEOUT_MS = 120_000L -private const val TEST_TIMEOUT_MS = 10_000L - -private fun CompletableFuture.assertGet(timeoutMs: Long, message: String): T { - try { - return get(timeoutMs, TimeUnit.MILLISECONDS) - } catch (e: TimeoutException) { - throw AssertionFailedError(message) - } -} - -@AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps") -@RunWith(AndroidJUnit4::class) -class CaptivePortalTest { - private val context: android.content.Context by lazy { getInstrumentation().context } - private val wm by lazy { context.getSystemService(WifiManager::class.java) } - private val cm by lazy { context.getSystemService(ConnectivityManager::class.java) } - private val pm by lazy { context.packageManager } - private val utils by lazy { CtsNetUtils(context) } - - private val server = TestHttpServer("localhost") - - @Before - fun setUp() { - runAsShell(READ_DEVICE_CONFIG) { - // Verify that the test URLs are not normally set on the device, but do not fail if the - // test URLs are set to what this test uses (URLs on localhost), in case the test was - // interrupted manually and rerun. - assertEmptyOrLocalhostUrl(TEST_CAPTIVE_PORTAL_HTTPS_URL) - assertEmptyOrLocalhostUrl(TEST_CAPTIVE_PORTAL_HTTP_URL) - } - clearValidationTestUrlsDeviceConfig() - server.start() - } - - @After - fun tearDown() { - clearValidationTestUrlsDeviceConfig() - if (pm.hasSystemFeature(FEATURE_WIFI)) { - reconnectWifi() - } - server.stop() - } - - private fun assertEmptyOrLocalhostUrl(urlKey: String) { - val url = DeviceConfig.getProperty(NAMESPACE_CONNECTIVITY, urlKey) - assertTrue(TextUtils.isEmpty(url) || LOCALHOST_HOSTNAME == Uri.parse(url).host, - "$urlKey must not be set in production scenarios (current value: $url)") - } - - @Test - fun testCaptivePortalIsNotDefaultNetwork() { - assumeTrue(pm.hasSystemFeature(FEATURE_TELEPHONY)) - assumeTrue(pm.hasSystemFeature(FEATURE_WIFI)) - utils.ensureWifiConnected() - utils.connectToCell() - - // Have network validation use a local server that serves a HTTPS error / HTTP redirect - server.addResponse(Request(TEST_PORTAL_URL_PATH), Status.OK, - content = "Test captive portal content") - server.addResponse(Request(TEST_HTTPS_URL_PATH), Status.INTERNAL_ERROR) - server.addResponse(Request(TEST_HTTP_URL_PATH), Status.REDIRECT, - locationHeader = makeUrl(TEST_PORTAL_URL_PATH)) - setHttpsUrlDeviceConfig(makeUrl(TEST_HTTPS_URL_PATH)) - setHttpUrlDeviceConfig(makeUrl(TEST_HTTP_URL_PATH)) - // URL expiration needs to be in the next 10 minutes - setUrlExpirationDeviceConfig(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(9)) - - // Wait for a captive portal to be detected on the network - val wifiNetworkFuture = CompletableFuture() - val wifiCb = object : NetworkCallback() { - override fun onCapabilitiesChanged( - network: Network, - nc: NetworkCapabilities - ) { - if (nc.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) { - wifiNetworkFuture.complete(network) - } - } - } - cm.requestNetwork(NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build(), wifiCb) - - try { - reconnectWifi() - val network = wifiNetworkFuture.assertGet(WIFI_CONNECT_TIMEOUT_MS, - "Captive portal not detected after ${WIFI_CONNECT_TIMEOUT_MS}ms") - - val wifiDefaultMessage = "Wifi should not be the default network when a captive " + - "portal was detected and another network (mobile data) can provide internet " + - "access." - assertNotEquals(network, cm.activeNetwork, wifiDefaultMessage) - - val startPortalAppPermission = - if (isDevSdkInRange(0, Build.VERSION_CODES.Q)) CONNECTIVITY_INTERNAL - else NETWORK_SETTINGS - runAsShell(startPortalAppPermission) { cm.startCaptivePortalApp(network) } - - // Expect the portal content to be fetched at some point after detecting the portal. - // Some implementations may fetch the URL before startCaptivePortalApp is called. - assertNotNull(server.requestsRecord.poll(TEST_TIMEOUT_MS, pos = 0) { - it.path == TEST_PORTAL_URL_PATH - }, "The captive portal login page was still not fetched ${TEST_TIMEOUT_MS}ms " + - "after startCaptivePortalApp.") - - assertNotEquals(network, cm.activeNetwork, wifiDefaultMessage) - } finally { - cm.unregisterNetworkCallback(wifiCb) - server.stop() - // disconnectFromCell should be called after connectToCell - utils.disconnectFromCell() - } - } - - /** - * Create a URL string that, when fetched, will hit the test server with the given URL [path]. - */ - private fun makeUrl(path: String) = "http://localhost:${server.listeningPort}" + path - - private fun reconnectWifi() { - utils.ensureWifiDisconnected(null /* wifiNetworkToCheck */) - utils.ensureWifiConnected() - } -} \ No newline at end of file diff --git a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java deleted file mode 100644 index 54509cd1df..0000000000 --- a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java +++ /dev/null @@ -1,576 +0,0 @@ -/* - * 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.cts; - -import static android.content.pm.PackageManager.FEATURE_TELEPHONY; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_VALIDATION_RESULT; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.NETWORK_VALIDATION_RESULT_VALID; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_TCP_METRICS; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_DNS_CONSECUTIVE_TIMEOUTS; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE; -import static android.net.ConnectivityDiagnosticsManager.persistableBundleEquals; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_TEST; -import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; - -import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity; -import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import android.annotation.NonNull; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.net.ConnectivityDiagnosticsManager; -import android.net.ConnectivityManager; -import android.net.LinkAddress; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.TestNetworkInterface; -import android.net.TestNetworkManager; -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; -import android.os.ParcelFileDescriptor; -import android.os.PersistableBundle; -import android.os.Process; -import android.platform.test.annotations.AppModeFull; -import android.telephony.CarrierConfigManager; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; -import android.util.Pair; - -import androidx.test.InstrumentationRegistry; - -import com.android.internal.telephony.uicc.IccUtils; -import com.android.internal.util.ArrayUtils; -import com.android.net.module.util.ArrayTrackRecord; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; -import com.android.testutils.DevSdkIgnoreRunner; -import com.android.testutils.SkipPresubmit; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.security.MessageDigest; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; - -@RunWith(DevSdkIgnoreRunner.class) -@IgnoreUpTo(Build.VERSION_CODES.Q) // ConnectivityDiagnosticsManager did not exist in Q -@AppModeFull(reason = "CHANGE_NETWORK_STATE, MANAGE_TEST_NETWORKS not grantable to instant apps") -public class ConnectivityDiagnosticsManagerTest { - private static final int CALLBACK_TIMEOUT_MILLIS = 5000; - private static final int NO_CALLBACK_INVOKED_TIMEOUT = 500; - private static final long TIMESTAMP = 123456789L; - private static final int DNS_CONSECUTIVE_TIMEOUTS = 5; - private static final int COLLECTION_PERIOD_MILLIS = 5000; - private static final int FAIL_RATE_PERCENTAGE = 100; - private static final int UNKNOWN_DETECTION_METHOD = 4; - private static final int FILTERED_UNKNOWN_DETECTION_METHOD = 0; - private static final int CARRIER_CONFIG_CHANGED_BROADCAST_TIMEOUT = 5000; - private static final int DELAY_FOR_ADMIN_UIDS_MILLIS = 2000; - - private static final Executor INLINE_EXECUTOR = x -> x.run(); - - private static final NetworkRequest TEST_NETWORK_REQUEST = - new NetworkRequest.Builder() - .addTransportType(TRANSPORT_TEST) - .removeCapability(NET_CAPABILITY_TRUSTED) - .removeCapability(NET_CAPABILITY_NOT_VPN) - .build(); - - private static final String SHA_256 = "SHA-256"; - - private static final NetworkRequest CELLULAR_NETWORK_REQUEST = - new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_INTERNET) - .build(); - - private static final IBinder BINDER = new Binder(); - - private Context mContext; - private ConnectivityManager mConnectivityManager; - private ConnectivityDiagnosticsManager mCdm; - private CarrierConfigManager mCarrierConfigManager; - private PackageManager mPackageManager; - private TelephonyManager mTelephonyManager; - - // Callback used to keep TestNetworks up when there are no other outstanding NetworkRequests - // for it. - private TestNetworkCallback mTestNetworkCallback; - private Network mTestNetwork; - private ParcelFileDescriptor mTestNetworkFD; - - private List mRegisteredCallbacks; - - @Before - public void setUp() throws Exception { - mContext = InstrumentationRegistry.getContext(); - mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); - mCdm = mContext.getSystemService(ConnectivityDiagnosticsManager.class); - mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); - mPackageManager = mContext.getPackageManager(); - mTelephonyManager = mContext.getSystemService(TelephonyManager.class); - - mTestNetworkCallback = new TestNetworkCallback(); - mConnectivityManager.requestNetwork(TEST_NETWORK_REQUEST, mTestNetworkCallback); - - mRegisteredCallbacks = new ArrayList<>(); - } - - @After - public void tearDown() throws Exception { - mConnectivityManager.unregisterNetworkCallback(mTestNetworkCallback); - if (mTestNetwork != null) { - runWithShellPermissionIdentity(() -> { - final TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class); - tnm.teardownTestNetwork(mTestNetwork); - }); - mTestNetwork = null; - } - - if (mTestNetworkFD != null) { - mTestNetworkFD.close(); - mTestNetworkFD = null; - } - - for (TestConnectivityDiagnosticsCallback cb : mRegisteredCallbacks) { - mCdm.unregisterConnectivityDiagnosticsCallback(cb); - } - } - - @Test - public void testRegisterConnectivityDiagnosticsCallback() throws Exception { - mTestNetworkFD = setUpTestNetwork().getFileDescriptor(); - mTestNetwork = mTestNetworkCallback.waitForAvailable(); - - final TestConnectivityDiagnosticsCallback cb = - createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); - - final String interfaceName = - mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName(); - - cb.expectOnConnectivityReportAvailable(mTestNetwork, interfaceName); - cb.assertNoCallback(); - } - - @SkipPresubmit(reason = "Flaky: b/159718782; add to presubmit after fixing") - @Test - public void testRegisterCallbackWithCarrierPrivileges() throws Exception { - assumeTrue(mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)); - - final int subId = SubscriptionManager.getDefaultSubscriptionId(); - if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - fail("Need an active subscription. Please ensure that the device has working mobile" - + " data."); - } - - final CarrierConfigReceiver carrierConfigReceiver = new CarrierConfigReceiver(subId); - mContext.registerReceiver( - carrierConfigReceiver, - new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - - final TestNetworkCallback testNetworkCallback = new TestNetworkCallback(); - - try { - doBroadcastCarrierConfigsAndVerifyOnConnectivityReportAvailable( - subId, carrierConfigReceiver, testNetworkCallback); - } finally { - runWithShellPermissionIdentity( - () -> mCarrierConfigManager.overrideConfig(subId, null), - android.Manifest.permission.MODIFY_PHONE_STATE); - mConnectivityManager.unregisterNetworkCallback(testNetworkCallback); - mContext.unregisterReceiver(carrierConfigReceiver); - } - } - - private String getCertHashForThisPackage() throws Exception { - final PackageInfo pkgInfo = - mPackageManager.getPackageInfo( - mContext.getOpPackageName(), PackageManager.GET_SIGNATURES); - final MessageDigest md = MessageDigest.getInstance(SHA_256); - final byte[] certHash = md.digest(pkgInfo.signatures[0].toByteArray()); - return IccUtils.bytesToHexString(certHash); - } - - private void doBroadcastCarrierConfigsAndVerifyOnConnectivityReportAvailable( - int subId, - @NonNull CarrierConfigReceiver carrierConfigReceiver, - @NonNull TestNetworkCallback testNetworkCallback) - throws Exception { - final PersistableBundle carrierConfigs = new PersistableBundle(); - carrierConfigs.putStringArray( - CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY, - new String[] {getCertHashForThisPackage()}); - - runWithShellPermissionIdentity( - () -> { - mCarrierConfigManager.overrideConfig(subId, carrierConfigs); - mCarrierConfigManager.notifyConfigChangedForSubId(subId); - }, - android.Manifest.permission.MODIFY_PHONE_STATE); - - // TODO(b/157779832): This should use android.permission.CHANGE_NETWORK_STATE. However, the - // shell does not have CHANGE_NETWORK_STATE, so use CONNECTIVITY_INTERNAL until the shell - // permissions are updated. - runWithShellPermissionIdentity( - () -> mConnectivityManager.requestNetwork( - CELLULAR_NETWORK_REQUEST, testNetworkCallback), - android.Manifest.permission.CONNECTIVITY_INTERNAL); - - final Network network = testNetworkCallback.waitForAvailable(); - assertNotNull(network); - - assertTrue("Didn't receive broadcast for ACTION_CARRIER_CONFIG_CHANGED for subId=" + subId, - carrierConfigReceiver.waitForCarrierConfigChanged()); - assertTrue("Don't have Carrier Privileges after adding cert for this package", - mTelephonyManager.createForSubscriptionId(subId).hasCarrierPrivileges()); - - // Wait for CarrierPrivilegesTracker to receive the ACTION_CARRIER_CONFIG_CHANGED - // broadcast. CPT then needs to update the corresponding DataConnection, which then - // updates ConnectivityService. Unfortunately, this update to the NetworkCapabilities in - // CS does not trigger NetworkCallback#onCapabilitiesChanged as changing the - // administratorUids is not a publicly visible change. In lieu of a better signal to - // detministically wait for, use Thread#sleep here. - // TODO(b/157949581): replace this Thread#sleep with a deterministic signal - Thread.sleep(DELAY_FOR_ADMIN_UIDS_MILLIS); - - final TestConnectivityDiagnosticsCallback connDiagsCallback = - createAndRegisterConnectivityDiagnosticsCallback(CELLULAR_NETWORK_REQUEST); - - final String interfaceName = - mConnectivityManager.getLinkProperties(network).getInterfaceName(); - connDiagsCallback.expectOnConnectivityReportAvailable( - network, interfaceName, TRANSPORT_CELLULAR); - connDiagsCallback.assertNoCallback(); - } - - @Test - public void testRegisterDuplicateConnectivityDiagnosticsCallback() { - final TestConnectivityDiagnosticsCallback cb = - createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); - - try { - mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb); - fail("Registering the same callback twice should throw an IllegalArgumentException"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testUnregisterConnectivityDiagnosticsCallback() { - final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback(); - mCdm.registerConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST, INLINE_EXECUTOR, cb); - mCdm.unregisterConnectivityDiagnosticsCallback(cb); - } - - @Test - public void testUnregisterUnknownConnectivityDiagnosticsCallback() { - // Expected to silently ignore the unregister() call - mCdm.unregisterConnectivityDiagnosticsCallback(new TestConnectivityDiagnosticsCallback()); - } - - @Test - public void testOnConnectivityReportAvailable() throws Exception { - final TestConnectivityDiagnosticsCallback cb = - createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); - - mTestNetworkFD = setUpTestNetwork().getFileDescriptor(); - mTestNetwork = mTestNetworkCallback.waitForAvailable(); - - final String interfaceName = - mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName(); - - cb.expectOnConnectivityReportAvailable(mTestNetwork, interfaceName); - cb.assertNoCallback(); - } - - @Test - public void testOnDataStallSuspected_DnsEvents() throws Exception { - final PersistableBundle extras = new PersistableBundle(); - extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, DNS_CONSECUTIVE_TIMEOUTS); - - verifyOnDataStallSuspected(DETECTION_METHOD_DNS_EVENTS, TIMESTAMP, extras); - } - - @Test - public void testOnDataStallSuspected_TcpMetrics() throws Exception { - final PersistableBundle extras = new PersistableBundle(); - extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, COLLECTION_PERIOD_MILLIS); - extras.putInt(KEY_TCP_PACKET_FAIL_RATE, FAIL_RATE_PERCENTAGE); - - verifyOnDataStallSuspected(DETECTION_METHOD_TCP_METRICS, TIMESTAMP, extras); - } - - @Test - public void testOnDataStallSuspected_UnknownDetectionMethod() throws Exception { - verifyOnDataStallSuspected( - UNKNOWN_DETECTION_METHOD, - FILTERED_UNKNOWN_DETECTION_METHOD, - TIMESTAMP, - PersistableBundle.EMPTY); - } - - private void verifyOnDataStallSuspected( - int detectionMethod, long timestampMillis, @NonNull PersistableBundle extras) - throws Exception { - // Input detection method is expected to match received detection method - verifyOnDataStallSuspected(detectionMethod, detectionMethod, timestampMillis, extras); - } - - private void verifyOnDataStallSuspected( - int inputDetectionMethod, - int expectedDetectionMethod, - long timestampMillis, - @NonNull PersistableBundle extras) - throws Exception { - mTestNetworkFD = setUpTestNetwork().getFileDescriptor(); - mTestNetwork = mTestNetworkCallback.waitForAvailable(); - - final TestConnectivityDiagnosticsCallback cb = - createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); - - final String interfaceName = - mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName(); - - cb.expectOnConnectivityReportAvailable(mTestNetwork, interfaceName); - - runWithShellPermissionIdentity( - () -> mConnectivityManager.simulateDataStall( - inputDetectionMethod, timestampMillis, mTestNetwork, extras), - android.Manifest.permission.MANAGE_TEST_NETWORKS); - - cb.expectOnDataStallSuspected( - mTestNetwork, interfaceName, expectedDetectionMethod, timestampMillis, extras); - cb.assertNoCallback(); - } - - @Test - public void testOnNetworkConnectivityReportedTrue() throws Exception { - verifyOnNetworkConnectivityReported(true /* hasConnectivity */); - } - - @Test - public void testOnNetworkConnectivityReportedFalse() throws Exception { - verifyOnNetworkConnectivityReported(false /* hasConnectivity */); - } - - private void verifyOnNetworkConnectivityReported(boolean hasConnectivity) throws Exception { - mTestNetworkFD = setUpTestNetwork().getFileDescriptor(); - mTestNetwork = mTestNetworkCallback.waitForAvailable(); - - final TestConnectivityDiagnosticsCallback cb = - createAndRegisterConnectivityDiagnosticsCallback(TEST_NETWORK_REQUEST); - - // onConnectivityReportAvailable always invoked when the test network is established - final String interfaceName = - mConnectivityManager.getLinkProperties(mTestNetwork).getInterfaceName(); - cb.expectOnConnectivityReportAvailable(mTestNetwork, interfaceName); - cb.assertNoCallback(); - - mConnectivityManager.reportNetworkConnectivity(mTestNetwork, hasConnectivity); - - cb.expectOnNetworkConnectivityReported(mTestNetwork, hasConnectivity); - - // if hasConnectivity does not match the network's known connectivity, it will be - // revalidated which will trigger another onConnectivityReportAvailable callback. - if (!hasConnectivity) { - cb.expectOnConnectivityReportAvailable(mTestNetwork, interfaceName); - } - - cb.assertNoCallback(); - } - - private TestConnectivityDiagnosticsCallback createAndRegisterConnectivityDiagnosticsCallback( - NetworkRequest request) { - final TestConnectivityDiagnosticsCallback cb = new TestConnectivityDiagnosticsCallback(); - mCdm.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, cb); - mRegisteredCallbacks.add(cb); - return cb; - } - - /** - * Registers a test NetworkAgent with ConnectivityService with limited capabilities, which leads - * to the Network being validated. - */ - @NonNull - private TestNetworkInterface setUpTestNetwork() throws Exception { - final int[] administratorUids = new int[] {Process.myUid()}; - return callWithShellPermissionIdentity( - () -> { - final TestNetworkManager tnm = - mContext.getSystemService(TestNetworkManager.class); - final TestNetworkInterface tni = tnm.createTunInterface(new LinkAddress[0]); - tnm.setupTestNetwork(tni.getInterfaceName(), administratorUids, BINDER); - return tni; - }); - } - - private static class TestConnectivityDiagnosticsCallback - extends ConnectivityDiagnosticsCallback { - private final ArrayTrackRecord.ReadHead mHistory = - new ArrayTrackRecord().newReadHead(); - - @Override - public void onConnectivityReportAvailable(ConnectivityReport report) { - mHistory.add(report); - } - - @Override - public void onDataStallSuspected(DataStallReport report) { - mHistory.add(report); - } - - @Override - public void onNetworkConnectivityReported(Network network, boolean hasConnectivity) { - mHistory.add(new Pair(network, hasConnectivity)); - } - - public void expectOnConnectivityReportAvailable( - @NonNull Network network, @NonNull String interfaceName) { - expectOnConnectivityReportAvailable(network, interfaceName, TRANSPORT_TEST); - } - - public void expectOnConnectivityReportAvailable( - @NonNull Network network, @NonNull String interfaceName, int transportType) { - final ConnectivityReport result = - (ConnectivityReport) mHistory.poll(CALLBACK_TIMEOUT_MILLIS, x -> true); - assertEquals(network, result.getNetwork()); - - final NetworkCapabilities nc = result.getNetworkCapabilities(); - assertNotNull(nc); - assertTrue(nc.hasTransport(transportType)); - assertNotNull(result.getLinkProperties()); - assertEquals(interfaceName, result.getLinkProperties().getInterfaceName()); - - final PersistableBundle extras = result.getAdditionalInfo(); - assertTrue(extras.containsKey(KEY_NETWORK_VALIDATION_RESULT)); - final int validationResult = extras.getInt(KEY_NETWORK_VALIDATION_RESULT); - assertEquals("Network validation result is not 'valid'", - NETWORK_VALIDATION_RESULT_VALID, validationResult); - - assertTrue(extras.containsKey(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK)); - final int probesSucceeded = extras.getInt(KEY_NETWORK_VALIDATION_RESULT); - assertTrue("PROBES_SUCCEEDED mask not in expected range", probesSucceeded >= 0); - - assertTrue(extras.containsKey(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK)); - final int probesAttempted = extras.getInt(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK); - assertTrue("PROBES_ATTEMPTED mask not in expected range", probesAttempted >= 0); - } - - public void expectOnDataStallSuspected( - @NonNull Network network, - @NonNull String interfaceName, - int detectionMethod, - long timestampMillis, - @NonNull PersistableBundle extras) { - final DataStallReport result = - (DataStallReport) mHistory.poll(CALLBACK_TIMEOUT_MILLIS, x -> true); - assertEquals(network, result.getNetwork()); - assertEquals(detectionMethod, result.getDetectionMethod()); - assertEquals(timestampMillis, result.getReportTimestamp()); - - final NetworkCapabilities nc = result.getNetworkCapabilities(); - assertNotNull(nc); - assertTrue(nc.hasTransport(TRANSPORT_TEST)); - assertNotNull(result.getLinkProperties()); - assertEquals(interfaceName, result.getLinkProperties().getInterfaceName()); - - assertTrue(persistableBundleEquals(extras, result.getStallDetails())); - } - - public void expectOnNetworkConnectivityReported( - @NonNull Network network, boolean hasConnectivity) { - final Pair result = - (Pair) mHistory.poll(CALLBACK_TIMEOUT_MILLIS, x -> true); - assertEquals(network, result.first /* network */); - assertEquals(hasConnectivity, result.second /* hasConnectivity */); - } - - public void assertNoCallback() { - // If no more callbacks exist, there should be nothing left in the ReadHead - assertNull("Unexpected event in history", - mHistory.poll(NO_CALLBACK_INVOKED_TIMEOUT, x -> true)); - } - } - - private class CarrierConfigReceiver extends BroadcastReceiver { - private final CountDownLatch mLatch = new CountDownLatch(1); - private final int mSubId; - - CarrierConfigReceiver(int subId) { - mSubId = subId; - } - - @Override - public void onReceive(Context context, Intent intent) { - if (!CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) { - return; - } - - final int subId = - intent.getIntExtra( - CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, - SubscriptionManager.INVALID_SUBSCRIPTION_ID); - if (mSubId != subId) return; - - final PersistableBundle carrierConfigs = mCarrierConfigManager.getConfigForSubId(subId); - if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfigs)) return; - - final String[] certs = - carrierConfigs.getStringArray( - CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY); - try { - if (ArrayUtils.contains(certs, getCertHashForThisPackage())) { - mLatch.countDown(); - } - } catch (Exception e) { - } - } - - boolean waitForCarrierConfigChanged() throws Exception { - return mLatch.await(CARRIER_CONFIG_CHANGED_BROADCAST_TIMEOUT, TimeUnit.MILLISECONDS); - } - } -} diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java deleted file mode 100644 index b7cc95dc9a..0000000000 --- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java +++ /dev/null @@ -1,1384 +0,0 @@ -/* - * Copyright (C) 2009 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.cts; - -import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; -import static android.content.pm.PackageManager.FEATURE_ETHERNET; -import static android.content.pm.PackageManager.FEATURE_TELEPHONY; -import static android.content.pm.PackageManager.FEATURE_USB_HOST; -import static android.content.pm.PackageManager.FEATURE_WIFI; -import static android.content.pm.PackageManager.GET_PERMISSIONS; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static android.net.cts.util.CtsNetUtils.ConnectivityActionReceiver; -import static android.net.cts.util.CtsNetUtils.HTTP_PORT; -import static android.net.cts.util.CtsNetUtils.NETWORK_CALLBACK_ACTION; -import static android.net.cts.util.CtsNetUtils.TEST_HOST; -import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; -import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; -import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; -import static android.system.OsConstants.AF_UNSPEC; - -import static com.android.compatibility.common.util.SystemUtil.runShellCommand; -import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import android.annotation.NonNull; -import android.app.Instrumentation; -import android.app.PendingIntent; -import android.app.UiAutomation; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.IpSecManager; -import android.net.IpSecManager.UdpEncapsulationSocket; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkConfig; -import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; -import android.net.NetworkInfo.State; -import android.net.NetworkRequest; -import android.net.NetworkUtils; -import android.net.SocketKeepalive; -import android.net.cts.util.CtsNetUtils; -import android.net.util.KeepaliveUtils; -import android.net.wifi.WifiManager; -import android.os.Binder; -import android.os.Build; -import android.os.Looper; -import android.os.MessageQueue; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.os.VintfRuntimeInfo; -import android.platform.test.annotations.AppModeFull; -import android.provider.Settings; -import android.text.TextUtils; -import android.util.Log; -import android.util.Pair; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.ArrayUtils; -import com.android.testutils.SkipPresubmit; - -import libcore.io.Streams; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.URL; -import java.net.UnknownHostException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@RunWith(AndroidJUnit4.class) -public class ConnectivityManagerTest { - - private static final String TAG = ConnectivityManagerTest.class.getSimpleName(); - - public static final int TYPE_MOBILE = ConnectivityManager.TYPE_MOBILE; - public static final int TYPE_WIFI = ConnectivityManager.TYPE_WIFI; - - private static final int HOST_ADDRESS = 0x7f000001;// represent ip 127.0.0.1 - private static final int KEEPALIVE_CALLBACK_TIMEOUT_MS = 2000; - private static final int INTERVAL_KEEPALIVE_RETRY_MS = 500; - private static final int MAX_KEEPALIVE_RETRY_COUNT = 3; - private static final int MIN_KEEPALIVE_INTERVAL = 10; - - // Changing meteredness on wifi involves reconnecting, which can take several seconds (involves - // re-associating, DHCP...) - private static final int NETWORK_CHANGE_METEREDNESS_TIMEOUT = 30_000; - private static final int NUM_TRIES_MULTIPATH_PREF_CHECK = 20; - private static final long INTERVAL_MULTIPATH_PREF_CHECK_MS = 500; - // device could have only one interface: data, wifi. - private static final int MIN_NUM_NETWORK_TYPES = 1; - - // Minimum supported keepalive counts for wifi and cellular. - public static final int MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT = 1; - public static final int MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT = 3; - - private static final String NETWORK_METERED_MULTIPATH_PREFERENCE_RES_NAME = - "config_networkMeteredMultipathPreference"; - private static final String KEEPALIVE_ALLOWED_UNPRIVILEGED_RES_NAME = - "config_allowedUnprivilegedKeepalivePerUid"; - private static final String KEEPALIVE_RESERVED_PER_SLOT_RES_NAME = - "config_reservedPrivilegedKeepaliveSlots"; - - private Context mContext; - private Instrumentation mInstrumentation; - private ConnectivityManager mCm; - private WifiManager mWifiManager; - private PackageManager mPackageManager; - private final HashMap mNetworks = - new HashMap(); - boolean mWifiWasDisabled; - private UiAutomation mUiAutomation; - private CtsNetUtils mCtsNetUtils; - - @Before - public void setUp() throws Exception { - mInstrumentation = InstrumentationRegistry.getInstrumentation(); - mContext = mInstrumentation.getContext(); - mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - mPackageManager = mContext.getPackageManager(); - mCtsNetUtils = new CtsNetUtils(mContext); - mWifiWasDisabled = false; - - // Get com.android.internal.R.array.networkAttributes - int resId = mContext.getResources().getIdentifier("networkAttributes", "array", "android"); - String[] naStrings = mContext.getResources().getStringArray(resId); - //TODO: What is the "correct" way to determine if this is a wifi only device? - boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false); - for (String naString : naStrings) { - try { - NetworkConfig n = new NetworkConfig(naString); - if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) { - continue; - } - mNetworks.put(n.type, n); - } catch (Exception e) {} - } - mUiAutomation = mInstrumentation.getUiAutomation(); - } - - @After - public void tearDown() throws Exception { - // Return WiFi to its original disabled state after tests that explicitly connect. - if (mWifiWasDisabled) { - mCtsNetUtils.disconnectFromWifi(null); - } - if (mCtsNetUtils.cellConnectAttempted()) { - mCtsNetUtils.disconnectFromCell(); - } - - // All tests in this class require a working Internet connection as they start. Make - // sure there is still one as they end that's ready to use for the next test to use. - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(callback); - try { - assertNotNull("Couldn't restore Internet connectivity", callback.waitForAvailable()); - } finally { - mCm.unregisterNetworkCallback(callback); - } - } - - /** - * Make sure WiFi is connected to an access point if it is not already. If - * WiFi is enabled as a result of this function, it will be disabled - * automatically in tearDown(). - */ - private Network ensureWifiConnected() { - mWifiWasDisabled = !mWifiManager.isWifiEnabled(); - // Even if wifi is enabled, the network may not be connected or ready yet - return mCtsNetUtils.connectToWifi(); - } - - @Test - public void testIsNetworkTypeValid() { - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE)); - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI)); - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_MMS)); - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_SUPL)); - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_DUN)); - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_HIPRI)); - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIMAX)); - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_BLUETOOTH)); - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_DUMMY)); - assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_ETHERNET)); - assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_FOTA)); - assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_IMS)); - assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_CBS)); - assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI_P2P)); - assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_IA)); - assertFalse(mCm.isNetworkTypeValid(-1)); - assertTrue(mCm.isNetworkTypeValid(0)); - assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.MAX_NETWORK_TYPE)); - assertFalse(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.MAX_NETWORK_TYPE+1)); - - NetworkInfo[] ni = mCm.getAllNetworkInfo(); - - for (NetworkInfo n: ni) { - assertTrue(ConnectivityManager.isNetworkTypeValid(n.getType())); - } - - } - - @Test - public void testSetNetworkPreference() { - // getNetworkPreference() and setNetworkPreference() are both deprecated so they do - // not preform any action. Verify they are at least still callable. - mCm.setNetworkPreference(mCm.getNetworkPreference()); - } - - @Test - public void testGetActiveNetworkInfo() { - NetworkInfo ni = mCm.getActiveNetworkInfo(); - - assertNotNull("You must have an active network connection to complete CTS", ni); - assertTrue(ConnectivityManager.isNetworkTypeValid(ni.getType())); - assertTrue(ni.getState() == State.CONNECTED); - } - - @Test - public void testGetActiveNetwork() { - Network network = mCm.getActiveNetwork(); - assertNotNull("You must have an active network connection to complete CTS", network); - - NetworkInfo ni = mCm.getNetworkInfo(network); - assertNotNull("Network returned from getActiveNetwork was invalid", ni); - - // Similar to testGetActiveNetworkInfo above. - assertTrue(ConnectivityManager.isNetworkTypeValid(ni.getType())); - assertTrue(ni.getState() == State.CONNECTED); - } - - @Test - public void testGetNetworkInfo() { - for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) { - if (shouldBeSupported(type)) { - NetworkInfo ni = mCm.getNetworkInfo(type); - assertTrue("Info shouldn't be null for " + type, ni != null); - State state = ni.getState(); - assertTrue("Bad state for " + type, State.UNKNOWN.ordinal() >= state.ordinal() - && state.ordinal() >= State.CONNECTING.ordinal()); - DetailedState ds = ni.getDetailedState(); - assertTrue("Bad detailed state for " + type, - DetailedState.FAILED.ordinal() >= ds.ordinal() - && ds.ordinal() >= DetailedState.IDLE.ordinal()); - } else { - assertNull("Info should be null for " + type, mCm.getNetworkInfo(type)); - } - } - } - - @Test - public void testGetAllNetworkInfo() { - NetworkInfo[] ni = mCm.getAllNetworkInfo(); - assertTrue(ni.length >= MIN_NUM_NETWORK_TYPES); - for (int type = 0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) { - int desiredFoundCount = (shouldBeSupported(type) ? 1 : 0); - int foundCount = 0; - for (NetworkInfo i : ni) { - if (i.getType() == type) foundCount++; - } - if (foundCount != desiredFoundCount) { - Log.e(TAG, "failure in testGetAllNetworkInfo. Dump of returned NetworkInfos:"); - for (NetworkInfo networkInfo : ni) Log.e(TAG, " " + networkInfo); - } - assertTrue("Unexpected foundCount of " + foundCount + " for type " + type, - foundCount == desiredFoundCount); - } - } - - /** - * Tests that connections can be opened on WiFi and cellphone networks, - * and that they are made from different IP addresses. - */ - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - @SkipPresubmit(reason = "Virtual devices use a single internet connection for all networks") - public void testOpenConnection() throws Exception { - boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI) - && mPackageManager.hasSystemFeature(FEATURE_TELEPHONY); - if (!canRunTest) { - Log.i(TAG,"testOpenConnection cannot execute unless device supports both WiFi " - + "and a cellular connection"); - return; - } - - Network wifiNetwork = mCtsNetUtils.connectToWifi(); - Network cellNetwork = mCtsNetUtils.connectToCell(); - // This server returns the requestor's IP address as the response body. - URL url = new URL("http://google-ipv6test.appspot.com/ip.js?fmt=text"); - String wifiAddressString = httpGet(wifiNetwork, url); - String cellAddressString = httpGet(cellNetwork, url); - - assertFalse(String.format("Same address '%s' on two different networks (%s, %s)", - wifiAddressString, wifiNetwork, cellNetwork), - wifiAddressString.equals(cellAddressString)); - - // Sanity check that the IP addresses that the requests appeared to come from - // are actually on the respective networks. - assertOnNetwork(wifiAddressString, wifiNetwork); - assertOnNetwork(cellAddressString, cellNetwork); - - assertFalse("Unexpectedly equal: " + wifiNetwork, wifiNetwork.equals(cellNetwork)); - } - - /** - * Performs a HTTP GET to the specified URL on the specified Network, and returns - * the response body decoded as UTF-8. - */ - private static String httpGet(Network network, URL httpUrl) throws IOException { - HttpURLConnection connection = (HttpURLConnection) network.openConnection(httpUrl); - try { - InputStream inputStream = connection.getInputStream(); - return Streams.readFully(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); - } finally { - connection.disconnect(); - } - } - - private void assertOnNetwork(String adressString, Network network) throws UnknownHostException { - InetAddress address = InetAddress.getByName(adressString); - LinkProperties linkProperties = mCm.getLinkProperties(network); - // To make sure that the request went out on the right network, check that - // the IP address seen by the server is assigned to the expected network. - // We can only do this for IPv6 addresses, because in IPv4 we will likely - // have a private IPv4 address, and that won't match what the server sees. - if (address instanceof Inet6Address) { - assertContains(linkProperties.getAddresses(), address); - } - } - - private static void assertContains(Collection collection, T element) { - assertTrue(element + " not found in " + collection, collection.contains(element)); - } - - private void assertStartUsingNetworkFeatureUnsupported(int networkType, String feature) { - try { - mCm.startUsingNetworkFeature(networkType, feature); - fail("startUsingNetworkFeature is no longer supported in the current API version"); - } catch (UnsupportedOperationException expected) {} - } - - private void assertStopUsingNetworkFeatureUnsupported(int networkType, String feature) { - try { - mCm.startUsingNetworkFeature(networkType, feature); - fail("stopUsingNetworkFeature is no longer supported in the current API version"); - } catch (UnsupportedOperationException expected) {} - } - - private void assertRequestRouteToHostUnsupported(int networkType, int hostAddress) { - try { - mCm.requestRouteToHost(networkType, hostAddress); - fail("requestRouteToHost is no longer supported in the current API version"); - } catch (UnsupportedOperationException expected) {} - } - - @Test - public void testStartUsingNetworkFeature() { - - final String invalidateFeature = "invalidateFeature"; - final String mmsFeature = "enableMMS"; - - assertStartUsingNetworkFeatureUnsupported(TYPE_MOBILE, invalidateFeature); - assertStopUsingNetworkFeatureUnsupported(TYPE_MOBILE, invalidateFeature); - assertStartUsingNetworkFeatureUnsupported(TYPE_WIFI, mmsFeature); - } - - private boolean shouldEthernetBeSupported() { - // Instant mode apps aren't allowed to query the Ethernet service due to selinux policies. - // When in instant mode, don't fail if the Ethernet service is available. Instead, rely on - // the fact that Ethernet should be supported if the device has a hardware Ethernet port, or - // if the device can be a USB host and thus can use USB Ethernet adapters. - // - // Note that this test this will still fail in instant mode if a device supports Ethernet - // via other hardware means. We are not currently aware of any such device. - return (mContext.getSystemService(Context.ETHERNET_SERVICE) != null) || - mPackageManager.hasSystemFeature(FEATURE_ETHERNET) || - mPackageManager.hasSystemFeature(FEATURE_USB_HOST); - } - - private boolean shouldBeSupported(int networkType) { - return mNetworks.containsKey(networkType) || - (networkType == ConnectivityManager.TYPE_VPN) || - (networkType == ConnectivityManager.TYPE_ETHERNET && shouldEthernetBeSupported()); - } - - @Test - public void testIsNetworkSupported() { - for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) { - boolean supported = mCm.isNetworkSupported(type); - if (shouldBeSupported(type)) { - assertTrue("Network type " + type + " should be supported", supported); - } else { - assertFalse("Network type " + type + " should not be supported", supported); - } - } - } - - @Test - public void testRequestRouteToHost() { - for (int type = -1 ; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) { - assertRequestRouteToHostUnsupported(type, HOST_ADDRESS); - } - } - - @Test - public void testTest() { - mCm.getBackgroundDataSetting(); - } - - private NetworkRequest makeWifiNetworkRequest() { - return new NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .build(); - } - - /** - * Exercises both registerNetworkCallback and unregisterNetworkCallback. This checks to - * see if we get a callback for the TRANSPORT_WIFI transport type being available. - * - *

In order to test that a NetworkCallback occurs, we need some change in the network - * state (either a transport or capability is now available). The most straightforward is - * WiFi. We could add a version that uses the telephony data connection but it's not clear - * that it would increase test coverage by much (how many devices have 3G radio but not Wifi?). - */ - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - public void testRegisterNetworkCallback() { - if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { - Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi"); - return; - } - - // We will register for a WIFI network being available or lost. - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback); - - final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(defaultTrackingCallback); - - Network wifiNetwork = null; - - try { - ensureWifiConnected(); - - // Now we should expect to get a network callback about availability of the wifi - // network even if it was already connected as a state-based action when the callback - // is registered. - wifiNetwork = callback.waitForAvailable(); - assertNotNull("Did not receive NetworkCallback.onAvailable for TRANSPORT_WIFI", - wifiNetwork); - - assertNotNull("Did not receive NetworkCallback.onAvailable for any default network", - defaultTrackingCallback.waitForAvailable()); - } catch (InterruptedException e) { - fail("Broadcast receiver or NetworkCallback wait was interrupted."); - } finally { - mCm.unregisterNetworkCallback(callback); - mCm.unregisterNetworkCallback(defaultTrackingCallback); - } - } - - /** - * Tests both registerNetworkCallback and unregisterNetworkCallback similarly to - * {@link #testRegisterNetworkCallback} except that a {@code PendingIntent} is used instead - * of a {@code NetworkCallback}. - */ - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - public void testRegisterNetworkCallback_withPendingIntent() { - if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { - Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi"); - return; - } - - // Create a ConnectivityActionReceiver that has an IntentFilter for our locally defined - // action, NETWORK_CALLBACK_ACTION. - IntentFilter filter = new IntentFilter(); - filter.addAction(NETWORK_CALLBACK_ACTION); - - ConnectivityActionReceiver receiver = new ConnectivityActionReceiver( - mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED); - mContext.registerReceiver(receiver, filter); - - // Create a broadcast PendingIntent for NETWORK_CALLBACK_ACTION. - Intent intent = new Intent(NETWORK_CALLBACK_ACTION); - PendingIntent pendingIntent = PendingIntent.getBroadcast( - mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); - - // We will register for a WIFI network being available or lost. - mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent); - - try { - ensureWifiConnected(); - - // Now we expect to get the Intent delivered notifying of the availability of the wifi - // network even if it was already connected as a state-based action when the callback - // is registered. - assertTrue("Did not receive expected Intent " + intent + " for TRANSPORT_WIFI", - receiver.waitForState()); - } catch (InterruptedException e) { - fail("Broadcast receiver or NetworkCallback wait was interrupted."); - } finally { - mCm.unregisterNetworkCallback(pendingIntent); - pendingIntent.cancel(); - mContext.unregisterReceiver(receiver); - } - } - - /** - * Exercises the requestNetwork with NetworkCallback API. This checks to - * see if we get a callback for an INTERNET request. - */ - @AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps") - @Test - public void testRequestNetworkCallback() { - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.requestNetwork(new NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build(), callback); - - try { - // Wait to get callback for availability of internet - Network internetNetwork = callback.waitForAvailable(); - assertNotNull("Did not receive NetworkCallback#onAvailable for INTERNET", - internetNetwork); - } catch (InterruptedException e) { - fail("NetworkCallback wait was interrupted."); - } finally { - mCm.unregisterNetworkCallback(callback); - } - } - - /** - * Exercises the requestNetwork with NetworkCallback API with timeout - expected to - * fail. Use WIFI and switch Wi-Fi off. - */ - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - public void testRequestNetworkCallback_onUnavailable() { - final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled(); - if (previousWifiEnabledState) { - mCtsNetUtils.ensureWifiDisconnected(null); - } - - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.requestNetwork(new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI) - .build(), callback, 100); - - try { - // Wait to get callback for unavailability of requested network - assertTrue("Did not receive NetworkCallback#onUnavailable", - callback.waitForUnavailable()); - } catch (InterruptedException e) { - fail("NetworkCallback wait was interrupted."); - } finally { - mCm.unregisterNetworkCallback(callback); - if (previousWifiEnabledState) { - mCtsNetUtils.connectToWifi(); - } - } - } - - private InetAddress getFirstV4Address(Network network) { - LinkProperties linkProperties = mCm.getLinkProperties(network); - for (InetAddress address : linkProperties.getAddresses()) { - if (address instanceof Inet4Address) { - return address; - } - } - return null; - } - - /** Verify restricted networks cannot be requested. */ - @AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps") - @Test - public void testRestrictedNetworks() { - // Verify we can request unrestricted networks: - NetworkRequest request = new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_INTERNET).build(); - NetworkCallback callback = new NetworkCallback(); - mCm.requestNetwork(request, callback); - mCm.unregisterNetworkCallback(callback); - // Verify we cannot request restricted networks: - request = new NetworkRequest.Builder().addCapability(NET_CAPABILITY_IMS).build(); - callback = new NetworkCallback(); - try { - mCm.requestNetwork(request, callback); - fail("No exception thrown when restricted network requested."); - } catch (SecurityException expected) {} - } - - // Returns "true", "false" or "none" - private String getWifiMeteredStatus(String ssid) throws Exception { - // Interestingly giving the SSID as an argument to list wifi-networks - // only works iff the network in question has the "false" policy. - // Also unfortunately runShellCommand does not pass the command to the interpreter - // so it's not possible to | grep the ssid. - final String command = "cmd netpolicy list wifi-networks"; - final String policyString = runShellCommand(mInstrumentation, command); - - final Matcher m = Pattern.compile("^" + ssid + ";(true|false|none)$", - Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString); - if (!m.find()) { - fail("Unexpected format from cmd netpolicy"); - } - return m.group(1); - } - - // metered should be "true", "false" or "none" - private void setWifiMeteredStatus(String ssid, String metered) throws Exception { - final String setCommand = "cmd netpolicy set metered-network " + ssid + " " + metered; - runShellCommand(mInstrumentation, setCommand); - assertEquals(getWifiMeteredStatus(ssid), metered); - } - - private String unquoteSSID(String ssid) { - // SSID is returned surrounded by quotes if it can be decoded as UTF-8. - // Otherwise it's guaranteed not to start with a quote. - if (ssid.charAt(0) == '"') { - return ssid.substring(1, ssid.length() - 1); - } else { - return ssid; - } - } - - private void waitForActiveNetworkMetered(int targetTransportType, boolean requestedMeteredness) - throws Exception { - final CountDownLatch latch = new CountDownLatch(1); - final NetworkCallback networkCallback = new NetworkCallback() { - @Override - public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) { - if (!nc.hasTransport(targetTransportType)) return; - - final boolean metered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED); - if (metered == requestedMeteredness) { - latch.countDown(); - } - } - }; - // Registering a callback here guarantees onCapabilitiesChanged is called immediately - // with the current setting. Therefore, if the setting has already been changed, - // this method will return right away, and if not it will wait for the setting to change. - mCm.registerDefaultNetworkCallback(networkCallback); - if (!latch.await(NETWORK_CHANGE_METEREDNESS_TIMEOUT, TimeUnit.MILLISECONDS)) { - fail("Timed out waiting for active network metered status to change to " - + requestedMeteredness + " ; network = " + mCm.getActiveNetwork()); - } - mCm.unregisterNetworkCallback(networkCallback); - } - - private void assertMultipathPreferenceIsEventually(Network network, int oldValue, - int expectedValue) { - // Sanity check : if oldValue == expectedValue, there is no way to guarantee the test - // is not flaky. - assertNotSame(oldValue, expectedValue); - - for (int i = 0; i < NUM_TRIES_MULTIPATH_PREF_CHECK; ++i) { - final int actualValue = mCm.getMultipathPreference(network); - if (actualValue == expectedValue) { - return; - } - if (actualValue != oldValue) { - fail("Multipath preference is neither previous (" + oldValue - + ") nor expected (" + expectedValue + ")"); - } - SystemClock.sleep(INTERVAL_MULTIPATH_PREF_CHECK_MS); - } - fail("Timed out waiting for multipath preference to change. expected = " - + expectedValue + " ; actual = " + mCm.getMultipathPreference(network)); - } - - private int getCurrentMeteredMultipathPreference(ContentResolver resolver) { - final String rawMeteredPref = Settings.Global.getString(resolver, - NETWORK_METERED_MULTIPATH_PREFERENCE); - return TextUtils.isEmpty(rawMeteredPref) - ? getIntResourceForName(NETWORK_METERED_MULTIPATH_PREFERENCE_RES_NAME) - : Integer.parseInt(rawMeteredPref); - } - - private int findNextPrefValue(ContentResolver resolver) { - // A bit of a nuclear hammer, but race conditions in CTS are bad. To be able to - // detect a correct setting value without race conditions, the next pref must - // be a valid value (range 0..3) that is different from the old setting of the - // metered preference and from the unmetered preference. - final int meteredPref = getCurrentMeteredMultipathPreference(resolver); - final int unmeteredPref = ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED; - if (0 != meteredPref && 0 != unmeteredPref) return 0; - if (1 != meteredPref && 1 != unmeteredPref) return 1; - return 2; - } - - /** - * Verify that getMultipathPreference does return appropriate values - * for metered and unmetered networks. - */ - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - public void testGetMultipathPreference() throws Exception { - final ContentResolver resolver = mContext.getContentResolver(); - ensureWifiConnected(); - final String ssid = unquoteSSID(mWifiManager.getConnectionInfo().getSSID()); - final String oldMeteredSetting = getWifiMeteredStatus(ssid); - final String oldMeteredMultipathPreference = Settings.Global.getString( - resolver, NETWORK_METERED_MULTIPATH_PREFERENCE); - try { - final int initialMeteredPreference = getCurrentMeteredMultipathPreference(resolver); - int newMeteredPreference = findNextPrefValue(resolver); - Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, - Integer.toString(newMeteredPreference)); - setWifiMeteredStatus(ssid, "true"); - waitForActiveNetworkMetered(TRANSPORT_WIFI, true); - // Wifi meterness changes from unmetered to metered will disconnect and reconnect since - // R. - final Network network = ensureWifiConnected(); - assertEquals(ssid, unquoteSSID(mWifiManager.getConnectionInfo().getSSID())); - assertEquals(mCm.getNetworkCapabilities(network).hasCapability( - NET_CAPABILITY_NOT_METERED), false); - assertMultipathPreferenceIsEventually(network, initialMeteredPreference, - newMeteredPreference); - - final int oldMeteredPreference = newMeteredPreference; - newMeteredPreference = findNextPrefValue(resolver); - Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, - Integer.toString(newMeteredPreference)); - assertEquals(mCm.getNetworkCapabilities(network).hasCapability( - NET_CAPABILITY_NOT_METERED), false); - assertMultipathPreferenceIsEventually(network, - oldMeteredPreference, newMeteredPreference); - - setWifiMeteredStatus(ssid, "false"); - // No disconnect from unmetered to metered. - waitForActiveNetworkMetered(TRANSPORT_WIFI, false); - assertEquals(mCm.getNetworkCapabilities(network).hasCapability( - NET_CAPABILITY_NOT_METERED), true); - assertMultipathPreferenceIsEventually(network, newMeteredPreference, - ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED); - } finally { - Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, - oldMeteredMultipathPreference); - setWifiMeteredStatus(ssid, oldMeteredSetting); - } - } - - // TODO: move the following socket keep alive test to dedicated test class. - /** - * Callback used in tcp keepalive offload that allows caller to wait callback fires. - */ - private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback { - public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }; - - public static class CallbackValue { - public final CallbackType callbackType; - public final int error; - - private CallbackValue(final CallbackType type, final int error) { - this.callbackType = type; - this.error = error; - } - - public static class OnStartedCallback extends CallbackValue { - OnStartedCallback() { super(CallbackType.ON_STARTED, 0); } - } - - public static class OnStoppedCallback extends CallbackValue { - OnStoppedCallback() { super(CallbackType.ON_STOPPED, 0); } - } - - public static class OnErrorCallback extends CallbackValue { - OnErrorCallback(final int error) { super(CallbackType.ON_ERROR, error); } - } - - @Override - public boolean equals(Object o) { - return o.getClass() == this.getClass() - && this.callbackType == ((CallbackValue) o).callbackType - && this.error == ((CallbackValue) o).error; - } - - @Override - public String toString() { - return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType, error); - } - } - - private final LinkedBlockingQueue mCallbacks = new LinkedBlockingQueue<>(); - - @Override - public void onStarted() { - mCallbacks.add(new CallbackValue.OnStartedCallback()); - } - - @Override - public void onStopped() { - mCallbacks.add(new CallbackValue.OnStoppedCallback()); - } - - @Override - public void onError(final int error) { - mCallbacks.add(new CallbackValue.OnErrorCallback(error)); - } - - public CallbackValue pollCallback() { - try { - return mCallbacks.poll(KEEPALIVE_CALLBACK_TIMEOUT_MS, - TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - fail("Callback not seen after " + KEEPALIVE_CALLBACK_TIMEOUT_MS + " ms"); - } - return null; - } - private void expectCallback(CallbackValue expectedCallback) { - final CallbackValue actualCallback = pollCallback(); - assertEquals(expectedCallback, actualCallback); - } - - public void expectStarted() { - expectCallback(new CallbackValue.OnStartedCallback()); - } - - public void expectStopped() { - expectCallback(new CallbackValue.OnStoppedCallback()); - } - - public void expectError(int error) { - expectCallback(new CallbackValue.OnErrorCallback(error)); - } - } - - private InetAddress getAddrByName(final String hostname, final int family) throws Exception { - final InetAddress[] allAddrs = InetAddress.getAllByName(hostname); - for (InetAddress addr : allAddrs) { - if (family == AF_INET && addr instanceof Inet4Address) return addr; - - if (family == AF_INET6 && addr instanceof Inet6Address) return addr; - - if (family == AF_UNSPEC) return addr; - } - return null; - } - - private Socket getConnectedSocket(final Network network, final String host, final int port, - final int family) throws Exception { - final Socket s = network.getSocketFactory().createSocket(); - try { - final InetAddress addr = getAddrByName(host, family); - if (addr == null) fail("Fail to get destination address for " + family); - - final InetSocketAddress sockAddr = new InetSocketAddress(addr, port); - s.connect(sockAddr); - } catch (Exception e) { - s.close(); - throw e; - } - return s; - } - - private int getSupportedKeepalivesForNet(@NonNull Network network) throws Exception { - final NetworkCapabilities nc = mCm.getNetworkCapabilities(network); - - // Get number of supported concurrent keepalives for testing network. - final int[] keepalivesPerTransport = KeepaliveUtils.getSupportedKeepalives(mContext); - return KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities( - keepalivesPerTransport, nc); - } - - private static boolean isTcpKeepaliveSupportedByKernel() { - final String kVersionString = VintfRuntimeInfo.getKernelVersion(); - return compareMajorMinorVersion(kVersionString, "4.8") >= 0; - } - - private static Pair getVersionFromString(String version) { - // Only gets major and minor number of the version string. - final Pattern versionPattern = Pattern.compile("^(\\d+)(\\.(\\d+))?.*"); - final Matcher m = versionPattern.matcher(version); - if (m.matches()) { - final int major = Integer.parseInt(m.group(1)); - final int minor = TextUtils.isEmpty(m.group(3)) ? 0 : Integer.parseInt(m.group(3)); - return new Pair<>(major, minor); - } else { - return new Pair<>(0, 0); - } - } - - // TODO: Move to util class. - private static int compareMajorMinorVersion(final String s1, final String s2) { - final Pair v1 = getVersionFromString(s1); - final Pair v2 = getVersionFromString(s2); - - if (v1.first == v2.first) { - return Integer.compare(v1.second, v2.second); - } else { - return Integer.compare(v1.first, v2.first); - } - } - - /** - * Verifies that version string compare logic returns expected result for various cases. - * Note that only major and minor number are compared. - */ - @Test - public void testMajorMinorVersionCompare() { - assertEquals(0, compareMajorMinorVersion("4.8.1", "4.8")); - assertEquals(1, compareMajorMinorVersion("4.9", "4.8.1")); - assertEquals(1, compareMajorMinorVersion("5.0", "4.8")); - assertEquals(1, compareMajorMinorVersion("5", "4.8")); - assertEquals(0, compareMajorMinorVersion("5", "5.0")); - assertEquals(1, compareMajorMinorVersion("5-beta1", "4.8")); - assertEquals(0, compareMajorMinorVersion("4.8.0.0", "4.8")); - assertEquals(0, compareMajorMinorVersion("4.8-RC1", "4.8")); - assertEquals(0, compareMajorMinorVersion("4.8", "4.8")); - assertEquals(-1, compareMajorMinorVersion("3.10", "4.8.0")); - assertEquals(-1, compareMajorMinorVersion("4.7.10.10", "4.8")); - } - - /** - * Verifies that the keepalive API cannot create any keepalive when the maximum number of - * keepalives is set to 0. - */ - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - public void testKeepaliveWifiUnsupported() throws Exception { - if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { - Log.i(TAG, "testKeepaliveUnsupported cannot execute unless device" - + " supports WiFi"); - return; - } - - final Network network = ensureWifiConnected(); - if (getSupportedKeepalivesForNet(network) != 0) return; - final InetAddress srcAddr = getFirstV4Address(network); - assumeTrue("This test requires native IPv4", srcAddr != null); - - runWithShellPermissionIdentity(() -> { - assertEquals(0, createConcurrentSocketKeepalives(network, srcAddr, 1, 0)); - assertEquals(0, createConcurrentSocketKeepalives(network, srcAddr, 0, 1)); - }); - } - - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - @SkipPresubmit(reason = "Keepalive is not supported on virtual hardware") - public void testCreateTcpKeepalive() throws Exception { - if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { - Log.i(TAG, "testCreateTcpKeepalive cannot execute unless device supports WiFi"); - return; - } - - final Network network = ensureWifiConnected(); - if (getSupportedKeepalivesForNet(network) == 0) return; - final InetAddress srcAddr = getFirstV4Address(network); - assumeTrue("This test requires native IPv4", srcAddr != null); - - // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support - // NAT-T keepalive. If keepalive limits from resource overlay is not zero, TCP keepalive - // needs to be supported except if the kernel doesn't support it. - if (!isTcpKeepaliveSupportedByKernel()) { - // Sanity check to ensure the callback result is expected. - runWithShellPermissionIdentity(() -> { - assertEquals(0, createConcurrentSocketKeepalives(network, srcAddr, 0, 1)); - }); - Log.i(TAG, "testCreateTcpKeepalive is skipped for kernel " - + VintfRuntimeInfo.getKernelVersion()); - return; - } - - final byte[] requestBytes = CtsNetUtils.HTTP_REQUEST.getBytes("UTF-8"); - // So far only ipv4 tcp keepalive offload is supported. - // TODO: add test case for ipv6 tcp keepalive offload when it is supported. - try (Socket s = getConnectedSocket(network, TEST_HOST, HTTP_PORT, AF_INET)) { - - // Should able to start keep alive offload when socket is idle. - final Executor executor = mContext.getMainExecutor(); - final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(); - - mUiAutomation.adoptShellPermissionIdentity(); - try (SocketKeepalive sk = mCm.createSocketKeepalive(network, s, executor, callback)) { - sk.start(MIN_KEEPALIVE_INTERVAL); - callback.expectStarted(); - - // App should not able to write during keepalive offload. - final OutputStream out = s.getOutputStream(); - try { - out.write(requestBytes); - fail("Should not able to write"); - } catch (IOException e) { } - // App should not able to read during keepalive offload. - final InputStream in = s.getInputStream(); - byte[] responseBytes = new byte[4096]; - try { - in.read(responseBytes); - fail("Should not able to read"); - } catch (IOException e) { } - - // Stop. - sk.stop(); - callback.expectStopped(); - } finally { - mUiAutomation.dropShellPermissionIdentity(); - } - - // Ensure socket is still connected. - assertTrue(s.isConnected()); - assertFalse(s.isClosed()); - - // Let socket be not idle. - try { - final OutputStream out = s.getOutputStream(); - out.write(requestBytes); - } catch (IOException e) { - fail("Failed to write data " + e); - } - // Make sure response data arrives. - final MessageQueue fdHandlerQueue = Looper.getMainLooper().getQueue(); - final FileDescriptor fd = s.getFileDescriptor$(); - final CountDownLatch mOnReceiveLatch = new CountDownLatch(1); - fdHandlerQueue.addOnFileDescriptorEventListener(fd, EVENT_INPUT, (readyFd, events) -> { - mOnReceiveLatch.countDown(); - return 0; // Unregister listener. - }); - if (!mOnReceiveLatch.await(2, TimeUnit.SECONDS)) { - fdHandlerQueue.removeOnFileDescriptorEventListener(fd); - fail("Timeout: no response data"); - } - - // Should get ERROR_SOCKET_NOT_IDLE because there is still data in the receive queue - // that has not been read. - mUiAutomation.adoptShellPermissionIdentity(); - try (SocketKeepalive sk = mCm.createSocketKeepalive(network, s, executor, callback)) { - sk.start(MIN_KEEPALIVE_INTERVAL); - callback.expectError(SocketKeepalive.ERROR_SOCKET_NOT_IDLE); - } finally { - mUiAutomation.dropShellPermissionIdentity(); - } - } - } - - private ArrayList createConcurrentKeepalivesOfType( - int requestCount, @NonNull TestSocketKeepaliveCallback callback, - Supplier kaFactory) { - final ArrayList kalist = new ArrayList<>(); - - int remainingRetries = MAX_KEEPALIVE_RETRY_COUNT; - - // Test concurrent keepalives with the given supplier. - while (kalist.size() < requestCount) { - final SocketKeepalive ka = kaFactory.get(); - ka.start(MIN_KEEPALIVE_INTERVAL); - TestSocketKeepaliveCallback.CallbackValue cv = callback.pollCallback(); - assertNotNull(cv); - if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_ERROR) { - if (kalist.size() == 0 && cv.error == SocketKeepalive.ERROR_UNSUPPORTED) { - // Unsupported. - break; - } else if (cv.error == SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES) { - // Limit reached or temporary unavailable due to stopped slot is not yet - // released. - if (remainingRetries > 0) { - SystemClock.sleep(INTERVAL_KEEPALIVE_RETRY_MS); - remainingRetries--; - continue; - } - break; - } - } - if (cv.callbackType == TestSocketKeepaliveCallback.CallbackType.ON_STARTED) { - kalist.add(ka); - } else { - fail("Unexpected error when creating " + (kalist.size() + 1) + " " - + ka.getClass().getSimpleName() + ": " + cv); - } - } - - return kalist; - } - - private @NonNull ArrayList createConcurrentNattSocketKeepalives( - @NonNull Network network, @NonNull InetAddress srcAddr, int requestCount, - @NonNull TestSocketKeepaliveCallback callback) throws Exception { - - final Executor executor = mContext.getMainExecutor(); - - // Initialize a real NaT-T socket. - final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); - final UdpEncapsulationSocket nattSocket = mIpSec.openUdpEncapsulationSocket(); - final InetAddress dstAddr = getAddrByName(TEST_HOST, AF_INET); - assertNotNull(srcAddr); - assertNotNull(dstAddr); - - // Test concurrent Nat-T keepalives. - final ArrayList result = createConcurrentKeepalivesOfType(requestCount, - callback, () -> mCm.createSocketKeepalive(network, nattSocket, - srcAddr, dstAddr, executor, callback)); - - nattSocket.close(); - return result; - } - - private @NonNull ArrayList createConcurrentTcpSocketKeepalives( - @NonNull Network network, int requestCount, - @NonNull TestSocketKeepaliveCallback callback) { - final Executor executor = mContext.getMainExecutor(); - - // Create concurrent TCP keepalives. - return createConcurrentKeepalivesOfType(requestCount, callback, () -> { - // Assert that TCP connections can be established. The file descriptor of tcp - // sockets will be duplicated and kept valid in service side if the keepalives are - // successfully started. - try (Socket tcpSocket = getConnectedSocket(network, TEST_HOST, HTTP_PORT, - AF_INET)) { - return mCm.createSocketKeepalive(network, tcpSocket, executor, callback); - } catch (Exception e) { - fail("Unexpected error when creating TCP socket: " + e); - } - return null; - }); - } - - /** - * Creates concurrent keepalives until the specified counts of each type of keepalives are - * reached or the expected error callbacks are received for each type of keepalives. - * - * @return the total number of keepalives created. - */ - private int createConcurrentSocketKeepalives( - @NonNull Network network, @NonNull InetAddress srcAddr, int nattCount, int tcpCount) - throws Exception { - final ArrayList kalist = new ArrayList<>(); - final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(); - - kalist.addAll(createConcurrentNattSocketKeepalives(network, srcAddr, nattCount, callback)); - kalist.addAll(createConcurrentTcpSocketKeepalives(network, tcpCount, callback)); - - final int ret = kalist.size(); - - // Clean up. - for (final SocketKeepalive ka : kalist) { - ka.stop(); - callback.expectStopped(); - } - kalist.clear(); - - return ret; - } - - /** - * Verifies that the concurrent keepalive slots meet the minimum requirement, and don't - * get leaked after iterations. - */ - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - @SkipPresubmit(reason = "Keepalive is not supported on virtual hardware") - public void testSocketKeepaliveLimitWifi() throws Exception { - if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { - Log.i(TAG, "testSocketKeepaliveLimitWifi cannot execute unless device" - + " supports WiFi"); - return; - } - - final Network network = ensureWifiConnected(); - final int supported = getSupportedKeepalivesForNet(network); - if (supported == 0) { - return; - } - final InetAddress srcAddr = getFirstV4Address(network); - assumeTrue("This test requires native IPv4", srcAddr != null); - - runWithShellPermissionIdentity(() -> { - // Verifies that the supported keepalive slots meet MIN_SUPPORTED_KEEPALIVE_COUNT. - assertGreaterOrEqual(supported, MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT); - - // Verifies that Nat-T keepalives can be established. - assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, - supported + 1, 0)); - // Verifies that keepalives don't get leaked in second round. - assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, supported, - 0)); - }); - - // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support - // NAT-T keepalive. Test below cases only if TCP keepalive is supported by kernel. - if (!isTcpKeepaliveSupportedByKernel()) return; - - runWithShellPermissionIdentity(() -> { - assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 0, - supported + 1)); - - // Verifies that different types can be established at the same time. - assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, - supported / 2, supported - supported / 2)); - - // Verifies that keepalives don't get leaked in second round. - assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 0, - supported)); - assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, - supported / 2, supported - supported / 2)); - }); - } - - /** - * Verifies that the concurrent keepalive slots meet the minimum telephony requirement, and - * don't get leaked after iterations. - */ - @AppModeFull(reason = "Cannot request network in instant app mode") - @Test - @SkipPresubmit(reason = "Keepalive is not supported on virtual hardware") - public void testSocketKeepaliveLimitTelephony() throws Exception { - if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) { - Log.i(TAG, "testSocketKeepaliveLimitTelephony cannot execute unless device" - + " supports telephony"); - return; - } - - final int firstSdk = Build.VERSION.FIRST_SDK_INT; - if (firstSdk < Build.VERSION_CODES.Q) { - Log.i(TAG, "testSocketKeepaliveLimitTelephony: skip test for devices launching" - + " before Q: " + firstSdk); - return; - } - - final Network network = mCtsNetUtils.connectToCell(); - final int supported = getSupportedKeepalivesForNet(network); - final InetAddress srcAddr = getFirstV4Address(network); - assumeTrue("This test requires native IPv4", srcAddr != null); - - runWithShellPermissionIdentity(() -> { - // Verifies that the supported keepalive slots meet minimum requirement. - assertGreaterOrEqual(supported, MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT); - // Verifies that Nat-T keepalives can be established. - assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, - supported + 1, 0)); - // Verifies that keepalives don't get leaked in second round. - assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, supported, - 0)); - }); - } - - private int getIntResourceForName(@NonNull String resName) { - final Resources r = mContext.getResources(); - final int resId = r.getIdentifier(resName, "integer", "android"); - return r.getInteger(resId); - } - - /** - * Verifies that the keepalive slots are limited as customized for unprivileged requests. - */ - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - @SkipPresubmit(reason = "Keepalive is not supported on virtual hardware") - public void testSocketKeepaliveUnprivileged() throws Exception { - if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { - Log.i(TAG, "testSocketKeepaliveUnprivileged cannot execute unless device" - + " supports WiFi"); - return; - } - - final Network network = ensureWifiConnected(); - final int supported = getSupportedKeepalivesForNet(network); - if (supported == 0) { - return; - } - final InetAddress srcAddr = getFirstV4Address(network); - assumeTrue("This test requires native IPv4", srcAddr != null); - - // Resource ID might be shifted on devices that compiled with different symbols. - // Thus, resolve ID at runtime is needed. - final int allowedUnprivilegedPerUid = - getIntResourceForName(KEEPALIVE_ALLOWED_UNPRIVILEGED_RES_NAME); - final int reservedPrivilegedSlots = - getIntResourceForName(KEEPALIVE_RESERVED_PER_SLOT_RES_NAME); - // Verifies that unprivileged request per uid cannot exceed the limit customized in the - // resource. Currently, unprivileged keepalive slots are limited to Nat-T only, this test - // does not apply to TCP. - assertGreaterOrEqual(supported, reservedPrivilegedSlots); - assertGreaterOrEqual(supported, allowedUnprivilegedPerUid); - final int expectedUnprivileged = - Math.min(allowedUnprivilegedPerUid, supported - reservedPrivilegedSlots); - assertEquals(expectedUnprivileged, - createConcurrentSocketKeepalives(network, srcAddr, supported + 1, 0)); - } - - private static void assertGreaterOrEqual(long greater, long lesser) { - assertTrue("" + greater + " expected to be greater than or equal to " + lesser, - greater >= lesser); - } - - /** - * Verifies that apps are not allowed to access restricted networks even if they declare the - * CONNECTIVITY_USE_RESTRICTED_NETWORKS permission in their manifests. - * See. b/144679405. - */ - @AppModeFull(reason = "Cannot get WifiManager in instant app mode") - @Test - public void testRestrictedNetworkPermission() throws Exception { - // Ensure that CONNECTIVITY_USE_RESTRICTED_NETWORKS isn't granted to this package. - final PackageInfo app = mPackageManager.getPackageInfo(mContext.getPackageName(), - GET_PERMISSIONS); - final int index = ArrayUtils.indexOf( - app.requestedPermissions, CONNECTIVITY_USE_RESTRICTED_NETWORKS); - assertTrue(index >= 0); - assertTrue(app.requestedPermissionsFlags[index] != PERMISSION_GRANTED); - - // Ensure that NetworkUtils.queryUserAccess always returns false since this package should - // not have netd system permission to call this function. - final Network wifiNetwork = ensureWifiConnected(); - assertFalse(NetworkUtils.queryUserAccess(Binder.getCallingUid(), wifiNetwork.netId)); - - // Ensure that this package cannot bind to any restricted network that's currently - // connected. - Network[] networks = mCm.getAllNetworks(); - for (Network network : networks) { - NetworkCapabilities nc = mCm.getNetworkCapabilities(network); - if (nc != null && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) { - try { - network.bindSocket(new Socket()); - fail("Bind to restricted network " + network + " unexpectedly succeeded"); - } catch (IOException expected) {} - } - } - } -} diff --git a/tests/cts/net/src/android/net/cts/CredentialsTest.java b/tests/cts/net/src/android/net/cts/CredentialsTest.java deleted file mode 100644 index 91c3621eab..0000000000 --- a/tests/cts/net/src/android/net/cts/CredentialsTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008 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.cts; - -import android.net.Credentials; -import android.test.AndroidTestCase; - -public class CredentialsTest extends AndroidTestCase { - - public void testCredentials() { - // new the Credentials instance - // Test with zero inputs - Credentials cred = new Credentials(0, 0, 0); - assertEquals(0, cred.getGid()); - assertEquals(0, cred.getPid()); - assertEquals(0, cred.getUid()); - - // Test with big integer - cred = new Credentials(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); - assertEquals(Integer.MAX_VALUE, cred.getGid()); - assertEquals(Integer.MAX_VALUE, cred.getPid()); - assertEquals(Integer.MAX_VALUE, cred.getUid()); - - // Test with big negative integer - cred = new Credentials(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); - assertEquals(Integer.MIN_VALUE, cred.getGid()); - assertEquals(Integer.MIN_VALUE, cred.getPid()); - assertEquals(Integer.MIN_VALUE, cred.getUid()); - } -} diff --git a/tests/cts/net/src/android/net/cts/DnsResolverTest.java b/tests/cts/net/src/android/net/cts/DnsResolverTest.java deleted file mode 100644 index 4d95fbe9a9..0000000000 --- a/tests/cts/net/src/android/net/cts/DnsResolverTest.java +++ /dev/null @@ -1,763 +0,0 @@ -/* - * Copyright (C) 2019 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.cts; - -import static android.net.DnsResolver.CLASS_IN; -import static android.net.DnsResolver.FLAG_EMPTY; -import static android.net.DnsResolver.FLAG_NO_CACHE_LOOKUP; -import static android.net.DnsResolver.TYPE_A; -import static android.net.DnsResolver.TYPE_AAAA; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.system.OsConstants.ETIMEDOUT; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.content.ContentResolver; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.DnsResolver; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.ParseException; -import android.net.cts.util.CtsNetUtils; -import android.os.CancellationSignal; -import android.os.Handler; -import android.os.Looper; -import android.platform.test.annotations.AppModeFull; -import android.provider.Settings; -import android.system.ErrnoException; -import android.test.AndroidTestCase; -import android.util.Log; - -import com.android.net.module.util.DnsPacket; -import com.android.testutils.SkipPresubmit; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; - -@AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps") -public class DnsResolverTest extends AndroidTestCase { - private static final String TAG = "DnsResolverTest"; - private static final char[] HEX_CHARS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - - static final String TEST_DOMAIN = "www.google.com"; - static final String TEST_NX_DOMAIN = "test1-nx.metric.gstatic.com"; - static final String INVALID_PRIVATE_DNS_SERVER = "invalid.google"; - static final String GOOGLE_PRIVATE_DNS_SERVER = "dns.google"; - static final byte[] TEST_BLOB = new byte[]{ - /* Header */ - 0x55, 0x66, /* Transaction ID */ - 0x01, 0x00, /* Flags */ - 0x00, 0x01, /* Questions */ - 0x00, 0x00, /* Answer RRs */ - 0x00, 0x00, /* Authority RRs */ - 0x00, 0x00, /* Additional RRs */ - /* Queries */ - 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6c, 0x65, - 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name */ - 0x00, 0x01, /* Type */ - 0x00, 0x01 /* Class */ - }; - static final int TIMEOUT_MS = 12_000; - static final int CANCEL_TIMEOUT_MS = 3_000; - static final int CANCEL_RETRY_TIMES = 5; - static final int QUERY_TIMES = 10; - static final int NXDOMAIN = 3; - - private ContentResolver mCR; - private ConnectivityManager mCM; - private PackageManager mPackageManager; - private CtsNetUtils mCtsNetUtils; - private Executor mExecutor; - private Executor mExecutorInline; - private DnsResolver mDns; - - private String mOldMode; - private String mOldDnsSpecifier; - - @Override - protected void setUp() throws Exception { - super.setUp(); - mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE); - mDns = DnsResolver.getInstance(); - mExecutor = new Handler(Looper.getMainLooper())::post; - mExecutorInline = (Runnable r) -> r.run(); - mCR = getContext().getContentResolver(); - mCtsNetUtils = new CtsNetUtils(getContext()); - mCtsNetUtils.storePrivateDnsSetting(); - mPackageManager = mContext.getPackageManager(); - } - - @Override - protected void tearDown() throws Exception { - mCtsNetUtils.restorePrivateDnsSetting(); - super.tearDown(); - } - - private static String byteArrayToHexString(byte[] bytes) { - char[] hexChars = new char[bytes.length * 2]; - for (int i = 0; i < bytes.length; ++i) { - int b = bytes[i] & 0xFF; - hexChars[i * 2] = HEX_CHARS[b >>> 4]; - hexChars[i * 2 + 1] = HEX_CHARS[b & 0x0F]; - } - return new String(hexChars); - } - - private Network[] getTestableNetworks() { - if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) { - mCtsNetUtils.ensureWifiConnected(); - } - final ArrayList testableNetworks = new ArrayList(); - for (Network network : mCM.getAllNetworks()) { - final NetworkCapabilities nc = mCM.getNetworkCapabilities(network); - if (nc != null - && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { - testableNetworks.add(network); - } - } - - assertTrue( - "This test requires that at least one network be connected. " + - "Please ensure that the device is connected to a network.", - testableNetworks.size() >= 1); - // In order to test query with null network, add null as an element. - // Test cases which query with null network will go on default network. - testableNetworks.add(null); - return testableNetworks.toArray(new Network[0]); - } - - static private void assertGreaterThan(String msg, int first, int second) { - assertTrue(msg + " Excepted " + first + " to be greater than " + second, first > second); - } - - private static class DnsParseException extends Exception { - public DnsParseException(String msg) { - super(msg); - } - } - - private static class DnsAnswer extends DnsPacket { - DnsAnswer(@NonNull byte[] data) throws DnsParseException { - super(data); - - // Check QR field.(query (0), or a response (1)). - if ((mHeader.flags & (1 << 15)) == 0) { - throw new DnsParseException("Not an answer packet"); - } - } - - int getRcode() { - return mHeader.rcode; - } - - int getANCount() { - return mHeader.getRecordCount(ANSECTION); - } - - int getQDCount() { - return mHeader.getRecordCount(QDSECTION); - } - } - - /** - * A query callback that ensures that the query is cancelled and that onAnswer is never - * called. If the query succeeds before it is cancelled, needRetry will return true so the - * test can retry. - */ - class VerifyCancelCallback implements DnsResolver.Callback { - private final CountDownLatch mLatch = new CountDownLatch(1); - private final String mMsg; - private final CancellationSignal mCancelSignal; - private int mRcode; - private DnsAnswer mDnsAnswer; - private String mErrorMsg = null; - - VerifyCancelCallback(@NonNull String msg, @Nullable CancellationSignal cancel) { - mMsg = msg; - mCancelSignal = cancel; - } - - VerifyCancelCallback(@NonNull String msg) { - this(msg, null); - } - - public boolean waitForAnswer(int timeout) throws InterruptedException { - return mLatch.await(timeout, TimeUnit.MILLISECONDS); - } - - public boolean waitForAnswer() throws InterruptedException { - return waitForAnswer(TIMEOUT_MS); - } - - public boolean needRetry() throws InterruptedException { - return mLatch.await(CANCEL_TIMEOUT_MS, TimeUnit.MILLISECONDS); - } - - @Override - public void onAnswer(@NonNull byte[] answer, int rcode) { - if (mCancelSignal != null && mCancelSignal.isCanceled()) { - mErrorMsg = mMsg + " should not have returned any answers"; - mLatch.countDown(); - return; - } - - mRcode = rcode; - try { - mDnsAnswer = new DnsAnswer(answer); - } catch (ParseException | DnsParseException e) { - mErrorMsg = mMsg + e.getMessage(); - mLatch.countDown(); - return; - } - Log.d(TAG, "Reported blob: " + byteArrayToHexString(answer)); - mLatch.countDown(); - } - - @Override - public void onError(@NonNull DnsResolver.DnsException error) { - mErrorMsg = mMsg + error.getMessage(); - mLatch.countDown(); - } - - private void assertValidAnswer() { - assertNull(mErrorMsg); - assertNotNull(mMsg + " No valid answer", mDnsAnswer); - assertEquals(mMsg + " Unexpected error: reported rcode" + mRcode + - " blob's rcode " + mDnsAnswer.getRcode(), mRcode, mDnsAnswer.getRcode()); - } - - public void assertHasAnswer() { - assertValidAnswer(); - // Check rcode field.(0, No error condition). - assertEquals(mMsg + " Response error, rcode: " + mRcode, mRcode, 0); - // Check answer counts. - assertGreaterThan(mMsg + " No answer found", mDnsAnswer.getANCount(), 0); - // Check question counts. - assertGreaterThan(mMsg + " No question found", mDnsAnswer.getQDCount(), 0); - } - - public void assertNXDomain() { - assertValidAnswer(); - // Check rcode field.(3, NXDomain). - assertEquals(mMsg + " Unexpected rcode: " + mRcode, mRcode, NXDOMAIN); - // Check answer counts. Expect 0 answer. - assertEquals(mMsg + " Not an empty answer", mDnsAnswer.getANCount(), 0); - // Check question counts. - assertGreaterThan(mMsg + " No question found", mDnsAnswer.getQDCount(), 0); - } - - public void assertEmptyAnswer() { - assertValidAnswer(); - // Check rcode field.(0, No error condition). - assertEquals(mMsg + " Response error, rcode: " + mRcode, mRcode, 0); - // Check answer counts. Expect 0 answer. - assertEquals(mMsg + " Not an empty answer", mDnsAnswer.getANCount(), 0); - // Check question counts. - assertGreaterThan(mMsg + " No question found", mDnsAnswer.getQDCount(), 0); - } - } - - public void testRawQuery() throws Exception { - doTestRawQuery(mExecutor); - } - - public void testRawQueryInline() throws Exception { - doTestRawQuery(mExecutorInline); - } - - public void testRawQueryBlob() throws Exception { - doTestRawQueryBlob(mExecutor); - } - - public void testRawQueryBlobInline() throws Exception { - doTestRawQueryBlob(mExecutorInline); - } - - public void testRawQueryRoot() throws Exception { - doTestRawQueryRoot(mExecutor); - } - - public void testRawQueryRootInline() throws Exception { - doTestRawQueryRoot(mExecutorInline); - } - - public void testRawQueryNXDomain() throws Exception { - doTestRawQueryNXDomain(mExecutor); - } - - public void testRawQueryNXDomainInline() throws Exception { - doTestRawQueryNXDomain(mExecutorInline); - } - - public void testRawQueryNXDomainWithPrivateDns() throws Exception { - doTestRawQueryNXDomainWithPrivateDns(mExecutor); - } - - public void testRawQueryNXDomainInlineWithPrivateDns() throws Exception { - doTestRawQueryNXDomainWithPrivateDns(mExecutorInline); - } - - public void doTestRawQuery(Executor executor) throws InterruptedException { - final String msg = "RawQuery " + TEST_DOMAIN; - for (Network network : getTestableNetworks()) { - final VerifyCancelCallback callback = new VerifyCancelCallback(msg); - mDns.rawQuery(network, TEST_DOMAIN, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP, - executor, null, callback); - - assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - callback.assertHasAnswer(); - } - } - - public void doTestRawQueryBlob(Executor executor) throws InterruptedException { - final byte[] blob = new byte[]{ - /* Header */ - 0x55, 0x66, /* Transaction ID */ - 0x01, 0x00, /* Flags */ - 0x00, 0x01, /* Questions */ - 0x00, 0x00, /* Answer RRs */ - 0x00, 0x00, /* Authority RRs */ - 0x00, 0x00, /* Additional RRs */ - /* Queries */ - 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6F, 0x6F, 0x67, 0x6c, 0x65, - 0x03, 0x63, 0x6f, 0x6d, 0x00, /* Name */ - 0x00, 0x01, /* Type */ - 0x00, 0x01 /* Class */ - }; - final String msg = "RawQuery blob " + byteArrayToHexString(blob); - for (Network network : getTestableNetworks()) { - final VerifyCancelCallback callback = new VerifyCancelCallback(msg); - mDns.rawQuery(network, blob, FLAG_NO_CACHE_LOOKUP, executor, null, callback); - - assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - callback.assertHasAnswer(); - } - } - - public void doTestRawQueryRoot(Executor executor) throws InterruptedException { - final String dname = ""; - final String msg = "RawQuery empty dname(ROOT) "; - for (Network network : getTestableNetworks()) { - final VerifyCancelCallback callback = new VerifyCancelCallback(msg); - mDns.rawQuery(network, dname, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP, - executor, null, callback); - - assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - // Except no answer record because the root does not have AAAA records. - callback.assertEmptyAnswer(); - } - } - - public void doTestRawQueryNXDomain(Executor executor) throws InterruptedException { - final String msg = "RawQuery " + TEST_NX_DOMAIN; - - for (Network network : getTestableNetworks()) { - final NetworkCapabilities nc = (network != null) - ? mCM.getNetworkCapabilities(network) - : mCM.getNetworkCapabilities(mCM.getActiveNetwork()); - assertNotNull("Couldn't determine NetworkCapabilities for " + network, nc); - // Some cellular networks configure their DNS servers never to return NXDOMAIN, so don't - // test NXDOMAIN on these DNS servers. - // b/144521720 - if (nc.hasTransport(TRANSPORT_CELLULAR)) continue; - final VerifyCancelCallback callback = new VerifyCancelCallback(msg); - mDns.rawQuery(network, TEST_NX_DOMAIN, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP, - executor, null, callback); - - assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - callback.assertNXDomain(); - } - } - - public void doTestRawQueryNXDomainWithPrivateDns(Executor executor) - throws InterruptedException { - final String msg = "RawQuery " + TEST_NX_DOMAIN + " with private DNS"; - // Enable private DNS strict mode and set server to dns.google before doing NxDomain test. - // b/144521720 - mCtsNetUtils.setPrivateDnsStrictMode(GOOGLE_PRIVATE_DNS_SERVER); - for (Network network : getTestableNetworks()) { - final Network networkForPrivateDns = - (network != null) ? network : mCM.getActiveNetwork(); - assertNotNull("Can't find network to await private DNS on", networkForPrivateDns); - mCtsNetUtils.awaitPrivateDnsSetting(msg + " wait private DNS setting timeout", - networkForPrivateDns, GOOGLE_PRIVATE_DNS_SERVER, true); - final VerifyCancelCallback callback = new VerifyCancelCallback(msg); - mDns.rawQuery(network, TEST_NX_DOMAIN, CLASS_IN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP, - executor, null, callback); - - assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - callback.assertNXDomain(); - } - } - - public void testRawQueryCancel() throws InterruptedException { - final String msg = "Test cancel RawQuery " + TEST_DOMAIN; - // Start a DNS query and the cancel it immediately. Use VerifyCancelCallback to expect - // that the query is cancelled before it succeeds. If it is not cancelled before it - // succeeds, retry the test until it is. - for (Network network : getTestableNetworks()) { - boolean retry = false; - int round = 0; - do { - if (++round > CANCEL_RETRY_TIMES) { - fail(msg + " cancel failed " + CANCEL_RETRY_TIMES + " times"); - } - final CountDownLatch latch = new CountDownLatch(1); - final CancellationSignal cancelSignal = new CancellationSignal(); - final VerifyCancelCallback callback = new VerifyCancelCallback(msg, cancelSignal); - mDns.rawQuery(network, TEST_DOMAIN, CLASS_IN, TYPE_AAAA, FLAG_EMPTY, - mExecutor, cancelSignal, callback); - mExecutor.execute(() -> { - cancelSignal.cancel(); - latch.countDown(); - }); - - retry = callback.needRetry(); - assertTrue(msg + " query was not cancelled", - latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } while (retry); - } - } - - public void testRawQueryBlobCancel() throws InterruptedException { - final String msg = "Test cancel RawQuery blob " + byteArrayToHexString(TEST_BLOB); - // Start a DNS query and the cancel it immediately. Use VerifyCancelCallback to expect - // that the query is cancelled before it succeeds. If it is not cancelled before it - // succeeds, retry the test until it is. - for (Network network : getTestableNetworks()) { - boolean retry = false; - int round = 0; - do { - if (++round > CANCEL_RETRY_TIMES) { - fail(msg + " cancel failed " + CANCEL_RETRY_TIMES + " times"); - } - final CountDownLatch latch = new CountDownLatch(1); - final CancellationSignal cancelSignal = new CancellationSignal(); - final VerifyCancelCallback callback = new VerifyCancelCallback(msg, cancelSignal); - mDns.rawQuery(network, TEST_BLOB, FLAG_EMPTY, mExecutor, cancelSignal, callback); - mExecutor.execute(() -> { - cancelSignal.cancel(); - latch.countDown(); - }); - - retry = callback.needRetry(); - assertTrue(msg + " cancel is not done", - latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } while (retry); - } - } - - public void testCancelBeforeQuery() throws InterruptedException { - final String msg = "Test cancelled RawQuery " + TEST_DOMAIN; - for (Network network : getTestableNetworks()) { - final VerifyCancelCallback callback = new VerifyCancelCallback(msg); - final CancellationSignal cancelSignal = new CancellationSignal(); - cancelSignal.cancel(); - mDns.rawQuery(network, TEST_DOMAIN, CLASS_IN, TYPE_AAAA, FLAG_EMPTY, - mExecutor, cancelSignal, callback); - - assertTrue(msg + " should not return any answers", - !callback.waitForAnswer(CANCEL_TIMEOUT_MS)); - } - } - - /** - * A query callback for InetAddress that ensures that the query is - * cancelled and that onAnswer is never called. If the query succeeds - * before it is cancelled, needRetry will return true so the - * test can retry. - */ - class VerifyCancelInetAddressCallback implements DnsResolver.Callback> { - private final CountDownLatch mLatch = new CountDownLatch(1); - private final String mMsg; - private final List mAnswers; - private final CancellationSignal mCancelSignal; - private String mErrorMsg = null; - - VerifyCancelInetAddressCallback(@NonNull String msg, @Nullable CancellationSignal cancel) { - this.mMsg = msg; - this.mCancelSignal = cancel; - mAnswers = new ArrayList<>(); - } - - public boolean waitForAnswer() throws InterruptedException { - return mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); - } - - public boolean needRetry() throws InterruptedException { - return mLatch.await(CANCEL_TIMEOUT_MS, TimeUnit.MILLISECONDS); - } - - public boolean isAnswerEmpty() { - return mAnswers.isEmpty(); - } - - public boolean hasIpv6Answer() { - for (InetAddress answer : mAnswers) { - if (answer instanceof Inet6Address) return true; - } - return false; - } - - public boolean hasIpv4Answer() { - for (InetAddress answer : mAnswers) { - if (answer instanceof Inet4Address) return true; - } - return false; - } - - public void assertNoError() { - assertNull(mErrorMsg); - } - - @Override - public void onAnswer(@NonNull List answerList, int rcode) { - if (mCancelSignal != null && mCancelSignal.isCanceled()) { - mErrorMsg = mMsg + " should not have returned any answers"; - mLatch.countDown(); - return; - } - for (InetAddress addr : answerList) { - Log.d(TAG, "Reported addr: " + addr.toString()); - } - mAnswers.clear(); - mAnswers.addAll(answerList); - mLatch.countDown(); - } - - @Override - public void onError(@NonNull DnsResolver.DnsException error) { - mErrorMsg = mMsg + error.getMessage(); - mLatch.countDown(); - } - } - - public void testQueryForInetAddress() throws Exception { - doTestQueryForInetAddress(mExecutor); - } - - public void testQueryForInetAddressInline() throws Exception { - doTestQueryForInetAddress(mExecutorInline); - } - - public void testQueryForInetAddressIpv4() throws Exception { - doTestQueryForInetAddressIpv4(mExecutor); - } - - public void testQueryForInetAddressIpv4Inline() throws Exception { - doTestQueryForInetAddressIpv4(mExecutorInline); - } - - public void testQueryForInetAddressIpv6() throws Exception { - doTestQueryForInetAddressIpv6(mExecutor); - } - - public void testQueryForInetAddressIpv6Inline() throws Exception { - doTestQueryForInetAddressIpv6(mExecutorInline); - } - - public void testContinuousQueries() throws Exception { - doTestContinuousQueries(mExecutor); - } - - @SkipPresubmit(reason = "Flaky: b/159762682; add to presubmit after fixing") - public void testContinuousQueriesInline() throws Exception { - doTestContinuousQueries(mExecutorInline); - } - - public void doTestQueryForInetAddress(Executor executor) throws InterruptedException { - final String msg = "Test query for InetAddress " + TEST_DOMAIN; - for (Network network : getTestableNetworks()) { - final VerifyCancelInetAddressCallback callback = - new VerifyCancelInetAddressCallback(msg, null); - mDns.query(network, TEST_DOMAIN, FLAG_NO_CACHE_LOOKUP, executor, null, callback); - - assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - callback.assertNoError(); - assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty()); - } - } - - public void testQueryCancelForInetAddress() throws InterruptedException { - final String msg = "Test cancel query for InetAddress " + TEST_DOMAIN; - // Start a DNS query and the cancel it immediately. Use VerifyCancelInetAddressCallback to - // expect that the query is cancelled before it succeeds. If it is not cancelled before it - // succeeds, retry the test until it is. - for (Network network : getTestableNetworks()) { - boolean retry = false; - int round = 0; - do { - if (++round > CANCEL_RETRY_TIMES) { - fail(msg + " cancel failed " + CANCEL_RETRY_TIMES + " times"); - } - final CountDownLatch latch = new CountDownLatch(1); - final CancellationSignal cancelSignal = new CancellationSignal(); - final VerifyCancelInetAddressCallback callback = - new VerifyCancelInetAddressCallback(msg, cancelSignal); - mDns.query(network, TEST_DOMAIN, FLAG_EMPTY, mExecutor, cancelSignal, callback); - mExecutor.execute(() -> { - cancelSignal.cancel(); - latch.countDown(); - }); - - retry = callback.needRetry(); - assertTrue(msg + " query was not cancelled", - latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } while (retry); - } - } - - public void doTestQueryForInetAddressIpv4(Executor executor) throws InterruptedException { - final String msg = "Test query for IPv4 InetAddress " + TEST_DOMAIN; - for (Network network : getTestableNetworks()) { - final VerifyCancelInetAddressCallback callback = - new VerifyCancelInetAddressCallback(msg, null); - mDns.query(network, TEST_DOMAIN, TYPE_A, FLAG_NO_CACHE_LOOKUP, - executor, null, callback); - - assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - callback.assertNoError(); - assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty()); - assertTrue(msg + " returned Ipv6 results", !callback.hasIpv6Answer()); - } - } - - public void doTestQueryForInetAddressIpv6(Executor executor) throws InterruptedException { - final String msg = "Test query for IPv6 InetAddress " + TEST_DOMAIN; - for (Network network : getTestableNetworks()) { - final VerifyCancelInetAddressCallback callback = - new VerifyCancelInetAddressCallback(msg, null); - mDns.query(network, TEST_DOMAIN, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP, - executor, null, callback); - - assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - callback.assertNoError(); - assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty()); - assertTrue(msg + " returned Ipv4 results", !callback.hasIpv4Answer()); - } - } - - public void testPrivateDnsBypass() throws InterruptedException { - final Network[] testNetworks = getTestableNetworks(); - - // Set an invalid private DNS server - mCtsNetUtils.setPrivateDnsStrictMode(INVALID_PRIVATE_DNS_SERVER); - final String msg = "Test PrivateDnsBypass " + TEST_DOMAIN; - for (Network network : testNetworks) { - // This test cannot be ran with null network because we need to explicitly pass a - // private DNS bypassable network or bind one. - if (network == null) continue; - - // wait for private DNS setting propagating - mCtsNetUtils.awaitPrivateDnsSetting(msg + " wait private DNS setting timeout", - network, INVALID_PRIVATE_DNS_SERVER, false); - - final CountDownLatch latch = new CountDownLatch(1); - final DnsResolver.Callback> errorCallback = - new DnsResolver.Callback>() { - @Override - public void onAnswer(@NonNull List answerList, int rcode) { - fail(msg + " should not get valid answer"); - } - - @Override - public void onError(@NonNull DnsResolver.DnsException error) { - assertEquals(DnsResolver.ERROR_SYSTEM, error.code); - assertEquals(ETIMEDOUT, ((ErrnoException) error.getCause()).errno); - latch.countDown(); - } - }; - // Private DNS strict mode with invalid DNS server is set - // Expect no valid answer returned but ErrnoException with ETIMEDOUT - mDns.query(network, TEST_DOMAIN, FLAG_NO_CACHE_LOOKUP, mExecutor, null, errorCallback); - - assertTrue(msg + " invalid server round. No response after " + TIMEOUT_MS + "ms.", - latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - final VerifyCancelInetAddressCallback callback = - new VerifyCancelInetAddressCallback(msg, null); - // Bypass privateDns, expect query works fine - mDns.query(network.getPrivateDnsBypassingCopy(), - TEST_DOMAIN, FLAG_NO_CACHE_LOOKUP, mExecutor, null, callback); - - assertTrue(msg + " bypass private DNS round. No answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - callback.assertNoError(); - assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty()); - - // To ensure private DNS bypass still work even if passing null network. - // Bind process network with a private DNS bypassable network. - mCM.bindProcessToNetwork(network.getPrivateDnsBypassingCopy()); - final VerifyCancelInetAddressCallback callbackWithNullNetwork = - new VerifyCancelInetAddressCallback(msg + " with null network ", null); - mDns.query(null, - TEST_DOMAIN, FLAG_NO_CACHE_LOOKUP, mExecutor, null, callbackWithNullNetwork); - - assertTrue(msg + " with null network bypass private DNS round. No answer after " + - TIMEOUT_MS + "ms.", callbackWithNullNetwork.waitForAnswer()); - callbackWithNullNetwork.assertNoError(); - assertTrue(msg + " with null network returned 0 results", - !callbackWithNullNetwork.isAnswerEmpty()); - - // Reset process network to default. - mCM.bindProcessToNetwork(null); - } - } - - public void doTestContinuousQueries(Executor executor) throws InterruptedException { - final String msg = "Test continuous " + QUERY_TIMES + " queries " + TEST_DOMAIN; - for (Network network : getTestableNetworks()) { - for (int i = 0; i < QUERY_TIMES ; ++i) { - final VerifyCancelInetAddressCallback callback = - new VerifyCancelInetAddressCallback(msg, null); - // query v6/v4 in turn - boolean queryV6 = (i % 2 == 0); - mDns.query(network, TEST_DOMAIN, queryV6 ? TYPE_AAAA : TYPE_A, - FLAG_NO_CACHE_LOOKUP, executor, null, callback); - - assertTrue(msg + " but no answer after " + TIMEOUT_MS + "ms.", - callback.waitForAnswer()); - callback.assertNoError(); - assertTrue(msg + " returned 0 results", !callback.isAnswerEmpty()); - assertTrue(msg + " returned " + (queryV6 ? "Ipv4" : "Ipv6") + " results", - queryV6 ? !callback.hasIpv4Answer() : !callback.hasIpv6Answer()); - } - } - } -} diff --git a/tests/cts/net/src/android/net/cts/DnsTest.java b/tests/cts/net/src/android/net/cts/DnsTest.java deleted file mode 100644 index fde27e9f12..0000000000 --- a/tests/cts/net/src/android/net/cts/DnsTest.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (C) 2013 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.cts; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkInfo; -import android.os.SystemClock; -import android.test.AndroidTestCase; -import android.util.Log; - -import com.android.testutils.SkipPresubmit; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -public class DnsTest extends AndroidTestCase { - - static { - System.loadLibrary("nativedns_jni"); - } - - private static final boolean DBG = false; - private static final String TAG = "DnsTest"; - private static final String PROXY_NETWORK_TYPE = "PROXY"; - - private ConnectivityManager mCm; - - public void setUp() { - mCm = getContext().getSystemService(ConnectivityManager.class); - } - - /** - * @return true on success - */ - private static native boolean testNativeDns(); - - /** - * Verify: - * DNS works - forwards and backwards, giving ipv4 and ipv6 - * Test that DNS work on v4 and v6 networks - * Test Native dns calls (4) - * Todo: - * Cache is flushed when we change networks - * have per-network caches - * No cache when there's no network - * Perf - measure size of first and second tier caches and their effect - * Assert requires network permission - */ - @SkipPresubmit(reason = "IPv6 support may be missing on presubmit virtual hardware") - public void testDnsWorks() throws Exception { - ensureIpv6Connectivity(); - - InetAddress addrs[] = {}; - try { - addrs = InetAddress.getAllByName("www.google.com"); - } catch (UnknownHostException e) {} - assertTrue("[RERUN] DNS could not resolve www.google.com. Check internet connection", - addrs.length != 0); - boolean foundV4 = false, foundV6 = false; - for (InetAddress addr : addrs) { - if (addr instanceof Inet4Address) foundV4 = true; - else if (addr instanceof Inet6Address) foundV6 = true; - if (DBG) Log.e(TAG, "www.google.com gave " + addr.toString()); - } - - // We should have at least one of the addresses to connect! - assertTrue("www.google.com must have IPv4 and/or IPv6 address", foundV4 || foundV6); - - // Skip the rest of the test if the active network for watch is PROXY. - // TODO: Check NetworkInfo type in addition to type name once ag/601257 is merged. - if (getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH) - && activeNetworkInfoIsProxy()) { - Log.i(TAG, "Skipping test because the active network type name is PROXY."); - return; - } - - // Clear test state so we don't get confused with the previous results. - addrs = new InetAddress[0]; - foundV4 = foundV6 = false; - try { - addrs = InetAddress.getAllByName("ipv6.google.com"); - } catch (UnknownHostException e) {} - String msg = - "[RERUN] DNS could not resolve ipv6.google.com, check the network supports IPv6. lp=" + - mCm.getActiveLinkProperties(); - assertTrue(msg, addrs.length != 0); - for (InetAddress addr : addrs) { - msg = "[RERUN] ipv6.google.com returned IPv4 address: " + addr.getHostAddress() + - ", check your network's DNS server. lp=" + mCm.getActiveLinkProperties(); - assertFalse (msg, addr instanceof Inet4Address); - foundV6 |= (addr instanceof Inet6Address); - if (DBG) Log.e(TAG, "ipv6.google.com gave " + addr.toString()); - } - - assertTrue(foundV6); - - assertTrue(testNativeDns()); - } - - private static final String[] URLS = { "www.google.com", "ipv6.google.com", "www.yahoo.com", - "facebook.com", "youtube.com", "blogspot.com", "baidu.com", "wikipedia.org", -// live.com fails rev lookup. - "twitter.com", "qq.com", "msn.com", "yahoo.co.jp", "linkedin.com", - "taobao.com", "google.co.in", "sina.com.cn", "amazon.com", "wordpress.com", - "google.co.uk", "ebay.com", "yandex.ru", "163.com", "google.co.jp", "google.fr", - "microsoft.com", "paypal.com", "google.com.br", "flickr.com", - "mail.ru", "craigslist.org", "fc2.com", "google.it", -// "apple.com", fails rev lookup - "google.es", - "imdb.com", "google.ru", "soho.com", "bbc.co.uk", "vkontakte.ru", "ask.com", - "tumblr.com", "weibo.com", "go.com", "xvideos.com", "livejasmin.com", "cnn.com", - "youku.com", "blogspot.com", "soso.com", "google.ca", "aol.com", "tudou.com", - "xhamster.com", "megaupload.com", "ifeng.com", "zedo.com", "mediafire.com", "ameblo.jp", - "pornhub.com", "google.co.id", "godaddy.com", "adobe.com", "rakuten.co.jp", "about.com", - "espn.go.com", "4shared.com", "alibaba.com","ebay.de", "yieldmanager.com", - "wordpress.org", "livejournal.com", "google.com.tr", "google.com.mx", "renren.com", - "livedoor.com", "google.com.au", "youporn.com", "uol.com.br", "cnet.com", "conduit.com", - "google.pl", "myspace.com", "nytimes.com", "ebay.co.uk", "chinaz.com", "hao123.com", - "thepiratebay.org", "doubleclick.com", "alipay.com", "netflix.com", "cnzz.com", - "huffingtonpost.com", "twitpic.com", "weather.com", "babylon.com", "amazon.de", - "dailymotion.com", "orkut.com", "orkut.com.br", "google.com.sa", "odnoklassniki.ru", - "amazon.co.jp", "google.nl", "goo.ne.jp", "stumbleupon.com", "tube8.com", "tmall.com", - "imgur.com", "globo.com", "secureserver.net", "fileserve.com", "tianya.cn", "badoo.com", - "ehow.com", "photobucket.com", "imageshack.us", "xnxx.com", "deviantart.com", - "filestube.com", "addthis.com", "douban.com", "vimeo.com", "sogou.com", - "stackoverflow.com", "reddit.com", "dailymail.co.uk", "redtube.com", "megavideo.com", - "taringa.net", "pengyou.com", "amazon.co.uk", "fbcdn.net", "aweber.com", "spiegel.de", - "rapidshare.com", "mixi.jp", "360buy.com", "google.cn", "digg.com", "answers.com", - "bit.ly", "indiatimes.com", "skype.com", "yfrog.com", "optmd.com", "google.com.eg", - "google.com.pk", "58.com", "hotfile.com", "google.co.th", - "bankofamerica.com", "sourceforge.net", "maktoob.com", "warriorforum.com", "rediff.com", - "google.co.za", "56.com", "torrentz.eu", "clicksor.com", "avg.com", - "download.com", "ku6.com", "statcounter.com", "foxnews.com", "google.com.ar", - "nicovideo.jp", "reference.com", "liveinternet.ru", "ucoz.ru", "xinhuanet.com", - "xtendmedia.com", "naver.com", "youjizz.com", "domaintools.com", "sparkstudios.com", - "rambler.ru", "scribd.com", "kaixin001.com", "mashable.com", "adultfirendfinder.com", - "files.wordpress.com", "guardian.co.uk", "bild.de", "yelp.com", "wikimedia.org", - "chase.com", "onet.pl", "ameba.jp", "pconline.com.cn", "free.fr", "etsy.com", - "typepad.com", "youdao.com", "megaclick.com", "digitalpoint.com", "blogfa.com", - "salesforce.com", "adf.ly", "ganji.com", "wikia.com", "archive.org", "terra.com.br", - "w3schools.com", "ezinearticles.com", "wjs.com", "google.com.my", "clickbank.com", - "squidoo.com", "hulu.com", "repubblica.it", "google.be", "allegro.pl", "comcast.net", - "narod.ru", "zol.com.cn", "orange.fr", "soufun.com", "hatena.ne.jp", "google.gr", - "in.com", "techcrunch.com", "orkut.co.in", "xunlei.com", - "reuters.com", "google.com.vn", "hostgator.com", "kaskus.us", "espncricinfo.com", - "hootsuite.com", "qiyi.com", "gmx.net", "xing.com", "php.net", "soku.com", "web.de", - "libero.it", "groupon.com", "51.la", "slideshare.net", "booking.com", "seesaa.net", - "126.com", "telegraph.co.uk", "wretch.cc", "twimg.com", "rutracker.org", "angege.com", - "nba.com", "dell.com", "leboncoin.fr", "people.com", "google.com.tw", "walmart.com", - "daum.net", "2ch.net", "constantcontact.com", "nifty.com", "mywebsearch.com", - "tripadvisor.com", "google.se", "paipai.com", "google.com.ua", "ning.com", "hp.com", - "google.at", "joomla.org", "icio.us", "hudong.com", "csdn.net", "getfirebug.com", - "ups.com", "cj.com", "google.ch", "camzap.com", "wordreference.com", "tagged.com", - "wp.pl", "mozilla.com", "google.ru", "usps.com", "china.com", "themeforest.net", - "search-results.com", "tribalfusion.com", "thefreedictionary.com", "isohunt.com", - "linkwithin.com", "cam4.com", "plentyoffish.com", "wellsfargo.com", "metacafe.com", - "depositfiles.com", "freelancer.com", "opendns.com", "homeway.com", "engadget.com", - "10086.cn", "360.cn", "marca.com", "dropbox.com", "ign.com", "match.com", "google.pt", - "facemoods.com", "hardsextube.com", "google.com.ph", "lockerz.com", "istockphoto.com", - "partypoker.com", "netlog.com", "outbrain.com", "elpais.com", "fiverr.com", - "biglobe.ne.jp", "corriere.it", "love21cn.com", "yesky.com", "spankwire.com", - "ig.com.br", "imagevenue.com", "hubpages.com", "google.co.ve"}; - -// TODO - this works, but is slow and cts doesn't do anything with the result. -// Maybe require a min performance, a min cache size (detectable) and/or move -// to perf testing - private static final int LOOKUP_COUNT_GOAL = URLS.length; - public void skiptestDnsPerf() { - ArrayList results = new ArrayList(); - int failures = 0; - try { - for (int numberOfUrls = URLS.length; numberOfUrls > 0; numberOfUrls--) { - failures = 0; - int iterationLimit = LOOKUP_COUNT_GOAL / numberOfUrls; - long startTime = SystemClock.elapsedRealtimeNanos(); - for (int iteration = 0; iteration < iterationLimit; iteration++) { - for (int urlIndex = 0; urlIndex < numberOfUrls; urlIndex++) { - try { - InetAddress addr = InetAddress.getByName(URLS[urlIndex]); - } catch (UnknownHostException e) { - Log.e(TAG, "failed first lookup of " + URLS[urlIndex]); - failures++; - try { - InetAddress addr = InetAddress.getByName(URLS[urlIndex]); - } catch (UnknownHostException ee) { - failures++; - Log.e(TAG, "failed SECOND lookup of " + URLS[urlIndex]); - } - } - } - } - long endTime = SystemClock.elapsedRealtimeNanos(); - float nsPer = ((float)(endTime-startTime) / iterationLimit) / numberOfUrls/ 1000; - String thisResult = new String("getByName for " + numberOfUrls + " took " + - (endTime - startTime)/1000 + "(" + nsPer + ") with " + - failures + " failures\n"); - Log.d(TAG, thisResult); - results.add(thisResult); - } - // build up a list of addresses - ArrayList addressList = new ArrayList(); - for (String url : URLS) { - try { - InetAddress addr = InetAddress.getByName(url); - addressList.add(addr.getAddress()); - } catch (UnknownHostException e) { - Log.e(TAG, "Exception making reverseDNS list: " + e.toString()); - } - } - for (int numberOfAddrs = addressList.size(); numberOfAddrs > 0; numberOfAddrs--) { - int iterationLimit = LOOKUP_COUNT_GOAL / numberOfAddrs; - failures = 0; - long startTime = SystemClock.elapsedRealtimeNanos(); - for (int iteration = 0; iteration < iterationLimit; iteration++) { - for (int addrIndex = 0; addrIndex < numberOfAddrs; addrIndex++) { - try { - InetAddress addr = InetAddress.getByAddress(addressList.get(addrIndex)); - String hostname = addr.getHostName(); - } catch (UnknownHostException e) { - failures++; - Log.e(TAG, "Failure doing reverse DNS lookup: " + e.toString()); - try { - InetAddress addr = - InetAddress.getByAddress(addressList.get(addrIndex)); - String hostname = addr.getHostName(); - - } catch (UnknownHostException ee) { - failures++; - Log.e(TAG, "Failure doing SECOND reverse DNS lookup: " + - ee.toString()); - } - } - } - } - long endTime = SystemClock.elapsedRealtimeNanos(); - float nsPer = ((endTime-startTime) / iterationLimit) / numberOfAddrs / 1000; - String thisResult = new String("getHostName for " + numberOfAddrs + " took " + - (endTime - startTime)/1000 + "(" + nsPer + ") with " + - failures + " failures\n"); - Log.d(TAG, thisResult); - results.add(thisResult); - } - for (String result : results) Log.d(TAG, result); - - InetAddress exit = InetAddress.getByName("exitrightnow.com"); - Log.e(TAG, " exit address= "+exit.toString()); - - } catch (Exception e) { - Log.e(TAG, "bad URL in testDnsPerf: " + e.toString()); - } - } - - private boolean activeNetworkInfoIsProxy() { - NetworkInfo info = mCm.getActiveNetworkInfo(); - if (PROXY_NETWORK_TYPE.equals(info.getTypeName())) { - return true; - } - - return false; - } - - private void ensureIpv6Connectivity() throws InterruptedException { - CountDownLatch latch = new CountDownLatch(1); - final int TIMEOUT_MS = 5_000; - - final NetworkCallback callback = new NetworkCallback() { - @Override - public void onLinkPropertiesChanged(Network network, LinkProperties lp) { - if (lp.hasGlobalIpv6Address()) { - latch.countDown(); - } - } - }; - mCm.registerDefaultNetworkCallback(callback); - - String msg = "Default network did not provide IPv6 connectivity after " + TIMEOUT_MS - + "ms. Please connect to an IPv6-capable network. lp=" - + mCm.getActiveLinkProperties(); - try { - assertTrue(msg, latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - mCm.unregisterNetworkCallback(callback); - } - } -} diff --git a/tests/cts/net/src/android/net/cts/IkeTunUtils.java b/tests/cts/net/src/android/net/cts/IkeTunUtils.java deleted file mode 100644 index fc25292b27..0000000000 --- a/tests/cts/net/src/android/net/cts/IkeTunUtils.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * 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.cts; - -import static android.net.cts.PacketUtils.BytePayload; -import static android.net.cts.PacketUtils.IP4_HDRLEN; -import static android.net.cts.PacketUtils.IP6_HDRLEN; -import static android.net.cts.PacketUtils.IpHeader; -import static android.net.cts.PacketUtils.UDP_HDRLEN; -import static android.net.cts.PacketUtils.UdpHeader; -import static android.net.cts.PacketUtils.getIpHeader; -import static android.system.OsConstants.IPPROTO_UDP; - -import android.os.ParcelFileDescriptor; - -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.util.Arrays; - -// TODO: Merge this with the version in the IPsec module (IKEv2 library) CTS tests. -/** An extension of the TunUtils class with IKE-specific packet handling. */ -public class IkeTunUtils extends TunUtils { - private static final int PORT_LEN = 2; - - private static final byte[] NON_ESP_MARKER = new byte[] {0, 0, 0, 0}; - - private static final int IKE_HEADER_LEN = 28; - private static final int IKE_SPI_LEN = 8; - private static final int IKE_IS_RESP_BYTE_OFFSET = 19; - private static final int IKE_MSG_ID_OFFSET = 20; - private static final int IKE_MSG_ID_LEN = 4; - - public IkeTunUtils(ParcelFileDescriptor tunFd) { - super(tunFd); - } - - /** - * Await an expected IKE request and inject an IKE response. - * - * @param respIkePkt IKE response packet without IP/UDP headers or NON ESP MARKER. - */ - public byte[] awaitReqAndInjectResp(long expectedInitIkeSpi, int expectedMsgId, - boolean encapExpected, byte[] respIkePkt) throws Exception { - final byte[] request = awaitIkePacket(expectedInitIkeSpi, expectedMsgId, encapExpected); - - // Build response header by flipping address and port - final InetAddress srcAddr = getDstAddress(request); - final InetAddress dstAddr = getSrcAddress(request); - final int srcPort = getDstPort(request); - final int dstPort = getSrcPort(request); - - final byte[] response = - buildIkePacket(srcAddr, dstAddr, srcPort, dstPort, encapExpected, respIkePkt); - injectPacket(response); - return request; - } - - private byte[] awaitIkePacket(long expectedInitIkeSpi, int expectedMsgId, boolean expectEncap) - throws Exception { - return super.awaitPacket(pkt -> isIke(pkt, expectedInitIkeSpi, expectedMsgId, expectEncap)); - } - - private static boolean isIke( - byte[] pkt, long expectedInitIkeSpi, int expectedMsgId, boolean encapExpected) { - final int ipProtocolOffset; - final int ikeOffset; - - if (isIpv6(pkt)) { - ipProtocolOffset = IP6_PROTO_OFFSET; - ikeOffset = IP6_HDRLEN + UDP_HDRLEN; - } else { - if (encapExpected && !hasNonEspMarkerv4(pkt)) { - return false; - } - - // Use default IPv4 header length (assuming no options) - final int encapMarkerLen = encapExpected ? NON_ESP_MARKER.length : 0; - ipProtocolOffset = IP4_PROTO_OFFSET; - ikeOffset = IP4_HDRLEN + UDP_HDRLEN + encapMarkerLen; - } - - return pkt[ipProtocolOffset] == IPPROTO_UDP - && areSpiAndMsgIdEqual(pkt, ikeOffset, expectedInitIkeSpi, expectedMsgId); - } - - /** Checks if the provided IPv4 packet has a UDP-encapsulation NON-ESP marker */ - private static boolean hasNonEspMarkerv4(byte[] ipv4Pkt) { - final int nonEspMarkerOffset = IP4_HDRLEN + UDP_HDRLEN; - if (ipv4Pkt.length < nonEspMarkerOffset + NON_ESP_MARKER.length) { - return false; - } - - final byte[] nonEspMarker = Arrays.copyOfRange( - ipv4Pkt, nonEspMarkerOffset, nonEspMarkerOffset + NON_ESP_MARKER.length); - return Arrays.equals(NON_ESP_MARKER, nonEspMarker); - } - - private static boolean areSpiAndMsgIdEqual( - byte[] pkt, int ikeOffset, long expectedIkeInitSpi, int expectedMsgId) { - if (pkt.length <= ikeOffset + IKE_HEADER_LEN) { - return false; - } - - final ByteBuffer buffer = ByteBuffer.wrap(pkt); - final long spi = buffer.getLong(ikeOffset); - final int msgId = buffer.getInt(ikeOffset + IKE_MSG_ID_OFFSET); - - return expectedIkeInitSpi == spi && expectedMsgId == msgId; - } - - private static InetAddress getSrcAddress(byte[] pkt) throws Exception { - return getAddress(pkt, true); - } - - private static InetAddress getDstAddress(byte[] pkt) throws Exception { - return getAddress(pkt, false); - } - - private static InetAddress getAddress(byte[] pkt, boolean getSrcAddr) throws Exception { - final int ipLen = isIpv6(pkt) ? IP6_ADDR_LEN : IP4_ADDR_LEN; - final int srcIpOffset = isIpv6(pkt) ? IP6_ADDR_OFFSET : IP4_ADDR_OFFSET; - final int ipOffset = getSrcAddr ? srcIpOffset : srcIpOffset + ipLen; - - if (pkt.length < ipOffset + ipLen) { - // Should be impossible; getAddress() is only called with a full IKE request including - // the IP and UDP headers. - throw new IllegalArgumentException("Packet was too short to contain IP address"); - } - - return InetAddress.getByAddress(Arrays.copyOfRange(pkt, ipOffset, ipOffset + ipLen)); - } - - private static int getSrcPort(byte[] pkt) throws Exception { - return getPort(pkt, true); - } - - private static int getDstPort(byte[] pkt) throws Exception { - return getPort(pkt, false); - } - - private static int getPort(byte[] pkt, boolean getSrcPort) { - final int srcPortOffset = isIpv6(pkt) ? IP6_HDRLEN : IP4_HDRLEN; - final int portOffset = getSrcPort ? srcPortOffset : srcPortOffset + PORT_LEN; - - if (pkt.length < portOffset + PORT_LEN) { - // Should be impossible; getPort() is only called with a full IKE request including the - // IP and UDP headers. - throw new IllegalArgumentException("Packet was too short to contain port"); - } - - final ByteBuffer buffer = ByteBuffer.wrap(pkt); - return Short.toUnsignedInt(buffer.getShort(portOffset)); - } - - private static byte[] buildIkePacket( - InetAddress srcAddr, - InetAddress dstAddr, - int srcPort, - int dstPort, - boolean useEncap, - byte[] payload) - throws Exception { - // Append non-ESP marker if encap is enabled - if (useEncap) { - final ByteBuffer buffer = ByteBuffer.allocate(NON_ESP_MARKER.length + payload.length); - buffer.put(NON_ESP_MARKER); - buffer.put(payload); - payload = buffer.array(); - } - - final UdpHeader udpPkt = new UdpHeader(srcPort, dstPort, new BytePayload(payload)); - final IpHeader ipPkt = getIpHeader(udpPkt.getProtocolId(), srcAddr, dstAddr, udpPkt); - return ipPkt.getPacketBytes(); - } -} diff --git a/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java b/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java deleted file mode 100644 index 9eab024cf0..0000000000 --- a/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java +++ /dev/null @@ -1,535 +0,0 @@ -/* - * 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.cts; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; - -import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import android.Manifest; -import android.annotation.NonNull; -import android.app.AppOpsManager; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.net.Ikev2VpnProfile; -import android.net.IpSecAlgorithm; -import android.net.LinkAddress; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.ProxyInfo; -import android.net.TestNetworkInterface; -import android.net.TestNetworkManager; -import android.net.VpnManager; -import android.net.cts.util.CtsNetUtils; -import android.os.Build; -import android.os.Process; -import android.platform.test.annotations.AppModeFull; - -import androidx.test.InstrumentationRegistry; - -import com.android.internal.util.HexDump; -import com.android.org.bouncycastle.x509.X509V1CertificateGenerator; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; -import com.android.testutils.DevSdkIgnoreRunner; - -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.math.BigInteger; -import java.net.InetAddress; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.PrivateKey; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import javax.security.auth.x500.X500Principal; - -@RunWith(DevSdkIgnoreRunner.class) -@IgnoreUpTo(Build.VERSION_CODES.Q) -@AppModeFull(reason = "Appops state changes disallowed for instant apps (OP_ACTIVATE_PLATFORM_VPN)") -public class Ikev2VpnTest { - private static final String TAG = Ikev2VpnTest.class.getSimpleName(); - - // Test vectors for IKE negotiation in test mode. - private static final String SUCCESSFUL_IKE_INIT_RESP_V4 = - "46b8eca1e0d72a18b2b5d9006d47a0022120222000000000000002d0220000300000002c01010004030000" - + "0c0100000c800e0100030000080300000c030000080200000400000008040000102800020800" - + "100000b8070f159fe5141d8754ca86f72ecc28d66f514927e96cbe9eec0adb42bf2c276a0ab7" - + "a97fa93555f4be9218c14e7f286bb28c6b4fb13825a420f2ffc165854f200bab37d69c8963d4" - + "0acb831d983163aa50622fd35c182efe882cf54d6106222abcfaa597255d302f1b95ab71c142" - + "c279ea5839a180070bff73f9d03fab815f0d5ee2adec7e409d1e35979f8bd92ffd8aab13d1a0" - + "0657d816643ae767e9ae84d2ccfa2bcce1a50572be8d3748ae4863c41ae90da16271e014270f" - + "77edd5cd2e3299f3ab27d7203f93d770bacf816041cdcecd0f9af249033979da4369cb242dd9" - + "6d172e60513ff3db02de63e50eb7d7f596ada55d7946cad0af0669d1f3e2804846ab3f2a930d" - + "df56f7f025f25c25ada694e6231abbb87ee8cfd072c8481dc0b0f6b083fdc3bd89b080e49feb" - + "0288eef6fdf8a26ee2fc564a11e7385215cf2deaf2a9965638fc279c908ccdf04094988d91a2" - + "464b4a8c0326533aff5119ed79ecbd9d99a218b44f506a5eb09351e67da86698b4c58718db25" - + "d55f426fb4c76471b27a41fbce00777bc233c7f6e842e39146f466826de94f564cad8b92bfbe" - + "87c99c4c7973ec5f1eea8795e7da82819753aa7c4fcfdab77066c56b939330c4b0d354c23f83" - + "ea82fa7a64c4b108f1188379ea0eb4918ee009d804100e6bf118771b9058d42141c847d5ec37" - + "6e5ec591c71fc9dac01063c2bd31f9c783b28bf1182900002430f3d5de3449462b31dd28bc27" - + "297b6ad169bccce4f66c5399c6e0be9120166f2900001c0000400428b8df2e66f69c8584a186" - + "c5eac66783551d49b72900001c000040054e7a622e802d5cbfb96d5f30a6e433994370173529" - + "0000080000402e290000100000402f00020003000400050000000800004014"; - private static final String SUCCESSFUL_IKE_INIT_RESP_V6 = - "46b8eca1e0d72a1800d9ea1babce26bf2120222000000000000002d0220000300000002c01010004030000" - + "0c0100000c800e0100030000080300000c030000080200000400000008040000102800020800" - + "100000ea0e6dd9ca5930a9a45c323a41f64bfd8cdef7730f5fbff37d7c377da427f489a42aa8" - + "c89233380e6e925990d49de35c2cdcf63a61302c731a4b3569df1ee1bf2457e55a6751838ede" - + "abb75cc63ba5c9e4355e8e784f383a5efe8a44727dc14aeaf8dacc2620fb1c8875416dc07739" - + "7fe4decc1bd514a9c7d270cf21fd734c63a25c34b30b68686e54e8a198f37f27cb491fe27235" - + "fab5476b036d875ccab9a68d65fbf3006197f9bebbf94de0d3802b4fafe1d48d931ce3a1a346" - + "2d65bd639e9bd7fa46299650a9dbaf9b324e40b466942d91a59f41ef8042f8474c4850ed0f63" - + "e9238949d41cd8bbaea9aefdb65443a6405792839563aa5dc5c36b5ce8326ccf8a94d9622b85" - + "038d390d5fc0299e14e1f022966d4ac66515f6108ca04faec44821fe5bbf2ed4f84ff5671219" - + "608cb4c36b44a31ba010c9088f8d5ff943bb9ff857f74be1755f57a5783874adc57f42bb174e" - + "4ad3215de628707014dbcb1707bd214658118fdd7a42b3e1638b991ce5b812a667f1145be811" - + "685e3cd3baf9b18d062657b64c206a4d19a531c252a6a51a04aeaf42c618620cdbab65baca23" - + "82c57ed888422aeaacf7f1bc3fe2247ff7e7eaca218b74d7b31d02f2b0afa123f802529e7e6c" - + "3259d418290740ddbf55686e26998d7edcbbf895664972fed666f2f20af40503aa2af436ec6d" - + "4ec981ab19b9088755d94ae7a7c2066ea331d4e56e290000243fefe5555fce552d57a84e682c" - + "d4a6dfb3f2f94a94464d5bec3d88b88e9559642900001c00004004eb4afff764e7b79bca78b1" - + "3a89100d36d678ae982900001c00004005d177216a3c26f782076e12570d40bfaaa148822929" - + "0000080000402e290000100000402f00020003000400050000000800004014"; - private static final String SUCCESSFUL_IKE_AUTH_RESP_V4 = - "46b8eca1e0d72a18b2b5d9006d47a0022e20232000000001000000e0240000c420a2500a3da4c66fa6929e" - + "600f36349ba0e38de14f78a3ad0416cba8c058735712a3d3f9a0a6ed36de09b5e9e02697e7c4" - + "2d210ac86cfbd709503cfa51e2eab8cfdc6427d136313c072968f6506a546eb5927164200592" - + "6e36a16ee994e63f029432a67bc7d37ca619e1bd6e1678df14853067ecf816b48b81e8746069" - + "406363e5aa55f13cb2afda9dbebee94256c29d630b17dd7f1ee52351f92b6e1c3d8551c513f1" - + "d74ac52a80b2041397e109fe0aeb3c105b0d4be0ae343a943398764281"; - private static final String SUCCESSFUL_IKE_AUTH_RESP_V6 = - "46b8eca1e0d72a1800d9ea1babce26bf2e20232000000001000000f0240000d4aaf6eaa6c06b50447e6f54" - + "827fd8a9d9d6ac8015c1ebb3e8cb03fc6e54b49a107441f50004027cc5021600828026367f03" - + "bc425821cd7772ee98637361300c9b76056e874fea2bd4a17212370b291894264d8c023a01d1" - + "c3b691fd4b7c0b534e8c95af4c4638e2d125cb21c6267e2507cd745d72e8da109c47b9259c6c" - + "57a26f6bc5b337b9b9496d54bdde0333d7a32e6e1335c9ee730c3ecd607a8689aa7b0577b74f" - + "3bf437696a9fd5fc0aee3ed346cd9e15d1dda293df89eb388a8719388a60ca7625754de12cdb" - + "efe4c886c5c401"; - private static final long IKE_INITIATOR_SPI = Long.parseLong("46B8ECA1E0D72A18", 16); - - private static final InetAddress LOCAL_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.1"); - private static final InetAddress LOCAL_OUTER_6 = - InetAddress.parseNumericAddress("2001:db8::1"); - - private static final int IP4_PREFIX_LEN = 32; - private static final int IP6_PREFIX_LEN = 128; - - // TODO: Use IPv6 address when we can generate test vectors (GCE does not allow IPv6 yet). - private static final String TEST_SERVER_ADDR_V4 = "192.0.2.2"; - private static final String TEST_SERVER_ADDR_V6 = "2001:db8::2"; - private static final String TEST_IDENTITY = "client.cts.android.com"; - private static final List TEST_ALLOWED_ALGORITHMS = - Arrays.asList(IpSecAlgorithm.AUTH_CRYPT_AES_GCM); - - private static final ProxyInfo TEST_PROXY_INFO = - ProxyInfo.buildDirectProxy("proxy.cts.android.com", 1234); - private static final int TEST_MTU = 1300; - - private static final byte[] TEST_PSK = "ikeAndroidPsk".getBytes(); - private static final String TEST_USER = "username"; - private static final String TEST_PASSWORD = "pa55w0rd"; - - // Static state to reduce setup/teardown - private static final Context sContext = InstrumentationRegistry.getContext(); - private static final ConnectivityManager sCM = - (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE); - private static final VpnManager sVpnMgr = - (VpnManager) sContext.getSystemService(Context.VPN_MANAGEMENT_SERVICE); - private static final CtsNetUtils mCtsNetUtils = new CtsNetUtils(sContext); - - private final X509Certificate mServerRootCa; - private final CertificateAndKey mUserCertKey; - - public Ikev2VpnTest() throws Exception { - // Build certificates - mServerRootCa = generateRandomCertAndKeyPair().cert; - mUserCertKey = generateRandomCertAndKeyPair(); - } - - @After - public void tearDown() { - setAppop(AppOpsManager.OP_ACTIVATE_VPN, false); - setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false); - } - - /** - * Sets the given appop using shell commands - * - *

This method must NEVER be called from within a shell permission, as it will attempt to - * acquire, and then drop the shell permission identity. This results in the caller losing the - * shell permission identity due to these calls not being reference counted. - */ - public void setAppop(int appop, boolean allow) { - // Requires shell permission to update appops. - runWithShellPermissionIdentity(() -> { - mCtsNetUtils.setAppopPrivileged(appop, allow); - }, Manifest.permission.MANAGE_TEST_NETWORKS); - } - - private Ikev2VpnProfile buildIkev2VpnProfileCommon( - Ikev2VpnProfile.Builder builder, boolean isRestrictedToTestNetworks) throws Exception { - if (isRestrictedToTestNetworks) { - builder.restrictToTestNetworks(); - } - - return builder.setBypassable(true) - .setAllowedAlgorithms(TEST_ALLOWED_ALGORITHMS) - .setProxy(TEST_PROXY_INFO) - .setMaxMtu(TEST_MTU) - .setMetered(false) - .build(); - } - - private Ikev2VpnProfile buildIkev2VpnProfilePsk(boolean isRestrictedToTestNetworks) - throws Exception { - return buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6, isRestrictedToTestNetworks); - } - - private Ikev2VpnProfile buildIkev2VpnProfilePsk( - String remote, boolean isRestrictedToTestNetworks) throws Exception { - final Ikev2VpnProfile.Builder builder = - new Ikev2VpnProfile.Builder(remote, TEST_IDENTITY).setAuthPsk(TEST_PSK); - - return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks); - } - - private Ikev2VpnProfile buildIkev2VpnProfileUsernamePassword(boolean isRestrictedToTestNetworks) - throws Exception { - final Ikev2VpnProfile.Builder builder = - new Ikev2VpnProfile.Builder(TEST_SERVER_ADDR_V6, TEST_IDENTITY) - .setAuthUsernamePassword(TEST_USER, TEST_PASSWORD, mServerRootCa); - - return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks); - } - - private Ikev2VpnProfile buildIkev2VpnProfileDigitalSignature(boolean isRestrictedToTestNetworks) - throws Exception { - final Ikev2VpnProfile.Builder builder = - new Ikev2VpnProfile.Builder(TEST_SERVER_ADDR_V6, TEST_IDENTITY) - .setAuthDigitalSignature( - mUserCertKey.cert, mUserCertKey.key, mServerRootCa); - - return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks); - } - - private void checkBasicIkev2VpnProfile(@NonNull Ikev2VpnProfile profile) throws Exception { - assertEquals(TEST_SERVER_ADDR_V6, profile.getServerAddr()); - assertEquals(TEST_IDENTITY, profile.getUserIdentity()); - assertEquals(TEST_PROXY_INFO, profile.getProxyInfo()); - assertEquals(TEST_ALLOWED_ALGORITHMS, profile.getAllowedAlgorithms()); - assertTrue(profile.isBypassable()); - assertFalse(profile.isMetered()); - assertEquals(TEST_MTU, profile.getMaxMtu()); - assertFalse(profile.isRestrictedToTestNetworks()); - } - - @Test - public void testBuildIkev2VpnProfilePsk() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - final Ikev2VpnProfile profile = - buildIkev2VpnProfilePsk(false /* isRestrictedToTestNetworks */); - - checkBasicIkev2VpnProfile(profile); - assertArrayEquals(TEST_PSK, profile.getPresharedKey()); - - // Verify nothing else is set. - assertNull(profile.getUsername()); - assertNull(profile.getPassword()); - assertNull(profile.getServerRootCaCert()); - assertNull(profile.getRsaPrivateKey()); - assertNull(profile.getUserCert()); - } - - @Test - public void testBuildIkev2VpnProfileUsernamePassword() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - final Ikev2VpnProfile profile = - buildIkev2VpnProfileUsernamePassword(false /* isRestrictedToTestNetworks */); - - checkBasicIkev2VpnProfile(profile); - assertEquals(TEST_USER, profile.getUsername()); - assertEquals(TEST_PASSWORD, profile.getPassword()); - assertEquals(mServerRootCa, profile.getServerRootCaCert()); - - // Verify nothing else is set. - assertNull(profile.getPresharedKey()); - assertNull(profile.getRsaPrivateKey()); - assertNull(profile.getUserCert()); - } - - @Test - public void testBuildIkev2VpnProfileDigitalSignature() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - final Ikev2VpnProfile profile = - buildIkev2VpnProfileDigitalSignature(false /* isRestrictedToTestNetworks */); - - checkBasicIkev2VpnProfile(profile); - assertEquals(mUserCertKey.cert, profile.getUserCert()); - assertEquals(mUserCertKey.key, profile.getRsaPrivateKey()); - assertEquals(mServerRootCa, profile.getServerRootCaCert()); - - // Verify nothing else is set. - assertNull(profile.getUsername()); - assertNull(profile.getPassword()); - assertNull(profile.getPresharedKey()); - } - - private void verifyProvisionVpnProfile( - boolean hasActivateVpn, boolean hasActivatePlatformVpn, boolean expectIntent) - throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - setAppop(AppOpsManager.OP_ACTIVATE_VPN, hasActivateVpn); - setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, hasActivatePlatformVpn); - - final Ikev2VpnProfile profile = - buildIkev2VpnProfilePsk(false /* isRestrictedToTestNetworks */); - final Intent intent = sVpnMgr.provisionVpnProfile(profile); - assertEquals(expectIntent, intent != null); - } - - @Test - public void testProvisionVpnProfileNoPreviousConsent() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - verifyProvisionVpnProfile(false /* hasActivateVpn */, - false /* hasActivatePlatformVpn */, true /* expectIntent */); - } - - @Test - public void testProvisionVpnProfilePlatformVpnConsented() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - verifyProvisionVpnProfile(false /* hasActivateVpn */, - true /* hasActivatePlatformVpn */, false /* expectIntent */); - } - - @Test - public void testProvisionVpnProfileVpnServiceConsented() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - verifyProvisionVpnProfile(true /* hasActivateVpn */, - false /* hasActivatePlatformVpn */, false /* expectIntent */); - } - - @Test - public void testProvisionVpnProfileAllPreConsented() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - verifyProvisionVpnProfile(true /* hasActivateVpn */, - true /* hasActivatePlatformVpn */, false /* expectIntent */); - } - - @Test - public void testDeleteVpnProfile() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true); - - final Ikev2VpnProfile profile = - buildIkev2VpnProfilePsk(false /* isRestrictedToTestNetworks */); - assertNull(sVpnMgr.provisionVpnProfile(profile)); - - // Verify that deleting the profile works (even without the appop) - setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false); - sVpnMgr.deleteProvisionedVpnProfile(); - - // Test that the profile was deleted - starting it should throw an IAE. - try { - setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true); - sVpnMgr.startProvisionedVpnProfile(); - fail("Expected IllegalArgumentException due to missing profile"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testStartVpnProfileNoPreviousConsent() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - setAppop(AppOpsManager.OP_ACTIVATE_VPN, false); - setAppop(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, false); - - // Make sure the VpnProfile is not provisioned already. - sVpnMgr.stopProvisionedVpnProfile(); - - try { - sVpnMgr.startProvisionedVpnProfile(); - fail("Expected SecurityException for missing consent"); - } catch (SecurityException expected) { - } - } - - private void checkStartStopVpnProfileBuildsNetworks(IkeTunUtils tunUtils, boolean testIpv6) - throws Exception { - String serverAddr = testIpv6 ? TEST_SERVER_ADDR_V6 : TEST_SERVER_ADDR_V4; - String initResp = testIpv6 ? SUCCESSFUL_IKE_INIT_RESP_V6 : SUCCESSFUL_IKE_INIT_RESP_V4; - String authResp = testIpv6 ? SUCCESSFUL_IKE_AUTH_RESP_V6 : SUCCESSFUL_IKE_AUTH_RESP_V4; - boolean hasNat = !testIpv6; - - // Requires MANAGE_TEST_NETWORKS to provision a test-mode profile. - mCtsNetUtils.setAppopPrivileged(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN, true); - - final Ikev2VpnProfile profile = - buildIkev2VpnProfilePsk(serverAddr, true /* isRestrictedToTestNetworks */); - assertNull(sVpnMgr.provisionVpnProfile(profile)); - - sVpnMgr.startProvisionedVpnProfile(); - - // Inject IKE negotiation - int expectedMsgId = 0; - tunUtils.awaitReqAndInjectResp(IKE_INITIATOR_SPI, expectedMsgId++, false /* isEncap */, - HexDump.hexStringToByteArray(initResp)); - tunUtils.awaitReqAndInjectResp(IKE_INITIATOR_SPI, expectedMsgId++, hasNat /* isEncap */, - HexDump.hexStringToByteArray(authResp)); - - // Verify the VPN network came up - final NetworkRequest nr = new NetworkRequest.Builder() - .clearCapabilities().addTransportType(TRANSPORT_VPN).build(); - - final TestNetworkCallback cb = new TestNetworkCallback(); - sCM.requestNetwork(nr, cb); - cb.waitForAvailable(); - final Network vpnNetwork = cb.currentNetwork; - assertNotNull(vpnNetwork); - - final NetworkCapabilities caps = sCM.getNetworkCapabilities(vpnNetwork); - assertTrue(caps.hasTransport(TRANSPORT_VPN)); - assertTrue(caps.hasCapability(NET_CAPABILITY_INTERNET)); - assertEquals(Process.myUid(), caps.getOwnerUid()); - - sVpnMgr.stopProvisionedVpnProfile(); - cb.waitForLost(); - assertEquals(vpnNetwork, cb.lastLostNetwork); - } - - private void doTestStartStopVpnProfile(boolean testIpv6) throws Exception { - // Non-final; these variables ensure we clean up properly after our test if we have - // allocated test network resources - final TestNetworkManager tnm = sContext.getSystemService(TestNetworkManager.class); - TestNetworkInterface testIface = null; - TestNetworkCallback tunNetworkCallback = null; - - try { - // Build underlying test network - testIface = tnm.createTunInterface( - new LinkAddress[] { - new LinkAddress(LOCAL_OUTER_4, IP4_PREFIX_LEN), - new LinkAddress(LOCAL_OUTER_6, IP6_PREFIX_LEN)}); - - // Hold on to this callback to ensure network does not get reaped. - tunNetworkCallback = mCtsNetUtils.setupAndGetTestNetwork( - testIface.getInterfaceName()); - final IkeTunUtils tunUtils = new IkeTunUtils(testIface.getFileDescriptor()); - - checkStartStopVpnProfileBuildsNetworks(tunUtils, testIpv6); - } finally { - // Make sure to stop the VPN profile. This is safe to call multiple times. - sVpnMgr.stopProvisionedVpnProfile(); - - if (testIface != null) { - testIface.getFileDescriptor().close(); - } - - if (tunNetworkCallback != null) { - sCM.unregisterNetworkCallback(tunNetworkCallback); - } - - final Network testNetwork = tunNetworkCallback.currentNetwork; - if (testNetwork != null) { - tnm.teardownTestNetwork(testNetwork); - } - } - } - - @Test - public void testStartStopVpnProfileV4() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - // Requires shell permission to update appops. - runWithShellPermissionIdentity(() -> { - doTestStartStopVpnProfile(false); - }); - } - - @Test - public void testStartStopVpnProfileV6() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - // Requires shell permission to update appops. - runWithShellPermissionIdentity(() -> { - doTestStartStopVpnProfile(true); - }); - } - - private static class CertificateAndKey { - public final X509Certificate cert; - public final PrivateKey key; - - CertificateAndKey(X509Certificate cert, PrivateKey key) { - this.cert = cert; - this.key = key; - } - } - - private static CertificateAndKey generateRandomCertAndKeyPair() throws Exception { - final Date validityBeginDate = - new Date(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1L)); - final Date validityEndDate = - new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1L)); - - // Generate a keypair - final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); - keyPairGenerator.initialize(512); - final KeyPair keyPair = keyPairGenerator.generateKeyPair(); - - final X500Principal dnName = new X500Principal("CN=test.android.com"); - final X509V1CertificateGenerator certGen = new X509V1CertificateGenerator(); - certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); - certGen.setSubjectDN(dnName); - certGen.setIssuerDN(dnName); - certGen.setNotBefore(validityBeginDate); - certGen.setNotAfter(validityEndDate); - certGen.setPublicKey(keyPair.getPublic()); - certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); - - final X509Certificate cert = certGen.generate(keyPair.getPrivate(), "AndroidOpenSSL"); - return new CertificateAndKey(cert, keyPair.getPrivate()); - } -} diff --git a/tests/cts/net/src/android/net/cts/InetAddressesTest.java b/tests/cts/net/src/android/net/cts/InetAddressesTest.java deleted file mode 100644 index 7837ce9ed5..0000000000 --- a/tests/cts/net/src/android/net/cts/InetAddressesTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2018 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.cts; - -import android.net.InetAddresses; -import java.net.InetAddress; -import junitparams.JUnitParamsRunner; -import junitparams.Parameters; -import org.junit.Test; -import org.junit.runner.RunWith; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -@RunWith(JUnitParamsRunner.class) -public class InetAddressesTest { - - public static String[][] validNumericAddressesAndStringRepresentation() { - return new String[][] { - // Regular IPv4. - { "1.2.3.4", "1.2.3.4" }, - - // Regular IPv6. - { "2001:4860:800d::68", "2001:4860:800d::68" }, - { "1234:5678::9ABC:DEF0", "1234:5678::9abc:def0" }, - { "2001:cdba:9abc:5678::", "2001:cdba:9abc:5678::" }, - { "::2001:cdba:9abc:5678", "::2001:cdba:9abc:5678" }, - { "64:ff9b::1.2.3.4", "64:ff9b::102:304" }, - - { "::9abc:5678", "::154.188.86.120" }, - - // Mapped IPv4 - { "::ffff:127.0.0.1", "127.0.0.1" }, - - // Android does not recognize Octal (leading 0) cases: they are treated as decimal. - { "0177.00.00.01", "177.0.0.1" }, - - // Verify that examples from JavaDoc work correctly. - { "192.0.2.1", "192.0.2.1" }, - { "2001:db8::1:2", "2001:db8::1:2" }, - }; - } - - public static String[] invalidNumericAddresses() { - return new String[] { - "", - " ", - "\t", - "\n", - "1.2.3.4.", - "1.2.3", - "1.2", - "1", - "1234", - "0", - "0x1.0x2.0x3.0x4", - "0x7f.0x00.0x00.0x01", - "0256.00.00.01", - "fred", - "www.google.com", - // IPv6 encoded for use in URL as defined in RFC 2732 - "[fe80::6:2222]", - }; - } - - @Parameters(method = "validNumericAddressesAndStringRepresentation") - @Test - public void parseNumericAddress(String address, String expectedString) { - InetAddress inetAddress = InetAddresses.parseNumericAddress(address); - assertEquals(expectedString, inetAddress.getHostAddress()); - } - - @Parameters(method = "invalidNumericAddresses") - @Test - public void test_parseNonNumericAddress(String address) { - try { - InetAddress inetAddress = InetAddresses.parseNumericAddress(address); - fail(String.format( - "Address %s is not numeric but was parsed as %s", address, inetAddress)); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(address); - } - } - - @Test - public void test_parseNumericAddress_null() { - try { - InetAddress inetAddress = InetAddresses.parseNumericAddress(null); - fail(String.format("null is not numeric but was parsed as %s", inetAddress)); - } catch (NullPointerException e) { - // expected - } - } - - @Parameters(method = "validNumericAddressesAndStringRepresentation") - @Test - public void test_isNumericAddress(String address, String unused) { - assertTrue("expected '" + address + "' to be treated as numeric", - InetAddresses.isNumericAddress(address)); - } - - @Parameters(method = "invalidNumericAddresses") - @Test - public void test_isNotNumericAddress(String address) { - assertFalse("expected '" + address + "' to be treated as non-numeric", - InetAddresses.isNumericAddress(address)); - } - - @Test - public void test_isNumericAddress_null() { - try { - InetAddresses.isNumericAddress(null); - fail("expected null to throw a NullPointerException"); - } catch (NullPointerException e) { - // expected - } - } -} diff --git a/tests/cts/net/src/android/net/cts/IpConfigurationTest.java b/tests/cts/net/src/android/net/cts/IpConfigurationTest.java deleted file mode 100644 index 56ab2a7531..0000000000 --- a/tests/cts/net/src/android/net/cts/IpConfigurationTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2019 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.cts; - -import static com.android.testutils.ParcelUtils.assertParcelSane; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import android.net.IpConfiguration; -import android.net.LinkAddress; -import android.net.ProxyInfo; -import android.net.StaticIpConfiguration; - -import androidx.test.runner.AndroidJUnit4; - -import libcore.net.InetAddressUtils; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.InetAddress; -import java.util.ArrayList; - -@RunWith(AndroidJUnit4.class) -public final class IpConfigurationTest { - private static final LinkAddress LINKADDR = new LinkAddress("192.0.2.2/25"); - private static final InetAddress GATEWAY = InetAddressUtils.parseNumericAddress("192.0.2.1"); - private static final InetAddress DNS1 = InetAddressUtils.parseNumericAddress("8.8.8.8"); - private static final InetAddress DNS2 = InetAddressUtils.parseNumericAddress("8.8.4.4"); - private static final String DOMAINS = "example.com"; - - private static final ArrayList dnsServers = new ArrayList<>(); - - private StaticIpConfiguration mStaticIpConfig; - private ProxyInfo mProxy; - - @Before - public void setUp() { - dnsServers.add(DNS1); - dnsServers.add(DNS2); - mStaticIpConfig = new StaticIpConfiguration.Builder() - .setIpAddress(LINKADDR) - .setGateway(GATEWAY) - .setDnsServers(dnsServers) - .setDomains(DOMAINS) - .build(); - - mProxy = ProxyInfo.buildDirectProxy("test", 8888); - } - - @Test - public void testConstructor() { - IpConfiguration ipConfig = new IpConfiguration(); - checkEmpty(ipConfig); - assertIpConfigurationEqual(ipConfig, new IpConfiguration()); - assertIpConfigurationEqual(ipConfig, new IpConfiguration(ipConfig)); - - ipConfig.setStaticIpConfiguration(mStaticIpConfig); - ipConfig.setHttpProxy(mProxy); - - ipConfig.setIpAssignment(IpConfiguration.IpAssignment.STATIC); - ipConfig.setProxySettings(IpConfiguration.ProxySettings.PAC); - assertIpConfigurationEqual(ipConfig, new IpConfiguration(ipConfig)); - - ipConfig.setIpAssignment(IpConfiguration.IpAssignment.STATIC); - ipConfig.setProxySettings(IpConfiguration.ProxySettings.STATIC); - assertIpConfigurationEqual(ipConfig, new IpConfiguration(ipConfig)); - - ipConfig.setIpAssignment(IpConfiguration.IpAssignment.DHCP); - ipConfig.setProxySettings(IpConfiguration.ProxySettings.PAC); - assertIpConfigurationEqual(ipConfig, new IpConfiguration(ipConfig)); - - ipConfig.setIpAssignment(IpConfiguration.IpAssignment.DHCP); - ipConfig.setProxySettings(IpConfiguration.ProxySettings.PAC); - assertIpConfigurationEqual(ipConfig, new IpConfiguration(ipConfig)); - - ipConfig.setIpAssignment(IpConfiguration.IpAssignment.DHCP); - ipConfig.setProxySettings(IpConfiguration.ProxySettings.STATIC); - assertIpConfigurationEqual(ipConfig, new IpConfiguration(ipConfig)); - - ipConfig.setIpAssignment(IpConfiguration.IpAssignment.DHCP); - ipConfig.setProxySettings(IpConfiguration.ProxySettings.NONE); - assertIpConfigurationEqual(ipConfig, new IpConfiguration(ipConfig)); - } - - private void checkEmpty(IpConfiguration config) { - assertEquals(IpConfiguration.IpAssignment.UNASSIGNED, - config.getIpAssignment().UNASSIGNED); - assertEquals(IpConfiguration.ProxySettings.UNASSIGNED, - config.getProxySettings().UNASSIGNED); - assertNull(config.getStaticIpConfiguration()); - assertNull(config.getHttpProxy()); - } - - private void assertIpConfigurationEqual(IpConfiguration source, IpConfiguration target) { - assertEquals(source.getIpAssignment(), target.getIpAssignment()); - assertEquals(source.getProxySettings(), target.getProxySettings()); - assertEquals(source.getHttpProxy(), target.getHttpProxy()); - assertEquals(source.getStaticIpConfiguration(), target.getStaticIpConfiguration()); - } - - @Test - public void testParcel() { - final IpConfiguration config = new IpConfiguration(); - assertParcelSane(config, 4); - } -} diff --git a/tests/cts/net/src/android/net/cts/IpSecBaseTest.java b/tests/cts/net/src/android/net/cts/IpSecBaseTest.java deleted file mode 100644 index 10e43e7b6a..0000000000 --- a/tests/cts/net/src/android/net/cts/IpSecBaseTest.java +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright (C) 2018 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.cts; - -import static org.junit.Assert.assertArrayEquals; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.IpSecAlgorithm; -import android.net.IpSecManager; -import android.net.IpSecTransform; -import android.platform.test.annotations.AppModeFull; -import android.system.Os; -import android.system.OsConstants; -import android.util.Log; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -public class IpSecBaseTest { - - private static final String TAG = IpSecBaseTest.class.getSimpleName(); - - protected static final String IPV4_LOOPBACK = "127.0.0.1"; - protected static final String IPV6_LOOPBACK = "::1"; - protected static final String[] LOOPBACK_ADDRS = new String[] {IPV4_LOOPBACK, IPV6_LOOPBACK}; - protected static final int[] DIRECTIONS = - new int[] {IpSecManager.DIRECTION_IN, IpSecManager.DIRECTION_OUT}; - - protected static final byte[] TEST_DATA = "Best test data ever!".getBytes(); - protected static final int DATA_BUFFER_LEN = 4096; - protected static final int SOCK_TIMEOUT = 500; - - private static final byte[] KEY_DATA = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23 - }; - - protected static final byte[] AUTH_KEY = getKey(256); - protected static final byte[] CRYPT_KEY = getKey(256); - - protected ConnectivityManager mCM; - protected IpSecManager mISM; - - @Before - public void setUp() throws Exception { - mISM = - (IpSecManager) - InstrumentationRegistry.getContext() - .getSystemService(Context.IPSEC_SERVICE); - mCM = - (ConnectivityManager) - InstrumentationRegistry.getContext() - .getSystemService(Context.CONNECTIVITY_SERVICE); - } - - protected static byte[] getKey(int bitLength) { - return Arrays.copyOf(KEY_DATA, bitLength / 8); - } - - protected static int getDomain(InetAddress address) { - int domain; - if (address instanceof Inet6Address) { - domain = OsConstants.AF_INET6; - } else { - domain = OsConstants.AF_INET; - } - return domain; - } - - protected static int getPort(FileDescriptor sock) throws Exception { - return ((InetSocketAddress) Os.getsockname(sock)).getPort(); - } - - public static interface GenericSocket extends AutoCloseable { - void send(byte[] data) throws Exception; - - byte[] receive() throws Exception; - - int getPort() throws Exception; - - void close() throws Exception; - - void applyTransportModeTransform( - IpSecManager ism, int direction, IpSecTransform transform) throws Exception; - - void removeTransportModeTransforms(IpSecManager ism) throws Exception; - } - - public static interface GenericTcpSocket extends GenericSocket {} - - public static interface GenericUdpSocket extends GenericSocket { - void sendTo(byte[] data, InetAddress dstAddr, int port) throws Exception; - } - - public abstract static class NativeSocket implements GenericSocket { - public FileDescriptor mFd; - - public NativeSocket(FileDescriptor fd) { - mFd = fd; - } - - @Override - public void send(byte[] data) throws Exception { - Os.write(mFd, data, 0, data.length); - } - - @Override - public byte[] receive() throws Exception { - byte[] in = new byte[DATA_BUFFER_LEN]; - AtomicInteger bytesRead = new AtomicInteger(-1); - - Thread readSockThread = new Thread(() -> { - long startTime = System.currentTimeMillis(); - while (bytesRead.get() < 0 && System.currentTimeMillis() < startTime + SOCK_TIMEOUT) { - try { - bytesRead.set(Os.recvfrom(mFd, in, 0, DATA_BUFFER_LEN, 0, null)); - } catch (Exception e) { - Log.e(TAG, "Error encountered reading from socket", e); - } - } - }); - - readSockThread.start(); - readSockThread.join(SOCK_TIMEOUT); - - if (bytesRead.get() < 0) { - throw new IOException("No data received from socket"); - } - - return Arrays.copyOfRange(in, 0, bytesRead.get()); - } - - @Override - public int getPort() throws Exception { - return IpSecBaseTest.getPort(mFd); - } - - @Override - public void close() throws Exception { - Os.close(mFd); - } - - @Override - public void applyTransportModeTransform( - IpSecManager ism, int direction, IpSecTransform transform) throws Exception { - ism.applyTransportModeTransform(mFd, direction, transform); - } - - @Override - public void removeTransportModeTransforms(IpSecManager ism) throws Exception { - ism.removeTransportModeTransforms(mFd); - } - } - - public static class NativeTcpSocket extends NativeSocket implements GenericTcpSocket { - public NativeTcpSocket(FileDescriptor fd) { - super(fd); - } - } - - public static class NativeUdpSocket extends NativeSocket implements GenericUdpSocket { - public NativeUdpSocket(FileDescriptor fd) { - super(fd); - } - - @Override - public void sendTo(byte[] data, InetAddress dstAddr, int port) throws Exception { - Os.sendto(mFd, data, 0, data.length, 0, dstAddr, port); - } - } - - public static class JavaUdpSocket implements GenericUdpSocket { - public final DatagramSocket mSocket; - - public JavaUdpSocket(InetAddress localAddr, int port) { - try { - mSocket = new DatagramSocket(port, localAddr); - mSocket.setSoTimeout(SOCK_TIMEOUT); - } catch (SocketException e) { - // Fail loudly if we can't set up sockets properly. And without the timeout, we - // could easily end up in an endless wait. - throw new RuntimeException(e); - } - } - - public JavaUdpSocket(InetAddress localAddr) { - try { - mSocket = new DatagramSocket(0, localAddr); - mSocket.setSoTimeout(SOCK_TIMEOUT); - } catch (SocketException e) { - // Fail loudly if we can't set up sockets properly. And without the timeout, we - // could easily end up in an endless wait. - throw new RuntimeException(e); - } - } - - @Override - public void send(byte[] data) throws Exception { - mSocket.send(new DatagramPacket(data, data.length)); - } - - @Override - public void sendTo(byte[] data, InetAddress dstAddr, int port) throws Exception { - mSocket.send(new DatagramPacket(data, data.length, dstAddr, port)); - } - - @Override - public int getPort() throws Exception { - return mSocket.getLocalPort(); - } - - @Override - public void close() throws Exception { - mSocket.close(); - } - - @Override - public byte[] receive() throws Exception { - DatagramPacket data = new DatagramPacket(new byte[DATA_BUFFER_LEN], DATA_BUFFER_LEN); - mSocket.receive(data); - return Arrays.copyOfRange(data.getData(), 0, data.getLength()); - } - - @Override - public void applyTransportModeTransform( - IpSecManager ism, int direction, IpSecTransform transform) throws Exception { - ism.applyTransportModeTransform(mSocket, direction, transform); - } - - @Override - public void removeTransportModeTransforms(IpSecManager ism) throws Exception { - ism.removeTransportModeTransforms(mSocket); - } - } - - public static class JavaTcpSocket implements GenericTcpSocket { - public final Socket mSocket; - - public JavaTcpSocket(Socket socket) { - mSocket = socket; - try { - mSocket.setSoTimeout(SOCK_TIMEOUT); - } catch (SocketException e) { - // Fail loudly if we can't set up sockets properly. And without the timeout, we - // could easily end up in an endless wait. - throw new RuntimeException(e); - } - } - - @Override - public void send(byte[] data) throws Exception { - mSocket.getOutputStream().write(data); - } - - @Override - public byte[] receive() throws Exception { - byte[] in = new byte[DATA_BUFFER_LEN]; - int bytesRead = mSocket.getInputStream().read(in); - return Arrays.copyOfRange(in, 0, bytesRead); - } - - @Override - public int getPort() throws Exception { - return mSocket.getLocalPort(); - } - - @Override - public void close() throws Exception { - mSocket.close(); - } - - @Override - public void applyTransportModeTransform( - IpSecManager ism, int direction, IpSecTransform transform) throws Exception { - ism.applyTransportModeTransform(mSocket, direction, transform); - } - - @Override - public void removeTransportModeTransforms(IpSecManager ism) throws Exception { - ism.removeTransportModeTransforms(mSocket); - } - } - - public static class SocketPair { - public final T mLeftSock; - public final T mRightSock; - - public SocketPair(T leftSock, T rightSock) { - mLeftSock = leftSock; - mRightSock = rightSock; - } - } - - protected static void applyTransformBidirectionally( - IpSecManager ism, IpSecTransform transform, GenericSocket socket) throws Exception { - for (int direction : DIRECTIONS) { - socket.applyTransportModeTransform(ism, direction, transform); - } - } - - public static SocketPair getNativeUdpSocketPair( - InetAddress localAddr, IpSecManager ism, IpSecTransform transform, boolean connected) - throws Exception { - int domain = getDomain(localAddr); - - NativeUdpSocket leftSock = new NativeUdpSocket( - Os.socket(domain, OsConstants.SOCK_DGRAM, OsConstants.IPPROTO_UDP)); - NativeUdpSocket rightSock = new NativeUdpSocket( - Os.socket(domain, OsConstants.SOCK_DGRAM, OsConstants.IPPROTO_UDP)); - - for (NativeUdpSocket sock : new NativeUdpSocket[] {leftSock, rightSock}) { - applyTransformBidirectionally(ism, transform, sock); - Os.bind(sock.mFd, localAddr, 0); - } - - if (connected) { - Os.connect(leftSock.mFd, localAddr, rightSock.getPort()); - Os.connect(rightSock.mFd, localAddr, leftSock.getPort()); - } - - return new SocketPair<>(leftSock, rightSock); - } - - public static SocketPair getNativeTcpSocketPair( - InetAddress localAddr, IpSecManager ism, IpSecTransform transform) throws Exception { - int domain = getDomain(localAddr); - - NativeTcpSocket server = new NativeTcpSocket( - Os.socket(domain, OsConstants.SOCK_STREAM, OsConstants.IPPROTO_TCP)); - NativeTcpSocket client = new NativeTcpSocket( - Os.socket(domain, OsConstants.SOCK_STREAM, OsConstants.IPPROTO_TCP)); - - Os.bind(server.mFd, localAddr, 0); - - applyTransformBidirectionally(ism, transform, server); - applyTransformBidirectionally(ism, transform, client); - - Os.listen(server.mFd, 10); - Os.connect(client.mFd, localAddr, server.getPort()); - NativeTcpSocket accepted = new NativeTcpSocket(Os.accept(server.mFd, null)); - - applyTransformBidirectionally(ism, transform, accepted); - server.close(); - - return new SocketPair<>(client, accepted); - } - - public static SocketPair getJavaUdpSocketPair( - InetAddress localAddr, IpSecManager ism, IpSecTransform transform, boolean connected) - throws Exception { - JavaUdpSocket leftSock = new JavaUdpSocket(localAddr); - JavaUdpSocket rightSock = new JavaUdpSocket(localAddr); - - applyTransformBidirectionally(ism, transform, leftSock); - applyTransformBidirectionally(ism, transform, rightSock); - - if (connected) { - leftSock.mSocket.connect(localAddr, rightSock.mSocket.getLocalPort()); - rightSock.mSocket.connect(localAddr, leftSock.mSocket.getLocalPort()); - } - - return new SocketPair<>(leftSock, rightSock); - } - - public static SocketPair getJavaTcpSocketPair( - InetAddress localAddr, IpSecManager ism, IpSecTransform transform) throws Exception { - JavaTcpSocket clientSock = new JavaTcpSocket(new Socket()); - ServerSocket serverSocket = new ServerSocket(); - serverSocket.bind(new InetSocketAddress(localAddr, 0)); - - // While technically the client socket does not need to be bound, the OpenJDK implementation - // of Socket only allocates an FD when bind() or connect() or other similar methods are - // called. So we call bind to force the FD creation, so that we can apply a transform to it - // prior to socket connect. - clientSock.mSocket.bind(new InetSocketAddress(localAddr, 0)); - - // IpSecService doesn't support serverSockets at the moment; workaround using FD - FileDescriptor serverFd = serverSocket.getImpl().getFD$(); - - applyTransformBidirectionally(ism, transform, new NativeTcpSocket(serverFd)); - applyTransformBidirectionally(ism, transform, clientSock); - - clientSock.mSocket.connect(new InetSocketAddress(localAddr, serverSocket.getLocalPort())); - JavaTcpSocket acceptedSock = new JavaTcpSocket(serverSocket.accept()); - - applyTransformBidirectionally(ism, transform, acceptedSock); - serverSocket.close(); - - return new SocketPair<>(clientSock, acceptedSock); - } - - private void checkSocketPair(GenericSocket left, GenericSocket right) throws Exception { - left.send(TEST_DATA); - assertArrayEquals(TEST_DATA, right.receive()); - - right.send(TEST_DATA); - assertArrayEquals(TEST_DATA, left.receive()); - - left.close(); - right.close(); - } - - private void checkUnconnectedUdpSocketPair( - GenericUdpSocket left, GenericUdpSocket right, InetAddress localAddr) throws Exception { - left.sendTo(TEST_DATA, localAddr, right.getPort()); - assertArrayEquals(TEST_DATA, right.receive()); - - right.sendTo(TEST_DATA, localAddr, left.getPort()); - assertArrayEquals(TEST_DATA, left.receive()); - - left.close(); - right.close(); - } - - protected static IpSecTransform buildIpSecTransform( - Context context, - IpSecManager.SecurityParameterIndex spi, - IpSecManager.UdpEncapsulationSocket encapSocket, - InetAddress remoteAddr) - throws Exception { - IpSecTransform.Builder builder = - new IpSecTransform.Builder(context) - .setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY)) - .setAuthentication( - new IpSecAlgorithm( - IpSecAlgorithm.AUTH_HMAC_SHA256, - AUTH_KEY, - AUTH_KEY.length * 4)); - - if (encapSocket != null) { - builder.setIpv4Encapsulation(encapSocket, encapSocket.getPort()); - } - - return builder.buildTransportModeTransform(remoteAddr, spi); - } - - private IpSecTransform buildDefaultTransform(InetAddress localAddr) throws Exception { - try (IpSecManager.SecurityParameterIndex spi = - mISM.allocateSecurityParameterIndex(localAddr)) { - return buildIpSecTransform(InstrumentationRegistry.getContext(), spi, null, localAddr); - } - } - - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void testJavaTcpSocketPair() throws Exception { - for (String addr : LOOPBACK_ADDRS) { - InetAddress local = InetAddress.getByName(addr); - try (IpSecTransform transform = buildDefaultTransform(local)) { - SocketPair sockets = getJavaTcpSocketPair(local, mISM, transform); - checkSocketPair(sockets.mLeftSock, sockets.mRightSock); - } - } - } - - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void testJavaUdpSocketPair() throws Exception { - for (String addr : LOOPBACK_ADDRS) { - InetAddress local = InetAddress.getByName(addr); - try (IpSecTransform transform = buildDefaultTransform(local)) { - SocketPair sockets = - getJavaUdpSocketPair(local, mISM, transform, true); - checkSocketPair(sockets.mLeftSock, sockets.mRightSock); - } - } - } - - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void testJavaUdpSocketPairUnconnected() throws Exception { - for (String addr : LOOPBACK_ADDRS) { - InetAddress local = InetAddress.getByName(addr); - try (IpSecTransform transform = buildDefaultTransform(local)) { - SocketPair sockets = - getJavaUdpSocketPair(local, mISM, transform, false); - checkUnconnectedUdpSocketPair(sockets.mLeftSock, sockets.mRightSock, local); - } - } - } - - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void testNativeTcpSocketPair() throws Exception { - for (String addr : LOOPBACK_ADDRS) { - InetAddress local = InetAddress.getByName(addr); - try (IpSecTransform transform = buildDefaultTransform(local)) { - SocketPair sockets = - getNativeTcpSocketPair(local, mISM, transform); - checkSocketPair(sockets.mLeftSock, sockets.mRightSock); - } - } - } - - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void testNativeUdpSocketPair() throws Exception { - for (String addr : LOOPBACK_ADDRS) { - InetAddress local = InetAddress.getByName(addr); - try (IpSecTransform transform = buildDefaultTransform(local)) { - SocketPair sockets = - getNativeUdpSocketPair(local, mISM, transform, true); - checkSocketPair(sockets.mLeftSock, sockets.mRightSock); - } - } - } - - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void testNativeUdpSocketPairUnconnected() throws Exception { - for (String addr : LOOPBACK_ADDRS) { - InetAddress local = InetAddress.getByName(addr); - try (IpSecTransform transform = buildDefaultTransform(local)) { - SocketPair sockets = - getNativeUdpSocketPair(local, mISM, transform, false); - checkUnconnectedUdpSocketPair(sockets.mLeftSock, sockets.mRightSock, local); - } - } - } -} diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java deleted file mode 100644 index 355b496829..0000000000 --- a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java +++ /dev/null @@ -1,1189 +0,0 @@ -/* - * Copyright (C) 2017 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.cts; - -import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE; -import static android.net.cts.PacketUtils.AES_CBC_IV_LEN; -import static android.net.cts.PacketUtils.AES_GCM_BLK_SIZE; -import static android.net.cts.PacketUtils.AES_GCM_IV_LEN; -import static android.net.cts.PacketUtils.IP4_HDRLEN; -import static android.net.cts.PacketUtils.IP6_HDRLEN; -import static android.net.cts.PacketUtils.TCP_HDRLEN_WITH_TIMESTAMP_OPT; -import static android.net.cts.PacketUtils.UDP_HDRLEN; -import static android.system.OsConstants.IPPROTO_TCP; -import static android.system.OsConstants.IPPROTO_UDP; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.net.IpSecAlgorithm; -import android.net.IpSecManager; -import android.net.IpSecTransform; -import android.net.TrafficStats; -import android.platform.test.annotations.AppModeFull; -import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.util.Arrays; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@AppModeFull(reason = "Socket cannot bind in instant app mode") -public class IpSecManagerTest extends IpSecBaseTest { - - private static final String TAG = IpSecManagerTest.class.getSimpleName(); - - private static final InetAddress GOOGLE_DNS_4 = InetAddress.parseNumericAddress("8.8.8.8"); - private static final InetAddress GOOGLE_DNS_6 = - InetAddress.parseNumericAddress("2001:4860:4860::8888"); - - private static final InetAddress[] GOOGLE_DNS_LIST = - new InetAddress[] {GOOGLE_DNS_4, GOOGLE_DNS_6}; - - private static final int DROID_SPI = 0xD1201D; - private static final int MAX_PORT_BIND_ATTEMPTS = 10; - - private static final byte[] AEAD_KEY = getKey(288); - - /* - * Allocate a random SPI - * Allocate a specific SPI using previous randomly created SPI value - * Realloc the same SPI that was specifically created (expect SpiUnavailable) - * Close SPIs - */ - @Test - public void testAllocSpi() throws Exception { - for (InetAddress addr : GOOGLE_DNS_LIST) { - IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null; - randomSpi = mISM.allocateSecurityParameterIndex(addr); - assertTrue( - "Failed to receive a valid SPI", - randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); - - droidSpi = mISM.allocateSecurityParameterIndex(addr, DROID_SPI); - assertTrue("Failed to allocate specified SPI, " + DROID_SPI, - droidSpi.getSpi() == DROID_SPI); - - try { - mISM.allocateSecurityParameterIndex(addr, DROID_SPI); - fail("Duplicate SPI was allowed to be created"); - } catch (IpSecManager.SpiUnavailableException expected) { - // This is a success case because we expect a dupe SPI to throw - } - - randomSpi.close(); - droidSpi.close(); - } - } - - /** This function finds an available port */ - private static int findUnusedPort() throws Exception { - // Get an available port. - DatagramSocket s = new DatagramSocket(); - int port = s.getLocalPort(); - s.close(); - return port; - } - - private static FileDescriptor getBoundUdpSocket(InetAddress address) throws Exception { - FileDescriptor sock = - Os.socket(getDomain(address), OsConstants.SOCK_DGRAM, OsConstants.IPPROTO_UDP); - - for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) { - try { - int port = findUnusedPort(); - Os.bind(sock, address, port); - break; - } catch (ErrnoException e) { - // Someone claimed the port since we called findUnusedPort. - if (e.errno == OsConstants.EADDRINUSE) { - if (i == MAX_PORT_BIND_ATTEMPTS - 1) { - - fail("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port"); - } - continue; - } - throw e.rethrowAsIOException(); - } - } - return sock; - } - - private void checkUnconnectedUdp(IpSecTransform transform, InetAddress local, int sendCount, - boolean useJavaSockets) throws Exception { - GenericUdpSocket sockLeft = null, sockRight = null; - if (useJavaSockets) { - SocketPair sockets = getJavaUdpSocketPair(local, mISM, transform, false); - sockLeft = sockets.mLeftSock; - sockRight = sockets.mRightSock; - } else { - SocketPair sockets = - getNativeUdpSocketPair(local, mISM, transform, false); - sockLeft = sockets.mLeftSock; - sockRight = sockets.mRightSock; - } - - for (int i = 0; i < sendCount; i++) { - byte[] in; - - sockLeft.sendTo(TEST_DATA, local, sockRight.getPort()); - in = sockRight.receive(); - assertArrayEquals("Left-to-right encrypted data did not match.", TEST_DATA, in); - - sockRight.sendTo(TEST_DATA, local, sockLeft.getPort()); - in = sockLeft.receive(); - assertArrayEquals("Right-to-left encrypted data did not match.", TEST_DATA, in); - } - - sockLeft.close(); - sockRight.close(); - } - - private void checkTcp(IpSecTransform transform, InetAddress local, int sendCount, - boolean useJavaSockets) throws Exception { - GenericTcpSocket client = null, accepted = null; - if (useJavaSockets) { - SocketPair sockets = getJavaTcpSocketPair(local, mISM, transform); - client = sockets.mLeftSock; - accepted = sockets.mRightSock; - } else { - SocketPair sockets = getNativeTcpSocketPair(local, mISM, transform); - client = sockets.mLeftSock; - accepted = sockets.mRightSock; - } - - // Wait for TCP handshake packets to be counted - StatsChecker.waitForNumPackets(3); // (SYN, SYN+ACK, ACK) - - // Reset StatsChecker, to ignore negotiation overhead. - StatsChecker.initStatsChecker(); - for (int i = 0; i < sendCount; i++) { - byte[] in; - - client.send(TEST_DATA); - in = accepted.receive(); - assertArrayEquals("Client-to-server encrypted data did not match.", TEST_DATA, in); - - // Allow for newest data + ack packets to be returned before sending next packet - // Also add the number of expected packets in each of the previous runs (4 per run) - StatsChecker.waitForNumPackets(2 + (4 * i)); - - accepted.send(TEST_DATA); - in = client.receive(); - assertArrayEquals("Server-to-client encrypted data did not match.", TEST_DATA, in); - - // Allow for all data + ack packets to be returned before sending next packet - // Also add the number of expected packets in each of the previous runs (4 per run) - StatsChecker.waitForNumPackets(4 * (i + 1)); - } - - // Transforms should not be removed from the sockets, otherwise FIN packets will be sent - // unencrypted. - // This test also unfortunately happens to rely on a nuance of the cleanup order. By - // keeping the policy on the socket, but removing the SA before lingering FIN packets - // are sent (at an undetermined later time), the FIN packets are dropped. Without this, - // we run into all kinds of headaches trying to test data accounting (unsolicited - // packets mysteriously appearing and messing up our counters) - // The right way to close sockets is to set SO_LINGER to ensure synchronous closure, - // closing the sockets, and then closing the transforms. See documentation for the - // Socket or FileDescriptor flavors of applyTransportModeTransform() in IpSecManager - // for more details. - - client.close(); - accepted.close(); - } - - /* - * Alloc outbound SPI - * Alloc inbound SPI - * Create transport mode transform - * open socket - * apply transform to socket - * send data on socket - * release transform - * send data (expect exception) - */ - @Test - public void testCreateTransform() throws Exception { - InetAddress localAddr = InetAddress.getByName(IPV4_LOOPBACK); - IpSecManager.SecurityParameterIndex spi = - mISM.allocateSecurityParameterIndex(localAddr); - - IpSecTransform transform = - new IpSecTransform.Builder(InstrumentationRegistry.getContext()) - .setEncryption(new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY)) - .setAuthentication( - new IpSecAlgorithm( - IpSecAlgorithm.AUTH_HMAC_SHA256, - AUTH_KEY, - AUTH_KEY.length * 8)) - .buildTransportModeTransform(localAddr, spi); - - final boolean [][] applyInApplyOut = { - {false, false}, {false, true}, {true, false}, {true,true}}; - final byte[] data = new String("Best test data ever!").getBytes("UTF-8"); - final DatagramPacket outPacket = new DatagramPacket(data, 0, data.length, localAddr, 0); - - byte[] in = new byte[data.length]; - DatagramPacket inPacket = new DatagramPacket(in, in.length); - DatagramSocket localSocket; - int localPort; - - for(boolean[] io : applyInApplyOut) { - boolean applyIn = io[0]; - boolean applyOut = io[1]; - // Bind localSocket to a random available port. - localSocket = new DatagramSocket(0); - localPort = localSocket.getLocalPort(); - localSocket.setSoTimeout(200); - outPacket.setPort(localPort); - if (applyIn) { - mISM.applyTransportModeTransform( - localSocket, IpSecManager.DIRECTION_IN, transform); - } - if (applyOut) { - mISM.applyTransportModeTransform( - localSocket, IpSecManager.DIRECTION_OUT, transform); - } - if (applyIn == applyOut) { - localSocket.send(outPacket); - localSocket.receive(inPacket); - assertTrue("Encapsulated data did not match.", - Arrays.equals(outPacket.getData(), inPacket.getData())); - mISM.removeTransportModeTransforms(localSocket); - localSocket.close(); - } else { - try { - localSocket.send(outPacket); - localSocket.receive(inPacket); - } catch (IOException e) { - continue; - } finally { - mISM.removeTransportModeTransforms(localSocket); - localSocket.close(); - } - // FIXME: This check is disabled because sockets currently receive data - // if there is a valid SA for decryption, even when the input policy is - // not applied to a socket. - // fail("Data IO should fail on asymmetrical transforms! + Input=" - // + applyIn + " Output=" + applyOut); - } - } - transform.close(); - } - - /** Snapshot of TrafficStats as of initStatsChecker call for later comparisons */ - private static class StatsChecker { - private static final double ERROR_MARGIN_BYTES = 1.05; - private static final double ERROR_MARGIN_PKTS = 1.05; - private static final int MAX_WAIT_TIME_MILLIS = 1000; - - private static long uidTxBytes; - private static long uidRxBytes; - private static long uidTxPackets; - private static long uidRxPackets; - - private static long ifaceTxBytes; - private static long ifaceRxBytes; - private static long ifaceTxPackets; - private static long ifaceRxPackets; - - /** - * This method counts the number of incoming packets, polling intermittently up to - * MAX_WAIT_TIME_MILLIS. - */ - private static void waitForNumPackets(int numPackets) throws Exception { - long uidTxDelta = 0; - long uidRxDelta = 0; - for (int i = 0; i < 100; i++) { - uidTxDelta = TrafficStats.getUidTxPackets(Os.getuid()) - uidTxPackets; - uidRxDelta = TrafficStats.getUidRxPackets(Os.getuid()) - uidRxPackets; - - // TODO: Check Rx packets as well once kernel security policy bug is fixed. - // (b/70635417) - if (uidTxDelta >= numPackets) { - return; - } - Thread.sleep(MAX_WAIT_TIME_MILLIS / 100); - } - fail( - "Not enough traffic was recorded to satisfy the provided conditions: wanted " - + numPackets - + ", got " - + uidTxDelta - + " tx and " - + uidRxDelta - + " rx packets"); - } - - private static void assertUidStatsDelta( - int expectedTxByteDelta, - int expectedTxPacketDelta, - int minRxByteDelta, - int maxRxByteDelta, - int expectedRxPacketDelta) { - long newUidTxBytes = TrafficStats.getUidTxBytes(Os.getuid()); - long newUidRxBytes = TrafficStats.getUidRxBytes(Os.getuid()); - long newUidTxPackets = TrafficStats.getUidTxPackets(Os.getuid()); - long newUidRxPackets = TrafficStats.getUidRxPackets(Os.getuid()); - - assertEquals(expectedTxByteDelta, newUidTxBytes - uidTxBytes); - assertTrue( - newUidRxBytes - uidRxBytes >= minRxByteDelta - && newUidRxBytes - uidRxBytes <= maxRxByteDelta); - assertEquals(expectedTxPacketDelta, newUidTxPackets - uidTxPackets); - assertEquals(expectedRxPacketDelta, newUidRxPackets - uidRxPackets); - } - - private static void assertIfaceStatsDelta( - int expectedTxByteDelta, - int expectedTxPacketDelta, - int expectedRxByteDelta, - int expectedRxPacketDelta) - throws IOException { - long newIfaceTxBytes = TrafficStats.getLoopbackTxBytes(); - long newIfaceRxBytes = TrafficStats.getLoopbackRxBytes(); - long newIfaceTxPackets = TrafficStats.getLoopbackTxPackets(); - long newIfaceRxPackets = TrafficStats.getLoopbackRxPackets(); - - // Check that iface stats are within an acceptable range; data might be sent - // on the local interface by other apps. - assertApproxEquals( - ifaceTxBytes, newIfaceTxBytes, expectedTxByteDelta, ERROR_MARGIN_BYTES); - assertApproxEquals( - ifaceRxBytes, newIfaceRxBytes, expectedRxByteDelta, ERROR_MARGIN_BYTES); - assertApproxEquals( - ifaceTxPackets, newIfaceTxPackets, expectedTxPacketDelta, ERROR_MARGIN_PKTS); - assertApproxEquals( - ifaceRxPackets, newIfaceRxPackets, expectedRxPacketDelta, ERROR_MARGIN_PKTS); - } - - private static void assertApproxEquals( - long oldStats, long newStats, int expectedDelta, double errorMargin) { - assertTrue(expectedDelta <= newStats - oldStats); - assertTrue((expectedDelta * errorMargin) > newStats - oldStats); - } - - private static void initStatsChecker() throws Exception { - uidTxBytes = TrafficStats.getUidTxBytes(Os.getuid()); - uidRxBytes = TrafficStats.getUidRxBytes(Os.getuid()); - uidTxPackets = TrafficStats.getUidTxPackets(Os.getuid()); - uidRxPackets = TrafficStats.getUidRxPackets(Os.getuid()); - - ifaceTxBytes = TrafficStats.getLoopbackTxBytes(); - ifaceRxBytes = TrafficStats.getLoopbackRxBytes(); - ifaceTxPackets = TrafficStats.getLoopbackTxPackets(); - ifaceRxPackets = TrafficStats.getLoopbackRxPackets(); - } - } - - private int getTruncLenBits(IpSecAlgorithm authOrAead) { - return authOrAead == null ? 0 : authOrAead.getTruncationLengthBits(); - } - - private int getIvLen(IpSecAlgorithm cryptOrAead) { - if (cryptOrAead == null) { return 0; } - - switch (cryptOrAead.getName()) { - case IpSecAlgorithm.CRYPT_AES_CBC: - return AES_CBC_IV_LEN; - case IpSecAlgorithm.AUTH_CRYPT_AES_GCM: - return AES_GCM_IV_LEN; - default: - throw new IllegalArgumentException( - "IV length unknown for algorithm" + cryptOrAead.getName()); - } - } - - private int getBlkSize(IpSecAlgorithm cryptOrAead) { - // RFC 4303, section 2.4 states that ciphertext plus pad_len, next_header fields must - // terminate on a 4-byte boundary. Thus, the minimum ciphertext block size is 4 bytes. - if (cryptOrAead == null) { return 4; } - - switch (cryptOrAead.getName()) { - case IpSecAlgorithm.CRYPT_AES_CBC: - return AES_CBC_BLK_SIZE; - case IpSecAlgorithm.AUTH_CRYPT_AES_GCM: - return AES_GCM_BLK_SIZE; - default: - throw new IllegalArgumentException( - "Blk size unknown for algorithm" + cryptOrAead.getName()); - } - } - - public void checkTransform( - int protocol, - String localAddress, - IpSecAlgorithm crypt, - IpSecAlgorithm auth, - IpSecAlgorithm aead, - boolean doUdpEncap, - int sendCount, - boolean useJavaSockets) - throws Exception { - StatsChecker.initStatsChecker(); - InetAddress local = InetAddress.getByName(localAddress); - - try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket(); - IpSecManager.SecurityParameterIndex spi = - mISM.allocateSecurityParameterIndex(local)) { - - IpSecTransform.Builder transformBuilder = - new IpSecTransform.Builder(InstrumentationRegistry.getContext()); - if (crypt != null) { - transformBuilder.setEncryption(crypt); - } - if (auth != null) { - transformBuilder.setAuthentication(auth); - } - if (aead != null) { - transformBuilder.setAuthenticatedEncryption(aead); - } - - if (doUdpEncap) { - transformBuilder = - transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort()); - } - - int ipHdrLen = local instanceof Inet6Address ? IP6_HDRLEN : IP4_HDRLEN; - int transportHdrLen = 0; - int udpEncapLen = doUdpEncap ? UDP_HDRLEN : 0; - - try (IpSecTransform transform = - transformBuilder.buildTransportModeTransform(local, spi)) { - if (protocol == IPPROTO_TCP) { - transportHdrLen = TCP_HDRLEN_WITH_TIMESTAMP_OPT; - checkTcp(transform, local, sendCount, useJavaSockets); - } else if (protocol == IPPROTO_UDP) { - transportHdrLen = UDP_HDRLEN; - - // TODO: Also check connected udp. - checkUnconnectedUdp(transform, local, sendCount, useJavaSockets); - } else { - throw new IllegalArgumentException("Invalid protocol"); - } - } - - checkStatsChecker( - protocol, - ipHdrLen, - transportHdrLen, - udpEncapLen, - sendCount, - getIvLen(crypt != null ? crypt : aead), - getBlkSize(crypt != null ? crypt : aead), - getTruncLenBits(auth != null ? auth : aead)); - } - } - - private void checkStatsChecker( - int protocol, - int ipHdrLen, - int transportHdrLen, - int udpEncapLen, - int sendCount, - int ivLen, - int blkSize, - int truncLenBits) - throws Exception { - - int innerPacketSize = TEST_DATA.length + transportHdrLen + ipHdrLen; - int outerPacketSize = - PacketUtils.calculateEspPacketSize( - TEST_DATA.length + transportHdrLen, ivLen, blkSize, truncLenBits) - + udpEncapLen - + ipHdrLen; - - int expectedOuterBytes = outerPacketSize * sendCount; - int expectedInnerBytes = innerPacketSize * sendCount; - int expectedPackets = sendCount; - - // Each run sends two packets, one in each direction. - sendCount *= 2; - expectedOuterBytes *= 2; - expectedInnerBytes *= 2; - expectedPackets *= 2; - - // Add TCP ACKs for data packets - if (protocol == IPPROTO_TCP) { - int encryptedTcpPktSize = - PacketUtils.calculateEspPacketSize( - TCP_HDRLEN_WITH_TIMESTAMP_OPT, ivLen, blkSize, truncLenBits); - - // Add data packet ACKs - expectedOuterBytes += (encryptedTcpPktSize + udpEncapLen + ipHdrLen) * (sendCount); - expectedInnerBytes += (TCP_HDRLEN_WITH_TIMESTAMP_OPT + ipHdrLen) * (sendCount); - expectedPackets += sendCount; - } - - StatsChecker.waitForNumPackets(expectedPackets); - - // eBPF only counts inner packets, whereas xt_qtaguid counts outer packets. Allow both - StatsChecker.assertUidStatsDelta( - expectedOuterBytes, - expectedPackets, - expectedInnerBytes, - expectedOuterBytes, - expectedPackets); - - // Unreliable at low numbers due to potential interference from other processes. - if (sendCount >= 1000) { - StatsChecker.assertIfaceStatsDelta( - expectedOuterBytes, expectedPackets, expectedOuterBytes, expectedPackets); - } - } - - private void checkIkePacket( - NativeUdpSocket wrappedEncapSocket, InetAddress localAddr) throws Exception { - StatsChecker.initStatsChecker(); - - try (NativeUdpSocket remoteSocket = new NativeUdpSocket(getBoundUdpSocket(localAddr))) { - - // Append IKE/ESP header - 4 bytes of SPI, 4 bytes of seq number, all zeroed out - // If the first four bytes are zero, assume non-ESP (IKE traffic) - byte[] dataWithEspHeader = new byte[TEST_DATA.length + 8]; - System.arraycopy(TEST_DATA, 0, dataWithEspHeader, 8, TEST_DATA.length); - - // Send the IKE packet from remoteSocket to wrappedEncapSocket. Since IKE packets - // are multiplexed over the socket, we expect them to appear on the encap socket - // (as opposed to being decrypted and received on the non-encap socket) - remoteSocket.sendTo(dataWithEspHeader, localAddr, wrappedEncapSocket.getPort()); - byte[] in = wrappedEncapSocket.receive(); - assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in); - - // Also test that the IKE socket can send data out. - wrappedEncapSocket.sendTo(dataWithEspHeader, localAddr, remoteSocket.getPort()); - in = remoteSocket.receive(); - assertArrayEquals("Encapsulated data did not match.", dataWithEspHeader, in); - - // Calculate expected packet sizes. Always use IPv4 header, since our kernels only - // guarantee support of UDP encap on IPv4. - int expectedNumPkts = 2; - int expectedPacketSize = - expectedNumPkts * (dataWithEspHeader.length + UDP_HDRLEN + IP4_HDRLEN); - - StatsChecker.waitForNumPackets(expectedNumPkts); - StatsChecker.assertUidStatsDelta( - expectedPacketSize, - expectedNumPkts, - expectedPacketSize, - expectedPacketSize, - expectedNumPkts); - StatsChecker.assertIfaceStatsDelta( - expectedPacketSize, expectedNumPkts, expectedPacketSize, expectedNumPkts); - } - } - - @Test - public void testIkeOverUdpEncapSocket() throws Exception { - // IPv6 not supported for UDP-encap-ESP - InetAddress local = InetAddress.getByName(IPV4_LOOPBACK); - try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) { - NativeUdpSocket wrappedEncapSocket = - new NativeUdpSocket(encapSocket.getFileDescriptor()); - checkIkePacket(wrappedEncapSocket, local); - - // Now try with a transform applied to a socket using this Encap socket - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - - try (IpSecManager.SecurityParameterIndex spi = - mISM.allocateSecurityParameterIndex(local); - IpSecTransform transform = - new IpSecTransform.Builder(InstrumentationRegistry.getContext()) - .setEncryption(crypt) - .setAuthentication(auth) - .setIpv4Encapsulation(encapSocket, encapSocket.getPort()) - .buildTransportModeTransform(local, spi); - JavaUdpSocket localSocket = new JavaUdpSocket(local)) { - applyTransformBidirectionally(mISM, transform, localSocket); - - checkIkePacket(wrappedEncapSocket, local); - } - } - } - - // TODO: Check IKE over ESP sockets (IPv4, IPv6) - does this need SOCK_RAW? - - /* TODO: Re-enable these when policy matcher works for reflected packets - * - * The issue here is that A sends to B, and everything is new; therefore PREROUTING counts - * correctly. But it appears that the security path is not cleared afterwards, thus when A - * sends an ACK back to B, the policy matcher flags it as a "IPSec" packet. See b/70635417 - */ - - // public void testInterfaceCountersTcp4() throws Exception { - // IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - // IpSecAlgorithm auth = new IpSecAlgorithm( - // IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - // checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, false, 1000); - // } - - // public void testInterfaceCountersTcp6() throws Exception { - // IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - // IpSecAlgorithm auth = new IpSecAlgorithm( - // IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - // checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, false, 1000); - // } - - // public void testInterfaceCountersTcp4UdpEncap() throws Exception { - // IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - // IpSecAlgorithm auth = - // new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - // checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, true, 1000); - // } - - @Test - public void testInterfaceCountersUdp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1000, false); - } - - @Test - public void testInterfaceCountersUdp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1000, false); - } - - @Test - public void testInterfaceCountersUdp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1000, false); - } - - @Test - public void testAesCbcHmacMd5Tcp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacMd5Tcp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacMd5Udp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacMd5Udp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha1Tcp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha1Tcp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha1Udp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha1Udp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha256Tcp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha256Tcp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha256Udp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha256Udp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha384Tcp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha384Tcp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha384Udp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha384Udp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha512Tcp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha512Tcp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha512Udp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesCbcHmacSha512Udp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, auth, null, false, 1, true); - } - - @Test - public void testAesGcm64Tcp4() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm64Tcp6() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm64Udp4() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm64Udp6() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm96Tcp4() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm96Tcp6() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm96Udp4() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm96Udp6() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm128Tcp4() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm128Tcp6() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm128Udp4() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesGcm128Udp6() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, null, authCrypt, false, 1, true); - } - - @Test - public void testAesCbcHmacMd5Tcp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesCbcHmacMd5Udp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_MD5, getKey(128), 96); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesCbcHmacSha1Tcp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesCbcHmacSha1Udp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA1, getKey(160), 96); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesCbcHmacSha256Tcp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesCbcHmacSha256Udp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesCbcHmacSha384Tcp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesCbcHmacSha384Udp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA384, getKey(384), 192); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesCbcHmacSha512Tcp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesCbcHmacSha512Udp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA512, getKey(512), 256); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, auth, null, true, 1, true); - } - - @Test - public void testAesGcm64Tcp4UdpEncap() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true); - } - - @Test - public void testAesGcm64Udp4UdpEncap() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 64); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true); - } - - @Test - public void testAesGcm96Tcp4UdpEncap() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true); - } - - @Test - public void testAesGcm96Udp4UdpEncap() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 96); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true); - } - - @Test - public void testAesGcm128Tcp4UdpEncap() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true); - } - - @Test - public void testAesGcm128Udp4UdpEncap() throws Exception { - IpSecAlgorithm authCrypt = - new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, null, authCrypt, true, 1, true); - } - - @Test - public void testCryptUdp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, false, 1, true); - } - - @Test - public void testAuthUdp4() throws Exception { - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, false, 1, true); - } - - @Test - public void testCryptUdp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, crypt, null, null, false, 1, true); - } - - @Test - public void testAuthUdp6() throws Exception { - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, false); - checkTransform(IPPROTO_UDP, IPV6_LOOPBACK, null, auth, null, false, 1, true); - } - - @Test - public void testCryptTcp4() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, false, 1, true); - } - - @Test - public void testAuthTcp4() throws Exception { - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, false, 1, true); - } - - @Test - public void testCryptTcp6() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, crypt, null, null, false, 1, true); - } - - @Test - public void testAuthTcp6() throws Exception { - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, false); - checkTransform(IPPROTO_TCP, IPV6_LOOPBACK, null, auth, null, false, 1, true); - } - - @Test - public void testCryptUdp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, crypt, null, null, true, 1, true); - } - - @Test - public void testAuthUdp4UdpEncap() throws Exception { - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, false); - checkTransform(IPPROTO_UDP, IPV4_LOOPBACK, null, auth, null, true, 1, true); - } - - @Test - public void testCryptTcp4UdpEncap() throws Exception { - IpSecAlgorithm crypt = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, crypt, null, null, true, 1, true); - } - - @Test - public void testAuthTcp4UdpEncap() throws Exception { - IpSecAlgorithm auth = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, getKey(256), 128); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, false); - checkTransform(IPPROTO_TCP, IPV4_LOOPBACK, null, auth, null, true, 1, true); - } - - @Test - public void testOpenUdpEncapSocketSpecificPort() throws Exception { - IpSecManager.UdpEncapsulationSocket encapSocket = null; - int port = -1; - for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) { - try { - port = findUnusedPort(); - encapSocket = mISM.openUdpEncapsulationSocket(port); - break; - } catch (ErrnoException e) { - if (e.errno == OsConstants.EADDRINUSE) { - // Someone claimed the port since we called findUnusedPort. - continue; - } - throw e; - } finally { - if (encapSocket != null) { - encapSocket.close(); - } - } - } - - if (encapSocket == null) { - fail("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port"); - } - - assertTrue("Returned invalid port", encapSocket.getPort() == port); - } - - @Test - public void testOpenUdpEncapSocketRandomPort() throws Exception { - try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) { - assertTrue("Returned invalid port", encapSocket.getPort() != 0); - } - } -} diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java deleted file mode 100644 index ae38faa124..0000000000 --- a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java +++ /dev/null @@ -1,899 +0,0 @@ -/* - * Copyright (C) 2018 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.cts; - -import static android.app.AppOpsManager.OP_MANAGE_IPSEC_TUNNELS; -import static android.net.IpSecManager.UdpEncapsulationSocket; -import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE; -import static android.net.cts.PacketUtils.AES_CBC_IV_LEN; -import static android.net.cts.PacketUtils.BytePayload; -import static android.net.cts.PacketUtils.EspHeader; -import static android.net.cts.PacketUtils.IP4_HDRLEN; -import static android.net.cts.PacketUtils.IP6_HDRLEN; -import static android.net.cts.PacketUtils.IpHeader; -import static android.net.cts.PacketUtils.UDP_HDRLEN; -import static android.net.cts.PacketUtils.UdpHeader; -import static android.net.cts.PacketUtils.getIpHeader; -import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.IpSecAlgorithm; -import android.net.IpSecManager; -import android.net.IpSecTransform; -import android.net.LinkAddress; -import android.net.Network; -import android.net.TestNetworkInterface; -import android.net.TestNetworkManager; -import android.net.cts.PacketUtils.Payload; -import android.net.cts.util.CtsNetUtils; -import android.os.ParcelFileDescriptor; -import android.platform.test.annotations.AppModeFull; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.NetworkInterface; - -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@AppModeFull(reason = "MANAGE_TEST_NETWORKS permission can't be granted to instant apps") -public class IpSecManagerTunnelTest extends IpSecBaseTest { - private static final String TAG = IpSecManagerTunnelTest.class.getSimpleName(); - - private static final InetAddress LOCAL_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.1"); - private static final InetAddress REMOTE_OUTER_4 = InetAddress.parseNumericAddress("192.0.2.2"); - private static final InetAddress LOCAL_OUTER_6 = - InetAddress.parseNumericAddress("2001:db8:1::1"); - private static final InetAddress REMOTE_OUTER_6 = - InetAddress.parseNumericAddress("2001:db8:1::2"); - - private static final InetAddress LOCAL_INNER_4 = - InetAddress.parseNumericAddress("198.51.100.1"); - private static final InetAddress REMOTE_INNER_4 = - InetAddress.parseNumericAddress("198.51.100.2"); - private static final InetAddress LOCAL_INNER_6 = - InetAddress.parseNumericAddress("2001:db8:2::1"); - private static final InetAddress REMOTE_INNER_6 = - InetAddress.parseNumericAddress("2001:db8:2::2"); - - private static final int IP4_PREFIX_LEN = 32; - private static final int IP6_PREFIX_LEN = 128; - - private static final int TIMEOUT_MS = 500; - - // Static state to reduce setup/teardown - private static ConnectivityManager sCM; - private static TestNetworkManager sTNM; - private static ParcelFileDescriptor sTunFd; - private static TestNetworkCallback sTunNetworkCallback; - private static Network sTunNetwork; - private static TunUtils sTunUtils; - - private static Context sContext = InstrumentationRegistry.getContext(); - private static final CtsNetUtils mCtsNetUtils = new CtsNetUtils(sContext); - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - InstrumentationRegistry.getInstrumentation() - .getUiAutomation() - .adoptShellPermissionIdentity(); - sCM = (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE); - sTNM = (TestNetworkManager) sContext.getSystemService(Context.TEST_NETWORK_SERVICE); - - // Under normal circumstances, the MANAGE_IPSEC_TUNNELS appop would be auto-granted, and - // a standard permission is insufficient. So we shell out the appop, to give us the - // right appop permissions. - mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, true); - - TestNetworkInterface testIface = - sTNM.createTunInterface( - new LinkAddress[] { - new LinkAddress(LOCAL_OUTER_4, IP4_PREFIX_LEN), - new LinkAddress(LOCAL_OUTER_6, IP6_PREFIX_LEN) - }); - - sTunFd = testIface.getFileDescriptor(); - sTunNetworkCallback = mCtsNetUtils.setupAndGetTestNetwork(testIface.getInterfaceName()); - sTunNetworkCallback.waitForAvailable(); - sTunNetwork = sTunNetworkCallback.currentNetwork; - - sTunUtils = new TunUtils(sTunFd); - } - - @Before - @Override - public void setUp() throws Exception { - super.setUp(); - - // Set to true before every run; some tests flip this. - mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, true); - - // Clear sTunUtils state - sTunUtils.reset(); - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, false); - - sCM.unregisterNetworkCallback(sTunNetworkCallback); - - sTNM.teardownTestNetwork(sTunNetwork); - sTunFd.close(); - - InstrumentationRegistry.getInstrumentation() - .getUiAutomation() - .dropShellPermissionIdentity(); - } - - @Test - public void testSecurityExceptionCreateTunnelInterfaceWithoutAppop() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - // Ensure we don't have the appop. Permission is not requested in the Manifest - mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, false); - - // Security exceptions are thrown regardless of IPv4/IPv6. Just test one - try { - mISM.createIpSecTunnelInterface(LOCAL_INNER_6, REMOTE_INNER_6, sTunNetwork); - fail("Did not throw SecurityException for Tunnel creation without appop"); - } catch (SecurityException expected) { - } - } - - @Test - public void testSecurityExceptionBuildTunnelTransformWithoutAppop() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - - // Ensure we don't have the appop. Permission is not requested in the Manifest - mCtsNetUtils.setAppopPrivileged(OP_MANAGE_IPSEC_TUNNELS, false); - - // Security exceptions are thrown regardless of IPv4/IPv6. Just test one - try (IpSecManager.SecurityParameterIndex spi = - mISM.allocateSecurityParameterIndex(LOCAL_INNER_4); - IpSecTransform transform = - new IpSecTransform.Builder(sContext) - .buildTunnelModeTransform(REMOTE_INNER_4, spi)) { - fail("Did not throw SecurityException for Transform creation without appop"); - } catch (SecurityException expected) { - } - } - - /* Test runnables for callbacks after IPsec tunnels are set up. */ - private abstract class IpSecTunnelTestRunnable { - /** - * Runs the test code, and returns the inner socket port, if any. - * - * @param ipsecNetwork The IPsec Interface based Network for binding sockets on - * @return the integer port of the inner socket if outbound, or 0 if inbound - * IpSecTunnelTestRunnable - * @throws Exception if any part of the test failed. - */ - public abstract int run(Network ipsecNetwork) throws Exception; - } - - private int getPacketSize( - int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode) { - int expectedPacketSize = TEST_DATA.length + UDP_HDRLEN; - - // Inner Transport mode packet size - if (transportInTunnelMode) { - expectedPacketSize = - PacketUtils.calculateEspPacketSize( - expectedPacketSize, - AES_CBC_IV_LEN, - AES_CBC_BLK_SIZE, - AUTH_KEY.length * 4); - } - - // Inner IP Header - expectedPacketSize += innerFamily == AF_INET ? IP4_HDRLEN : IP6_HDRLEN; - - // Tunnel mode transform size - expectedPacketSize = - PacketUtils.calculateEspPacketSize( - expectedPacketSize, AES_CBC_IV_LEN, AES_CBC_BLK_SIZE, AUTH_KEY.length * 4); - - // UDP encap size - expectedPacketSize += useEncap ? UDP_HDRLEN : 0; - - // Outer IP Header - expectedPacketSize += outerFamily == AF_INET ? IP4_HDRLEN : IP6_HDRLEN; - - return expectedPacketSize; - } - - private interface IpSecTunnelTestRunnableFactory { - IpSecTunnelTestRunnable getIpSecTunnelTestRunnable( - boolean transportInTunnelMode, - int spi, - InetAddress localInner, - InetAddress remoteInner, - InetAddress localOuter, - InetAddress remoteOuter, - IpSecTransform inTransportTransform, - IpSecTransform outTransportTransform, - int encapPort, - int innerSocketPort, - int expectedPacketSize) - throws Exception; - } - - private class OutputIpSecTunnelTestRunnableFactory implements IpSecTunnelTestRunnableFactory { - public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable( - boolean transportInTunnelMode, - int spi, - InetAddress localInner, - InetAddress remoteInner, - InetAddress localOuter, - InetAddress remoteOuter, - IpSecTransform inTransportTransform, - IpSecTransform outTransportTransform, - int encapPort, - int unusedInnerSocketPort, - int expectedPacketSize) { - return new IpSecTunnelTestRunnable() { - @Override - public int run(Network ipsecNetwork) throws Exception { - // Build a socket and send traffic - JavaUdpSocket socket = new JavaUdpSocket(localInner); - ipsecNetwork.bindSocket(socket.mSocket); - int innerSocketPort = socket.getPort(); - - // For Transport-In-Tunnel mode, apply transform to socket - if (transportInTunnelMode) { - mISM.applyTransportModeTransform( - socket.mSocket, IpSecManager.DIRECTION_IN, inTransportTransform); - mISM.applyTransportModeTransform( - socket.mSocket, IpSecManager.DIRECTION_OUT, outTransportTransform); - } - - socket.sendTo(TEST_DATA, remoteInner, socket.getPort()); - - // Verify that an encrypted packet is sent. As of right now, checking encrypted - // body is not possible, due to the test not knowing some of the fields of the - // inner IP header (flow label, flags, etc) - sTunUtils.awaitEspPacketNoPlaintext( - spi, TEST_DATA, encapPort != 0, expectedPacketSize); - - socket.close(); - - return innerSocketPort; - } - }; - } - } - - private class InputReflectedIpSecTunnelTestRunnableFactory - implements IpSecTunnelTestRunnableFactory { - public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable( - boolean transportInTunnelMode, - int spi, - InetAddress localInner, - InetAddress remoteInner, - InetAddress localOuter, - InetAddress remoteOuter, - IpSecTransform inTransportTransform, - IpSecTransform outTransportTransform, - int encapPort, - int innerSocketPort, - int expectedPacketSize) - throws Exception { - return new IpSecTunnelTestRunnable() { - @Override - public int run(Network ipsecNetwork) throws Exception { - // Build a socket and receive traffic - JavaUdpSocket socket = new JavaUdpSocket(localInner, innerSocketPort); - ipsecNetwork.bindSocket(socket.mSocket); - - // For Transport-In-Tunnel mode, apply transform to socket - if (transportInTunnelMode) { - mISM.applyTransportModeTransform( - socket.mSocket, IpSecManager.DIRECTION_IN, outTransportTransform); - mISM.applyTransportModeTransform( - socket.mSocket, IpSecManager.DIRECTION_OUT, inTransportTransform); - } - - sTunUtils.reflectPackets(); - - // Receive packet from socket, and validate that the payload is correct - receiveAndValidatePacket(socket); - - socket.close(); - - return 0; - } - }; - } - } - - private class InputPacketGeneratorIpSecTunnelTestRunnableFactory - implements IpSecTunnelTestRunnableFactory { - public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable( - boolean transportInTunnelMode, - int spi, - InetAddress localInner, - InetAddress remoteInner, - InetAddress localOuter, - InetAddress remoteOuter, - IpSecTransform inTransportTransform, - IpSecTransform outTransportTransform, - int encapPort, - int innerSocketPort, - int expectedPacketSize) - throws Exception { - return new IpSecTunnelTestRunnable() { - @Override - public int run(Network ipsecNetwork) throws Exception { - // Build a socket and receive traffic - JavaUdpSocket socket = new JavaUdpSocket(localInner); - ipsecNetwork.bindSocket(socket.mSocket); - - // For Transport-In-Tunnel mode, apply transform to socket - if (transportInTunnelMode) { - mISM.applyTransportModeTransform( - socket.mSocket, IpSecManager.DIRECTION_IN, outTransportTransform); - mISM.applyTransportModeTransform( - socket.mSocket, IpSecManager.DIRECTION_OUT, inTransportTransform); - } - - byte[] pkt; - if (transportInTunnelMode) { - pkt = - getTransportInTunnelModePacket( - spi, - spi, - remoteInner, - localInner, - remoteOuter, - localOuter, - socket.getPort(), - encapPort); - } else { - pkt = - getTunnelModePacket( - spi, - remoteInner, - localInner, - remoteOuter, - localOuter, - socket.getPort(), - encapPort); - } - sTunUtils.injectPacket(pkt); - - // Receive packet from socket, and validate - receiveAndValidatePacket(socket); - - socket.close(); - - return 0; - } - }; - } - } - - private void checkTunnelOutput( - int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode) - throws Exception { - checkTunnel( - innerFamily, - outerFamily, - useEncap, - transportInTunnelMode, - new OutputIpSecTunnelTestRunnableFactory()); - } - - private void checkTunnelInput( - int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode) - throws Exception { - checkTunnel( - innerFamily, - outerFamily, - useEncap, - transportInTunnelMode, - new InputPacketGeneratorIpSecTunnelTestRunnableFactory()); - } - - /** - * Validates that the kernel can talk to itself. - * - *

This test takes an outbound IPsec packet, reflects it (by flipping IP src/dst), and - * injects it back into the TUN. This test then verifies that a packet with the correct payload - * is found on the specified socket/port. - */ - public void checkTunnelReflected( - int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode) - throws Exception { - InetAddress localInner = innerFamily == AF_INET ? LOCAL_INNER_4 : LOCAL_INNER_6; - InetAddress remoteInner = innerFamily == AF_INET ? REMOTE_INNER_4 : REMOTE_INNER_6; - - InetAddress localOuter = outerFamily == AF_INET ? LOCAL_OUTER_4 : LOCAL_OUTER_6; - InetAddress remoteOuter = outerFamily == AF_INET ? REMOTE_OUTER_4 : REMOTE_OUTER_6; - - // Preselect both SPI and encap port, to be used for both inbound and outbound tunnels. - int spi = getRandomSpi(localOuter, remoteOuter); - int expectedPacketSize = - getPacketSize(innerFamily, outerFamily, useEncap, transportInTunnelMode); - - try (IpSecManager.SecurityParameterIndex inTransportSpi = - mISM.allocateSecurityParameterIndex(localInner, spi); - IpSecManager.SecurityParameterIndex outTransportSpi = - mISM.allocateSecurityParameterIndex(remoteInner, spi); - IpSecTransform inTransportTransform = - buildIpSecTransform(sContext, inTransportSpi, null, remoteInner); - IpSecTransform outTransportTransform = - buildIpSecTransform(sContext, outTransportSpi, null, localInner); - UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) { - - // Run output direction tests - IpSecTunnelTestRunnable outputIpSecTunnelTestRunnable = - new OutputIpSecTunnelTestRunnableFactory() - .getIpSecTunnelTestRunnable( - transportInTunnelMode, - spi, - localInner, - remoteInner, - localOuter, - remoteOuter, - inTransportTransform, - outTransportTransform, - useEncap ? encapSocket.getPort() : 0, - 0, - expectedPacketSize); - int innerSocketPort = - buildTunnelNetworkAndRunTests( - localInner, - remoteInner, - localOuter, - remoteOuter, - spi, - useEncap ? encapSocket : null, - outputIpSecTunnelTestRunnable); - - // Input direction tests, with matching inner socket ports. - IpSecTunnelTestRunnable inputIpSecTunnelTestRunnable = - new InputReflectedIpSecTunnelTestRunnableFactory() - .getIpSecTunnelTestRunnable( - transportInTunnelMode, - spi, - remoteInner, - localInner, - localOuter, - remoteOuter, - inTransportTransform, - outTransportTransform, - useEncap ? encapSocket.getPort() : 0, - innerSocketPort, - expectedPacketSize); - buildTunnelNetworkAndRunTests( - remoteInner, - localInner, - localOuter, - remoteOuter, - spi, - useEncap ? encapSocket : null, - inputIpSecTunnelTestRunnable); - } - } - - public void checkTunnel( - int innerFamily, - int outerFamily, - boolean useEncap, - boolean transportInTunnelMode, - IpSecTunnelTestRunnableFactory factory) - throws Exception { - - InetAddress localInner = innerFamily == AF_INET ? LOCAL_INNER_4 : LOCAL_INNER_6; - InetAddress remoteInner = innerFamily == AF_INET ? REMOTE_INNER_4 : REMOTE_INNER_6; - - InetAddress localOuter = outerFamily == AF_INET ? LOCAL_OUTER_4 : LOCAL_OUTER_6; - InetAddress remoteOuter = outerFamily == AF_INET ? REMOTE_OUTER_4 : REMOTE_OUTER_6; - - // Preselect both SPI and encap port, to be used for both inbound and outbound tunnels. - // Re-uses the same SPI to ensure that even in cases of symmetric SPIs shared across tunnel - // and transport mode, packets are encrypted/decrypted properly based on the src/dst. - int spi = getRandomSpi(localOuter, remoteOuter); - int expectedPacketSize = - getPacketSize(innerFamily, outerFamily, useEncap, transportInTunnelMode); - - try (IpSecManager.SecurityParameterIndex inTransportSpi = - mISM.allocateSecurityParameterIndex(localInner, spi); - IpSecManager.SecurityParameterIndex outTransportSpi = - mISM.allocateSecurityParameterIndex(remoteInner, spi); - IpSecTransform inTransportTransform = - buildIpSecTransform(sContext, inTransportSpi, null, remoteInner); - IpSecTransform outTransportTransform = - buildIpSecTransform(sContext, outTransportSpi, null, localInner); - UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) { - - buildTunnelNetworkAndRunTests( - localInner, - remoteInner, - localOuter, - remoteOuter, - spi, - useEncap ? encapSocket : null, - factory.getIpSecTunnelTestRunnable( - transportInTunnelMode, - spi, - localInner, - remoteInner, - localOuter, - remoteOuter, - inTransportTransform, - outTransportTransform, - useEncap ? encapSocket.getPort() : 0, - 0, - expectedPacketSize)); - } - } - - private int buildTunnelNetworkAndRunTests( - InetAddress localInner, - InetAddress remoteInner, - InetAddress localOuter, - InetAddress remoteOuter, - int spi, - UdpEncapsulationSocket encapSocket, - IpSecTunnelTestRunnable test) - throws Exception { - int innerPrefixLen = localInner instanceof Inet6Address ? IP6_PREFIX_LEN : IP4_PREFIX_LEN; - TestNetworkCallback testNetworkCb = null; - int innerSocketPort; - - try (IpSecManager.SecurityParameterIndex inSpi = - mISM.allocateSecurityParameterIndex(localOuter, spi); - IpSecManager.SecurityParameterIndex outSpi = - mISM.allocateSecurityParameterIndex(remoteOuter, spi); - IpSecManager.IpSecTunnelInterface tunnelIface = - mISM.createIpSecTunnelInterface(localOuter, remoteOuter, sTunNetwork)) { - // Build the test network - tunnelIface.addAddress(localInner, innerPrefixLen); - testNetworkCb = mCtsNetUtils.setupAndGetTestNetwork(tunnelIface.getInterfaceName()); - testNetworkCb.waitForAvailable(); - Network testNetwork = testNetworkCb.currentNetwork; - - // Check interface was created - assertNotNull(NetworkInterface.getByName(tunnelIface.getInterfaceName())); - - // Verify address was added - final NetworkInterface netIface = NetworkInterface.getByInetAddress(localInner); - assertNotNull(netIface); - assertEquals(tunnelIface.getInterfaceName(), netIface.getDisplayName()); - - // Configure Transform parameters - IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(sContext); - transformBuilder.setEncryption( - new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY)); - transformBuilder.setAuthentication( - new IpSecAlgorithm( - IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4)); - - if (encapSocket != null) { - transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort()); - } - - // Apply transform and check that traffic is properly encrypted - try (IpSecTransform inTransform = - transformBuilder.buildTunnelModeTransform(remoteOuter, inSpi); - IpSecTransform outTransform = - transformBuilder.buildTunnelModeTransform(localOuter, outSpi)) { - mISM.applyTunnelModeTransform(tunnelIface, IpSecManager.DIRECTION_IN, inTransform); - mISM.applyTunnelModeTransform( - tunnelIface, IpSecManager.DIRECTION_OUT, outTransform); - - innerSocketPort = test.run(testNetwork); - } - - // Teardown the test network - sTNM.teardownTestNetwork(testNetwork); - - // Remove addresses and check that interface is still present, but fails lookup-by-addr - tunnelIface.removeAddress(localInner, innerPrefixLen); - assertNotNull(NetworkInterface.getByName(tunnelIface.getInterfaceName())); - assertNull(NetworkInterface.getByInetAddress(localInner)); - - // Check interface was cleaned up - tunnelIface.close(); - assertNull(NetworkInterface.getByName(tunnelIface.getInterfaceName())); - } finally { - if (testNetworkCb != null) { - sCM.unregisterNetworkCallback(testNetworkCb); - } - } - - return innerSocketPort; - } - - private static void receiveAndValidatePacket(JavaUdpSocket socket) throws Exception { - byte[] socketResponseBytes = socket.receive(); - assertArrayEquals(TEST_DATA, socketResponseBytes); - } - - private int getRandomSpi(InetAddress localOuter, InetAddress remoteOuter) throws Exception { - // Try to allocate both in and out SPIs using the same requested SPI value. - try (IpSecManager.SecurityParameterIndex inSpi = - mISM.allocateSecurityParameterIndex(localOuter); - IpSecManager.SecurityParameterIndex outSpi = - mISM.allocateSecurityParameterIndex(remoteOuter, inSpi.getSpi()); ) { - return inSpi.getSpi(); - } - } - - private EspHeader buildTransportModeEspPacket( - int spi, InetAddress src, InetAddress dst, int port, Payload payload) throws Exception { - IpHeader preEspIpHeader = getIpHeader(payload.getProtocolId(), src, dst, payload); - - return new EspHeader( - payload.getProtocolId(), - spi, - 1, // sequence number - CRYPT_KEY, // Same key for auth and crypt - payload.getPacketBytes(preEspIpHeader)); - } - - private EspHeader buildTunnelModeEspPacket( - int spi, - InetAddress srcInner, - InetAddress dstInner, - InetAddress srcOuter, - InetAddress dstOuter, - int port, - int encapPort, - Payload payload) - throws Exception { - IpHeader innerIp = getIpHeader(payload.getProtocolId(), srcInner, dstInner, payload); - return new EspHeader( - innerIp.getProtocolId(), - spi, - 1, // sequence number - CRYPT_KEY, // Same key for auth and crypt - innerIp.getPacketBytes()); - } - - private IpHeader maybeEncapPacket( - InetAddress src, InetAddress dst, int encapPort, EspHeader espPayload) - throws Exception { - - Payload payload = espPayload; - if (encapPort != 0) { - payload = new UdpHeader(encapPort, encapPort, espPayload); - } - - return getIpHeader(payload.getProtocolId(), src, dst, payload); - } - - private byte[] getTunnelModePacket( - int spi, - InetAddress srcInner, - InetAddress dstInner, - InetAddress srcOuter, - InetAddress dstOuter, - int port, - int encapPort) - throws Exception { - UdpHeader udp = new UdpHeader(port, port, new BytePayload(TEST_DATA)); - - EspHeader espPayload = - buildTunnelModeEspPacket( - spi, srcInner, dstInner, srcOuter, dstOuter, port, encapPort, udp); - return maybeEncapPacket(srcOuter, dstOuter, encapPort, espPayload).getPacketBytes(); - } - - private byte[] getTransportInTunnelModePacket( - int spiInner, - int spiOuter, - InetAddress srcInner, - InetAddress dstInner, - InetAddress srcOuter, - InetAddress dstOuter, - int port, - int encapPort) - throws Exception { - UdpHeader udp = new UdpHeader(port, port, new BytePayload(TEST_DATA)); - - EspHeader espPayload = buildTransportModeEspPacket(spiInner, srcInner, dstInner, port, udp); - espPayload = - buildTunnelModeEspPacket( - spiOuter, - srcInner, - dstInner, - srcOuter, - dstOuter, - port, - encapPort, - espPayload); - return maybeEncapPacket(srcOuter, dstOuter, encapPort, espPayload).getPacketBytes(); - } - - // Transport-in-Tunnel mode tests - @Test - public void testTransportInTunnelModeV4InV4() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET, AF_INET, false, true); - checkTunnelInput(AF_INET, AF_INET, false, true); - } - - @Test - public void testTransportInTunnelModeV4InV4Reflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET, AF_INET, false, true); - } - - @Test - public void testTransportInTunnelModeV4InV4UdpEncap() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET, AF_INET, true, true); - checkTunnelInput(AF_INET, AF_INET, true, true); - } - - @Test - public void testTransportInTunnelModeV4InV4UdpEncapReflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET, AF_INET, false, true); - } - - @Test - public void testTransportInTunnelModeV4InV6() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET, AF_INET6, false, true); - checkTunnelInput(AF_INET, AF_INET6, false, true); - } - - @Test - public void testTransportInTunnelModeV4InV6Reflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET, AF_INET, false, true); - } - - @Test - public void testTransportInTunnelModeV6InV4() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET6, AF_INET, false, true); - checkTunnelInput(AF_INET6, AF_INET, false, true); - } - - @Test - public void testTransportInTunnelModeV6InV4Reflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET, AF_INET, false, true); - } - - @Test - public void testTransportInTunnelModeV6InV4UdpEncap() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET6, AF_INET, true, true); - checkTunnelInput(AF_INET6, AF_INET, true, true); - } - - @Test - public void testTransportInTunnelModeV6InV4UdpEncapReflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET, AF_INET, false, true); - } - - @Test - public void testTransportInTunnelModeV6InV6() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET, AF_INET6, false, true); - checkTunnelInput(AF_INET, AF_INET6, false, true); - } - - @Test - public void testTransportInTunnelModeV6InV6Reflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET, AF_INET, false, true); - } - - // Tunnel mode tests - @Test - public void testTunnelV4InV4() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET, AF_INET, false, false); - checkTunnelInput(AF_INET, AF_INET, false, false); - } - - @Test - public void testTunnelV4InV4Reflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET, AF_INET, false, false); - } - - @Test - public void testTunnelV4InV4UdpEncap() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET, AF_INET, true, false); - checkTunnelInput(AF_INET, AF_INET, true, false); - } - - @Test - public void testTunnelV4InV4UdpEncapReflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET, AF_INET, true, false); - } - - @Test - public void testTunnelV4InV6() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET, AF_INET6, false, false); - checkTunnelInput(AF_INET, AF_INET6, false, false); - } - - @Test - public void testTunnelV4InV6Reflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET, AF_INET6, false, false); - } - - @Test - public void testTunnelV6InV4() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET6, AF_INET, false, false); - checkTunnelInput(AF_INET6, AF_INET, false, false); - } - - @Test - public void testTunnelV6InV4Reflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET6, AF_INET, false, false); - } - - @Test - public void testTunnelV6InV4UdpEncap() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET6, AF_INET, true, false); - checkTunnelInput(AF_INET6, AF_INET, true, false); - } - - @Test - public void testTunnelV6InV4UdpEncapReflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET6, AF_INET, true, false); - } - - @Test - public void testTunnelV6InV6() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelOutput(AF_INET6, AF_INET6, false, false); - checkTunnelInput(AF_INET6, AF_INET6, false, false); - } - - @Test - public void testTunnelV6InV6Reflected() throws Exception { - assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); - checkTunnelReflected(AF_INET6, AF_INET6, false, false); - } -} diff --git a/tests/cts/net/src/android/net/cts/LocalServerSocketTest.java b/tests/cts/net/src/android/net/cts/LocalServerSocketTest.java deleted file mode 100644 index 7c5a1b353d..0000000000 --- a/tests/cts/net/src/android/net/cts/LocalServerSocketTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2009 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.cts; - -import junit.framework.TestCase; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import android.net.LocalServerSocket; -import android.net.LocalSocket; -import android.net.LocalSocketAddress; - -public class LocalServerSocketTest extends TestCase { - - public void testLocalServerSocket() throws IOException { - String address = "com.android.net.LocalServerSocketTest_testLocalServerSocket"; - LocalServerSocket localServerSocket = new LocalServerSocket(address); - assertNotNull(localServerSocket.getLocalSocketAddress()); - - // create client socket - LocalSocket clientSocket = new LocalSocket(); - - // establish connection between client and server - clientSocket.connect(new LocalSocketAddress(address)); - LocalSocket serverSocket = localServerSocket.accept(); - - assertTrue(serverSocket.isConnected()); - assertTrue(serverSocket.isBound()); - - // send data from client to server - OutputStream clientOutStream = clientSocket.getOutputStream(); - clientOutStream.write(12); - InputStream serverInStream = serverSocket.getInputStream(); - assertEquals(12, serverInStream.read()); - - // send data from server to client - OutputStream serverOutStream = serverSocket.getOutputStream(); - serverOutStream.write(3); - InputStream clientInStream = clientSocket.getInputStream(); - assertEquals(3, clientInStream.read()); - - // close server socket - assertNotNull(localServerSocket.getFileDescriptor()); - localServerSocket.close(); - assertNull(localServerSocket.getFileDescriptor()); - } -} diff --git a/tests/cts/net/src/android/net/cts/LocalSocketAddressTest.java b/tests/cts/net/src/android/net/cts/LocalSocketAddressTest.java deleted file mode 100644 index 6ef003b26f..0000000000 --- a/tests/cts/net/src/android/net/cts/LocalSocketAddressTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008 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.cts; - -import android.net.LocalSocketAddress; -import android.net.LocalSocketAddress.Namespace; -import android.test.AndroidTestCase; - -public class LocalSocketAddressTest extends AndroidTestCase { - - public void testNewLocalSocketAddressWithDefaultNamespace() { - // default namespace - LocalSocketAddress localSocketAddress = new LocalSocketAddress("name"); - assertEquals("name", localSocketAddress.getName()); - assertEquals(Namespace.ABSTRACT, localSocketAddress.getNamespace()); - - // specify the namespace - LocalSocketAddress localSocketAddress2 = - new LocalSocketAddress("name2", Namespace.ABSTRACT); - assertEquals("name2", localSocketAddress2.getName()); - assertEquals(Namespace.ABSTRACT, localSocketAddress2.getNamespace()); - - LocalSocketAddress localSocketAddress3 = - new LocalSocketAddress("name3", Namespace.FILESYSTEM); - assertEquals("name3", localSocketAddress3.getName()); - assertEquals(Namespace.FILESYSTEM, localSocketAddress3.getNamespace()); - - LocalSocketAddress localSocketAddress4 = - new LocalSocketAddress("name4", Namespace.RESERVED); - assertEquals("name4", localSocketAddress4.getName()); - assertEquals(Namespace.RESERVED, localSocketAddress4.getNamespace()); - } -} diff --git a/tests/cts/net/src/android/net/cts/LocalSocketAddress_NamespaceTest.java b/tests/cts/net/src/android/net/cts/LocalSocketAddress_NamespaceTest.java deleted file mode 100644 index 97dfa435fa..0000000000 --- a/tests/cts/net/src/android/net/cts/LocalSocketAddress_NamespaceTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2009 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.cts; - -import android.net.LocalSocketAddress.Namespace; -import android.test.AndroidTestCase; - -public class LocalSocketAddress_NamespaceTest extends AndroidTestCase { - - public void testValueOf() { - assertEquals(Namespace.ABSTRACT, Namespace.valueOf("ABSTRACT")); - assertEquals(Namespace.RESERVED, Namespace.valueOf("RESERVED")); - assertEquals(Namespace.FILESYSTEM, Namespace.valueOf("FILESYSTEM")); - } - - public void testValues() { - Namespace[] expected = Namespace.values(); - assertEquals(Namespace.ABSTRACT, expected[0]); - assertEquals(Namespace.RESERVED, expected[1]); - assertEquals(Namespace.FILESYSTEM, expected[2]); - } -} diff --git a/tests/cts/net/src/android/net/cts/LocalSocketTest.java b/tests/cts/net/src/android/net/cts/LocalSocketTest.java deleted file mode 100644 index 6e61705b92..0000000000 --- a/tests/cts/net/src/android/net/cts/LocalSocketTest.java +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (C) 2008 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.cts; - -import junit.framework.TestCase; - -import android.net.Credentials; -import android.net.LocalServerSocket; -import android.net.LocalSocket; -import android.net.LocalSocketAddress; -import android.system.Os; -import android.system.OsConstants; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -public class LocalSocketTest extends TestCase { - private final static String ADDRESS_PREFIX = "com.android.net.LocalSocketTest"; - - public void testLocalConnections() throws IOException { - String address = ADDRESS_PREFIX + "_testLocalConnections"; - // create client and server socket - LocalServerSocket localServerSocket = new LocalServerSocket(address); - LocalSocket clientSocket = new LocalSocket(); - - // establish connection between client and server - LocalSocketAddress locSockAddr = new LocalSocketAddress(address); - assertFalse(clientSocket.isConnected()); - clientSocket.connect(locSockAddr); - assertTrue(clientSocket.isConnected()); - - LocalSocket serverSocket = localServerSocket.accept(); - assertTrue(serverSocket.isConnected()); - assertTrue(serverSocket.isBound()); - try { - serverSocket.bind(localServerSocket.getLocalSocketAddress()); - fail("Cannot bind a LocalSocket from accept()"); - } catch (IOException expected) { - } - try { - serverSocket.connect(locSockAddr); - fail("Cannot connect a LocalSocket from accept()"); - } catch (IOException expected) { - } - - Credentials credent = clientSocket.getPeerCredentials(); - assertTrue(0 != credent.getPid()); - - // send data from client to server - OutputStream clientOutStream = clientSocket.getOutputStream(); - clientOutStream.write(12); - InputStream serverInStream = serverSocket.getInputStream(); - assertEquals(12, serverInStream.read()); - - //send data from server to client - OutputStream serverOutStream = serverSocket.getOutputStream(); - serverOutStream.write(3); - InputStream clientInStream = clientSocket.getInputStream(); - assertEquals(3, clientInStream.read()); - - // Test sending and receiving file descriptors - clientSocket.setFileDescriptorsForSend(new FileDescriptor[]{FileDescriptor.in}); - clientOutStream.write(32); - assertEquals(32, serverInStream.read()); - - FileDescriptor[] out = serverSocket.getAncillaryFileDescriptors(); - assertEquals(1, out.length); - FileDescriptor fd = clientSocket.getFileDescriptor(); - assertTrue(fd.valid()); - - //shutdown input stream of client - clientSocket.shutdownInput(); - assertEquals(-1, clientInStream.read()); - - //shutdown output stream of client - clientSocket.shutdownOutput(); - try { - clientOutStream.write(10); - fail("testLocalSocket shouldn't come to here"); - } catch (IOException e) { - // expected - } - - //shutdown input stream of server - serverSocket.shutdownInput(); - assertEquals(-1, serverInStream.read()); - - //shutdown output stream of server - serverSocket.shutdownOutput(); - try { - serverOutStream.write(10); - fail("testLocalSocket shouldn't come to here"); - } catch (IOException e) { - // expected - } - - //close client socket - clientSocket.close(); - try { - clientInStream.read(); - fail("testLocalSocket shouldn't come to here"); - } catch (IOException e) { - // expected - } - - //close server socket - serverSocket.close(); - try { - serverInStream.read(); - fail("testLocalSocket shouldn't come to here"); - } catch (IOException e) { - // expected - } - } - - public void testAccessors() throws IOException { - String address = ADDRESS_PREFIX + "_testAccessors"; - LocalSocket socket = new LocalSocket(); - LocalSocketAddress addr = new LocalSocketAddress(address); - - assertFalse(socket.isBound()); - socket.bind(addr); - assertTrue(socket.isBound()); - assertEquals(addr, socket.getLocalSocketAddress()); - - String str = socket.toString(); - assertTrue(str.contains("impl:android.net.LocalSocketImpl")); - - socket.setReceiveBufferSize(1999); - assertEquals(1999 << 1, socket.getReceiveBufferSize()); - - socket.setSendBufferSize(3998); - assertEquals(3998 << 1, socket.getSendBufferSize()); - - assertEquals(0, socket.getSoTimeout()); - socket.setSoTimeout(1996); - assertTrue(socket.getSoTimeout() > 0); - - try { - socket.getRemoteSocketAddress(); - fail("testLocalSocketSecondary shouldn't come to here"); - } catch (UnsupportedOperationException e) { - // expected - } - - try { - socket.isClosed(); - fail("testLocalSocketSecondary shouldn't come to here"); - } catch (UnsupportedOperationException e) { - // expected - } - - try { - socket.isInputShutdown(); - fail("testLocalSocketSecondary shouldn't come to here"); - } catch (UnsupportedOperationException e) { - // expected - } - - try { - socket.isOutputShutdown(); - fail("testLocalSocketSecondary shouldn't come to here"); - } catch (UnsupportedOperationException e) { - // expected - } - - try { - socket.connect(addr, 2005); - fail("testLocalSocketSecondary shouldn't come to here"); - } catch (UnsupportedOperationException e) { - // expected - } - - socket.close(); - } - - // http://b/31205169 - public void testSetSoTimeout_readTimeout() throws Exception { - String address = ADDRESS_PREFIX + "_testSetSoTimeout_readTimeout"; - - try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) { - final LocalSocket clientSocket = socketPair.clientSocket; - - // Set the timeout in millis. - int timeoutMillis = 1000; - clientSocket.setSoTimeout(timeoutMillis); - - // Avoid blocking the test run if timeout doesn't happen by using a separate thread. - Callable reader = () -> { - try { - clientSocket.getInputStream().read(); - return Result.noException("Did not block"); - } catch (IOException e) { - return Result.exception(e); - } - }; - // Allow the configured timeout, plus some slop. - int allowedTime = timeoutMillis + 2000; - Result result = runInSeparateThread(allowedTime, reader); - - // Check the message was a timeout, it's all we have to go on. - String expectedMessage = Os.strerror(OsConstants.EAGAIN); - result.assertThrewIOException(expectedMessage); - } - } - - // http://b/31205169 - public void testSetSoTimeout_writeTimeout() throws Exception { - String address = ADDRESS_PREFIX + "_testSetSoTimeout_writeTimeout"; - - try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) { - final LocalSocket clientSocket = socketPair.clientSocket; - - // Set the timeout in millis. - int timeoutMillis = 1000; - clientSocket.setSoTimeout(timeoutMillis); - - // Set a small buffer size so we know we can flood it. - clientSocket.setSendBufferSize(100); - final int bufferSize = clientSocket.getSendBufferSize(); - - // Avoid blocking the test run if timeout doesn't happen by using a separate thread. - Callable writer = () -> { - try { - byte[] toWrite = new byte[bufferSize * 2]; - clientSocket.getOutputStream().write(toWrite); - return Result.noException("Did not block"); - } catch (IOException e) { - return Result.exception(e); - } - }; - // Allow the configured timeout, plus some slop. - int allowedTime = timeoutMillis + 2000; - - Result result = runInSeparateThread(allowedTime, writer); - - // Check the message was a timeout, it's all we have to go on. - String expectedMessage = Os.strerror(OsConstants.EAGAIN); - result.assertThrewIOException(expectedMessage); - } - } - - public void testAvailable() throws Exception { - String address = ADDRESS_PREFIX + "_testAvailable"; - - try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) { - LocalSocket clientSocket = socketPair.clientSocket; - LocalSocket serverSocket = socketPair.serverSocket.accept(); - - OutputStream clientOutputStream = clientSocket.getOutputStream(); - InputStream serverInputStream = serverSocket.getInputStream(); - assertEquals(0, serverInputStream.available()); - - byte[] buffer = new byte[50]; - clientOutputStream.write(buffer); - assertEquals(50, serverInputStream.available()); - - InputStream clientInputStream = clientSocket.getInputStream(); - OutputStream serverOutputStream = serverSocket.getOutputStream(); - assertEquals(0, clientInputStream.available()); - serverOutputStream.write(buffer); - assertEquals(50, serverInputStream.available()); - - serverSocket.close(); - } - } - - // http://b/34095140 - public void testLocalSocketCreatedFromFileDescriptor() throws Exception { - String address = ADDRESS_PREFIX + "_testLocalSocketCreatedFromFileDescriptor"; - - // Establish connection between a local client and server to get a valid client socket file - // descriptor. - try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) { - // Extract the client FileDescriptor we can use. - FileDescriptor fileDescriptor = socketPair.clientSocket.getFileDescriptor(); - assertTrue(fileDescriptor.valid()); - - // Create the LocalSocket we want to test. - LocalSocket clientSocketCreatedFromFileDescriptor = - LocalSocket.createConnectedLocalSocket(fileDescriptor); - assertTrue(clientSocketCreatedFromFileDescriptor.isConnected()); - assertTrue(clientSocketCreatedFromFileDescriptor.isBound()); - - // Test the LocalSocket can be used for communication. - LocalSocket serverSocket = socketPair.serverSocket.accept(); - OutputStream clientOutputStream = - clientSocketCreatedFromFileDescriptor.getOutputStream(); - InputStream serverInputStream = serverSocket.getInputStream(); - - clientOutputStream.write(12); - assertEquals(12, serverInputStream.read()); - - // Closing clientSocketCreatedFromFileDescriptor does not close the file descriptor. - clientSocketCreatedFromFileDescriptor.close(); - assertTrue(fileDescriptor.valid()); - - // .. while closing the LocalSocket that owned the file descriptor does. - socketPair.clientSocket.close(); - assertFalse(fileDescriptor.valid()); - } - } - - public void testFlush() throws Exception { - String address = ADDRESS_PREFIX + "_testFlush"; - - try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) { - LocalSocket clientSocket = socketPair.clientSocket; - LocalSocket serverSocket = socketPair.serverSocket.accept(); - - OutputStream clientOutputStream = clientSocket.getOutputStream(); - InputStream serverInputStream = serverSocket.getInputStream(); - testFlushWorks(clientOutputStream, serverInputStream); - - OutputStream serverOutputStream = serverSocket.getOutputStream(); - InputStream clientInputStream = clientSocket.getInputStream(); - testFlushWorks(serverOutputStream, clientInputStream); - - serverSocket.close(); - } - } - - private void testFlushWorks(OutputStream outputStream, InputStream inputStream) - throws Exception { - final int bytesToTransfer = 50; - StreamReader inputStreamReader = new StreamReader(inputStream, bytesToTransfer); - - byte[] buffer = new byte[bytesToTransfer]; - outputStream.write(buffer); - assertEquals(bytesToTransfer, inputStream.available()); - - // Start consuming the data. - inputStreamReader.start(); - - // This doesn't actually flush any buffers, it just polls until the reader has read all the - // bytes. - outputStream.flush(); - - inputStreamReader.waitForCompletion(5000); - inputStreamReader.assertBytesRead(bytesToTransfer); - assertEquals(0, inputStream.available()); - } - - private static class StreamReader extends Thread { - private final InputStream is; - private final int expectedByteCount; - private final CountDownLatch completeLatch = new CountDownLatch(1); - - private volatile Exception exception; - private int bytesRead; - - private StreamReader(InputStream is, int expectedByteCount) { - this.is = is; - this.expectedByteCount = expectedByteCount; - } - - @Override - public void run() { - try { - byte[] buffer = new byte[10]; - int readCount; - while ((readCount = is.read(buffer)) >= 0) { - bytesRead += readCount; - if (bytesRead >= expectedByteCount) { - break; - } - } - } catch (IOException e) { - exception = e; - } finally { - completeLatch.countDown(); - } - } - - public void waitForCompletion(long waitMillis) throws Exception { - if (!completeLatch.await(waitMillis, TimeUnit.MILLISECONDS)) { - fail("Timeout waiting for completion"); - } - if (exception != null) { - throw new Exception("Read failed", exception); - } - } - - public void assertBytesRead(int expected) { - assertEquals(expected, bytesRead); - } - } - - private static class Result { - private final String type; - private final Exception e; - - private Result(String type, Exception e) { - this.type = type; - this.e = e; - } - - static Result noException(String description) { - return new Result(description, null); - } - - static Result exception(Exception e) { - return new Result(e.getClass().getName(), e); - } - - void assertThrewIOException(String expectedMessage) { - assertEquals("Unexpected result type", IOException.class.getName(), type); - assertEquals("Unexpected exception message", expectedMessage, e.getMessage()); - } - } - - private static Result runInSeparateThread(int allowedTime, final Callable callable) - throws Exception { - ExecutorService service = Executors.newSingleThreadScheduledExecutor(); - Future future = service.submit(callable); - Result result = future.get(allowedTime, TimeUnit.MILLISECONDS); - if (!future.isDone()) { - fail("Worker thread appears blocked"); - } - return result; - } - - private static class LocalSocketPair implements AutoCloseable { - static LocalSocketPair createConnectedSocketPair(String address) throws Exception { - LocalServerSocket localServerSocket = new LocalServerSocket(address); - final LocalSocket clientSocket = new LocalSocket(); - - // Establish connection between client and server - LocalSocketAddress locSockAddr = new LocalSocketAddress(address); - clientSocket.connect(locSockAddr); - assertTrue(clientSocket.isConnected()); - return new LocalSocketPair(localServerSocket, clientSocket); - } - - final LocalServerSocket serverSocket; - final LocalSocket clientSocket; - - LocalSocketPair(LocalServerSocket serverSocket, LocalSocket clientSocket) { - this.serverSocket = serverSocket; - this.clientSocket = clientSocket; - } - - public void close() throws Exception { - serverSocket.close(); - clientSocket.close(); - } - } -} diff --git a/tests/cts/net/src/android/net/cts/MacAddressTest.java b/tests/cts/net/src/android/net/cts/MacAddressTest.java deleted file mode 100644 index 3fd3bbac8c..0000000000 --- a/tests/cts/net/src/android/net/cts/MacAddressTest.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2018 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.cts; - -import static android.net.MacAddress.TYPE_BROADCAST; -import static android.net.MacAddress.TYPE_MULTICAST; -import static android.net.MacAddress.TYPE_UNICAST; - -import static com.android.testutils.ParcelUtils.assertParcelSane; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.net.MacAddress; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Inet6Address; -import java.util.Arrays; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class MacAddressTest { - - static class TestCase { - final String macAddress; - final String ouiString; - final int addressType; - final boolean isLocallyAssigned; - - TestCase(String macAddress, String ouiString, int addressType, boolean isLocallyAssigned) { - this.macAddress = macAddress; - this.ouiString = ouiString; - this.addressType = addressType; - this.isLocallyAssigned = isLocallyAssigned; - } - } - - static final boolean LOCALLY_ASSIGNED = true; - static final boolean GLOBALLY_UNIQUE = false; - - static String typeToString(int addressType) { - switch (addressType) { - case TYPE_UNICAST: - return "TYPE_UNICAST"; - case TYPE_BROADCAST: - return "TYPE_BROADCAST"; - case TYPE_MULTICAST: - return "TYPE_MULTICAST"; - default: - return "UNKNOWN"; - } - } - - static String localAssignedToString(boolean isLocallyAssigned) { - return isLocallyAssigned ? "LOCALLY_ASSIGNED" : "GLOBALLY_UNIQUE"; - } - - @Test - public void testMacAddress() { - TestCase[] tests = { - new TestCase("ff:ff:ff:ff:ff:ff", "ff:ff:ff", TYPE_BROADCAST, LOCALLY_ASSIGNED), - new TestCase("d2:c4:22:4d:32:a8", "d2:c4:22", TYPE_UNICAST, LOCALLY_ASSIGNED), - new TestCase("33:33:aa:bb:cc:dd", "33:33:aa", TYPE_MULTICAST, LOCALLY_ASSIGNED), - new TestCase("06:00:00:00:00:00", "06:00:00", TYPE_UNICAST, LOCALLY_ASSIGNED), - new TestCase("07:00:d3:56:8a:c4", "07:00:d3", TYPE_MULTICAST, LOCALLY_ASSIGNED), - new TestCase("00:01:44:55:66:77", "00:01:44", TYPE_UNICAST, GLOBALLY_UNIQUE), - new TestCase("08:00:22:33:44:55", "08:00:22", TYPE_UNICAST, GLOBALLY_UNIQUE), - }; - - for (TestCase tc : tests) { - MacAddress mac = MacAddress.fromString(tc.macAddress); - - if (!tc.ouiString.equals(mac.toOuiString())) { - fail(String.format("expected OUI string %s, got %s", - tc.ouiString, mac.toOuiString())); - } - - if (tc.isLocallyAssigned != mac.isLocallyAssigned()) { - fail(String.format("expected %s to be %s, got %s", mac, - localAssignedToString(tc.isLocallyAssigned), - localAssignedToString(mac.isLocallyAssigned()))); - } - - if (tc.addressType != mac.getAddressType()) { - fail(String.format("expected %s address type to be %s, got %s", mac, - typeToString(tc.addressType), typeToString(mac.getAddressType()))); - } - - if (!tc.macAddress.equals(mac.toString())) { - fail(String.format("expected toString() to return %s, got %s", - tc.macAddress, mac.toString())); - } - - if (!mac.equals(MacAddress.fromBytes(mac.toByteArray()))) { - byte[] bytes = mac.toByteArray(); - fail(String.format("expected mac address from bytes %s to be %s, got %s", - Arrays.toString(bytes), - MacAddress.fromBytes(bytes), - mac)); - } - } - } - - @Test - public void testConstructorInputValidation() { - String[] invalidStringAddresses = { - "", - "abcd", - "1:2:3:4:5", - "1:2:3:4:5:6:7", - "10000:2:3:4:5:6", - }; - - for (String s : invalidStringAddresses) { - try { - MacAddress mac = MacAddress.fromString(s); - fail("MacAddress.fromString(" + s + ") should have failed, but returned " + mac); - } catch (IllegalArgumentException excepted) { - } - } - - try { - MacAddress mac = MacAddress.fromString(null); - fail("MacAddress.fromString(null) should have failed, but returned " + mac); - } catch (NullPointerException excepted) { - } - - byte[][] invalidBytesAddresses = { - {}, - {1,2,3,4,5}, - {1,2,3,4,5,6,7}, - }; - - for (byte[] b : invalidBytesAddresses) { - try { - MacAddress mac = MacAddress.fromBytes(b); - fail("MacAddress.fromBytes(" + Arrays.toString(b) - + ") should have failed, but returned " + mac); - } catch (IllegalArgumentException excepted) { - } - } - - try { - MacAddress mac = MacAddress.fromBytes(null); - fail("MacAddress.fromBytes(null) should have failed, but returned " + mac); - } catch (NullPointerException excepted) { - } - } - - @Test - public void testMatches() { - // match 4 bytes prefix - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:dd:00:00"), - MacAddress.fromString("ff:ff:ff:ff:00:00"))); - - // match bytes 0,1,2 and 5 - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:00:00:11"), - MacAddress.fromString("ff:ff:ff:00:00:ff"))); - - // match 34 bit prefix - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:dd:c0:00"), - MacAddress.fromString("ff:ff:ff:ff:c0:00"))); - - // fail to match 36 bit prefix - assertFalse(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:dd:40:00"), - MacAddress.fromString("ff:ff:ff:ff:f0:00"))); - - // match all 6 bytes - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("aa:bb:cc:dd:ee:11"), - MacAddress.fromString("ff:ff:ff:ff:ff:ff"))); - - // match none of 6 bytes - assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches( - MacAddress.fromString("00:00:00:00:00:00"), - MacAddress.fromString("00:00:00:00:00:00"))); - } - - /** - * Tests that link-local address generation from MAC is valid. - */ - @Test - public void testLinkLocalFromMacGeneration() { - final MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f"); - final byte[] inet6ll = {(byte) 0xfe, (byte) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, - 0x74, (byte) 0xf2, (byte) 0xff, (byte) 0xfe, (byte) 0xb1, (byte) 0xa8, 0x7f}; - final Inet6Address llv6 = mac.getLinkLocalIpv6FromEui48Mac(); - assertTrue(llv6.isLinkLocalAddress()); - assertArrayEquals(inet6ll, llv6.getAddress()); - } - - @Test - public void testParcelMacAddress() { - final MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f"); - - assertParcelSane(mac, 1); - } -} diff --git a/tests/cts/net/src/android/net/cts/MailToTest.java b/tests/cts/net/src/android/net/cts/MailToTest.java deleted file mode 100644 index e454d20628..0000000000 --- a/tests/cts/net/src/android/net/cts/MailToTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2008 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.cts; - -import android.net.MailTo; -import android.test.AndroidTestCase; -import android.util.Log; - -public class MailToTest extends AndroidTestCase { - private static final String MAILTOURI_1 = "mailto:chris@example.com"; - private static final String MAILTOURI_2 = "mailto:infobot@example.com?subject=current-issue"; - private static final String MAILTOURI_3 = - "mailto:infobot@example.com?body=send%20current-issue"; - private static final String MAILTOURI_4 = "mailto:infobot@example.com?body=send%20current-" + - "issue%0D%0Asend%20index"; - private static final String MAILTOURI_5 = "mailto:joe@example.com?" + - "cc=bob@example.com&body=hello"; - private static final String MAILTOURI_6 = "mailto:?to=joe@example.com&" + - "cc=bob@example.com&body=hello"; - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - public void testParseMailToURI() { - assertFalse(MailTo.isMailTo(null)); - assertFalse(MailTo.isMailTo("")); - assertFalse(MailTo.isMailTo("http://www.google.com")); - - assertTrue(MailTo.isMailTo(MAILTOURI_1)); - MailTo mailTo_1 = MailTo.parse(MAILTOURI_1); - Log.d("Trace", mailTo_1.toString()); - assertEquals("chris@example.com", mailTo_1.getTo()); - assertEquals(1, mailTo_1.getHeaders().size()); - assertNull(mailTo_1.getBody()); - assertNull(mailTo_1.getCc()); - assertNull(mailTo_1.getSubject()); - assertEquals("mailto:?to=chris%40example.com&", mailTo_1.toString()); - - assertTrue(MailTo.isMailTo(MAILTOURI_2)); - MailTo mailTo_2 = MailTo.parse(MAILTOURI_2); - Log.d("Trace", mailTo_2.toString()); - assertEquals(2, mailTo_2.getHeaders().size()); - assertEquals("infobot@example.com", mailTo_2.getTo()); - assertEquals("current-issue", mailTo_2.getSubject()); - assertNull(mailTo_2.getBody()); - assertNull(mailTo_2.getCc()); - String stringUrl = mailTo_2.toString(); - assertTrue(stringUrl.startsWith("mailto:?")); - assertTrue(stringUrl.contains("to=infobot%40example.com&")); - assertTrue(stringUrl.contains("subject=current-issue&")); - - assertTrue(MailTo.isMailTo(MAILTOURI_3)); - MailTo mailTo_3 = MailTo.parse(MAILTOURI_3); - Log.d("Trace", mailTo_3.toString()); - assertEquals(2, mailTo_3.getHeaders().size()); - assertEquals("infobot@example.com", mailTo_3.getTo()); - assertEquals("send current-issue", mailTo_3.getBody()); - assertNull(mailTo_3.getCc()); - assertNull(mailTo_3.getSubject()); - stringUrl = mailTo_3.toString(); - assertTrue(stringUrl.startsWith("mailto:?")); - assertTrue(stringUrl.contains("to=infobot%40example.com&")); - assertTrue(stringUrl.contains("body=send%20current-issue&")); - - assertTrue(MailTo.isMailTo(MAILTOURI_4)); - MailTo mailTo_4 = MailTo.parse(MAILTOURI_4); - Log.d("Trace", mailTo_4.toString() + " " + mailTo_4.getBody()); - assertEquals(2, mailTo_4.getHeaders().size()); - assertEquals("infobot@example.com", mailTo_4.getTo()); - assertEquals("send current-issue\r\nsend index", mailTo_4.getBody()); - assertNull(mailTo_4.getCc()); - assertNull(mailTo_4.getSubject()); - stringUrl = mailTo_4.toString(); - assertTrue(stringUrl.startsWith("mailto:?")); - assertTrue(stringUrl.contains("to=infobot%40example.com&")); - assertTrue(stringUrl.contains("body=send%20current-issue%0D%0Asend%20index&")); - - - assertTrue(MailTo.isMailTo(MAILTOURI_5)); - MailTo mailTo_5 = MailTo.parse(MAILTOURI_5); - Log.d("Trace", mailTo_5.toString() + mailTo_5.getHeaders().toString() - + mailTo_5.getHeaders().size()); - assertEquals(3, mailTo_5.getHeaders().size()); - assertEquals("joe@example.com", mailTo_5.getTo()); - assertEquals("bob@example.com", mailTo_5.getCc()); - assertEquals("hello", mailTo_5.getBody()); - assertNull(mailTo_5.getSubject()); - stringUrl = mailTo_5.toString(); - assertTrue(stringUrl.startsWith("mailto:?")); - assertTrue(stringUrl.contains("cc=bob%40example.com&")); - assertTrue(stringUrl.contains("body=hello&")); - assertTrue(stringUrl.contains("to=joe%40example.com&")); - - assertTrue(MailTo.isMailTo(MAILTOURI_6)); - MailTo mailTo_6 = MailTo.parse(MAILTOURI_6); - Log.d("Trace", mailTo_6.toString() + mailTo_6.getHeaders().toString() - + mailTo_6.getHeaders().size()); - assertEquals(3, mailTo_6.getHeaders().size()); - assertEquals(", joe@example.com", mailTo_6.getTo()); - assertEquals("bob@example.com", mailTo_6.getCc()); - assertEquals("hello", mailTo_6.getBody()); - assertNull(mailTo_6.getSubject()); - stringUrl = mailTo_6.toString(); - assertTrue(stringUrl.startsWith("mailto:?")); - assertTrue(stringUrl.contains("cc=bob%40example.com&")); - assertTrue(stringUrl.contains("body=hello&")); - assertTrue(stringUrl.contains("to=%2C%20joe%40example.com&")); - } -} diff --git a/tests/cts/net/src/android/net/cts/MultinetworkApiTest.java b/tests/cts/net/src/android/net/cts/MultinetworkApiTest.java deleted file mode 100644 index 6d3db8912d..0000000000 --- a/tests/cts/net/src/android/net/cts/MultinetworkApiTest.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2015 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.cts; - -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; - -import android.content.Context; -import android.content.ContentResolver; -import android.net.ConnectivityManager; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkUtils; -import android.net.cts.util.CtsNetUtils; -import android.platform.test.annotations.AppModeFull; -import android.provider.Settings; -import android.system.ErrnoException; -import android.system.OsConstants; -import android.test.AndroidTestCase; - -import java.util.ArrayList; - -public class MultinetworkApiTest extends AndroidTestCase { - - static { - System.loadLibrary("nativemultinetwork_jni"); - } - - private static final String TAG = "MultinetworkNativeApiTest"; - static final String GOOGLE_PRIVATE_DNS_SERVER = "dns.google"; - - /** - * @return 0 on success - */ - private static native int runGetaddrinfoCheck(long networkHandle); - private static native int runSetprocnetwork(long networkHandle); - private static native int runSetsocknetwork(long networkHandle); - private static native int runDatagramCheck(long networkHandle); - private static native void runResNapiMalformedCheck(long networkHandle); - private static native void runResNcancelCheck(long networkHandle); - private static native void runResNqueryCheck(long networkHandle); - private static native void runResNsendCheck(long networkHandle); - private static native void runResNnxDomainCheck(long networkHandle); - - - private ContentResolver mCR; - private ConnectivityManager mCM; - private CtsNetUtils mCtsNetUtils; - private String mOldMode; - private String mOldDnsSpecifier; - - @Override - protected void setUp() throws Exception { - super.setUp(); - mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE); - mCR = getContext().getContentResolver(); - mCtsNetUtils = new CtsNetUtils(getContext()); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - private Network[] getTestableNetworks() { - final ArrayList testableNetworks = new ArrayList(); - for (Network network : mCM.getAllNetworks()) { - final NetworkCapabilities nc = mCM.getNetworkCapabilities(network); - if (nc != null - && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { - testableNetworks.add(network); - } - } - - assertTrue( - "This test requires that at least one network be connected. " + - "Please ensure that the device is connected to a network.", - testableNetworks.size() >= 1); - return testableNetworks.toArray(new Network[0]); - } - - public void testGetaddrinfo() throws ErrnoException { - for (Network network : getTestableNetworks()) { - int errno = runGetaddrinfoCheck(network.getNetworkHandle()); - if (errno != 0) { - throw new ErrnoException( - "getaddrinfo on " + mCM.getNetworkInfo(network), -errno); - } - } - } - - public void testSetprocnetwork() throws ErrnoException { - // Hopefully no prior test in this process space has set a default network. - assertNull(mCM.getProcessDefaultNetwork()); - assertEquals(0, NetworkUtils.getBoundNetworkForProcess()); - - for (Network network : getTestableNetworks()) { - mCM.setProcessDefaultNetwork(null); - assertNull(mCM.getProcessDefaultNetwork()); - - int errno = runSetprocnetwork(network.getNetworkHandle()); - if (errno != 0) { - throw new ErrnoException( - "setprocnetwork on " + mCM.getNetworkInfo(network), -errno); - } - Network processDefault = mCM.getProcessDefaultNetwork(); - assertNotNull(processDefault); - assertEquals(network, processDefault); - // TODO: open DatagramSockets, connect them to 192.0.2.1 and 2001:db8::, - // and ensure that the source address is in fact on this network as - // determined by mCM.getLinkProperties(network). - - mCM.setProcessDefaultNetwork(null); - } - - for (Network network : getTestableNetworks()) { - NetworkUtils.bindProcessToNetwork(0); - assertNull(mCM.getBoundNetworkForProcess()); - - int errno = runSetprocnetwork(network.getNetworkHandle()); - if (errno != 0) { - throw new ErrnoException( - "setprocnetwork on " + mCM.getNetworkInfo(network), -errno); - } - assertEquals(network, new Network(mCM.getBoundNetworkForProcess())); - // TODO: open DatagramSockets, connect them to 192.0.2.1 and 2001:db8::, - // and ensure that the source address is in fact on this network as - // determined by mCM.getLinkProperties(network). - - NetworkUtils.bindProcessToNetwork(0); - } - } - - public void testSetsocknetwork() throws ErrnoException { - for (Network network : getTestableNetworks()) { - int errno = runSetsocknetwork(network.getNetworkHandle()); - if (errno != 0) { - throw new ErrnoException( - "setsocknetwork on " + mCM.getNetworkInfo(network), -errno); - } - } - } - - public void testNativeDatagramTransmission() throws ErrnoException { - for (Network network : getTestableNetworks()) { - int errno = runDatagramCheck(network.getNetworkHandle()); - if (errno != 0) { - throw new ErrnoException( - "DatagramCheck on " + mCM.getNetworkInfo(network), -errno); - } - } - } - - public void testNoSuchNetwork() { - final Network eNoNet = new Network(54321); - assertNull(mCM.getNetworkInfo(eNoNet)); - - final long eNoNetHandle = eNoNet.getNetworkHandle(); - assertEquals(-OsConstants.ENONET, runSetsocknetwork(eNoNetHandle)); - assertEquals(-OsConstants.ENONET, runSetprocnetwork(eNoNetHandle)); - // TODO: correct test permissions so this call is not silently re-mapped - // to query on the default network. - // assertEquals(-OsConstants.ENONET, runGetaddrinfoCheck(eNoNetHandle)); - } - - public void testNetworkHandle() { - // Test Network -> NetworkHandle -> Network results in the same Network. - for (Network network : getTestableNetworks()) { - long networkHandle = network.getNetworkHandle(); - Network newNetwork = Network.fromNetworkHandle(networkHandle); - assertEquals(newNetwork, network); - } - - // Test that only obfuscated handles are allowed. - try { - Network.fromNetworkHandle(100); - fail(); - } catch (IllegalArgumentException e) {} - try { - Network.fromNetworkHandle(-1); - fail(); - } catch (IllegalArgumentException e) {} - try { - Network.fromNetworkHandle(0); - fail(); - } catch (IllegalArgumentException e) {} - } - - public void testResNApi() throws Exception { - final Network[] testNetworks = getTestableNetworks(); - - for (Network network : testNetworks) { - // Throws AssertionError directly in jni function if test fail. - runResNqueryCheck(network.getNetworkHandle()); - runResNsendCheck(network.getNetworkHandle()); - runResNcancelCheck(network.getNetworkHandle()); - runResNapiMalformedCheck(network.getNetworkHandle()); - - final NetworkCapabilities nc = mCM.getNetworkCapabilities(network); - // Some cellular networks configure their DNS servers never to return NXDOMAIN, so don't - // test NXDOMAIN on these DNS servers. - // b/144521720 - if (nc != null && !nc.hasTransport(TRANSPORT_CELLULAR)) { - runResNnxDomainCheck(network.getNetworkHandle()); - } - } - } - - @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps") - public void testResNApiNXDomainPrivateDns() throws InterruptedException { - mCtsNetUtils.storePrivateDnsSetting(); - // Enable private DNS strict mode and set server to dns.google before doing NxDomain test. - // b/144521720 - try { - mCtsNetUtils.setPrivateDnsStrictMode(GOOGLE_PRIVATE_DNS_SERVER); - for (Network network : getTestableNetworks()) { - // Wait for private DNS setting to propagate. - mCtsNetUtils.awaitPrivateDnsSetting("NxDomain test wait private DNS setting timeout", - network, GOOGLE_PRIVATE_DNS_SERVER, true); - runResNnxDomainCheck(network.getNetworkHandle()); - } - } finally { - mCtsNetUtils.restorePrivateDnsSetting(); - } - } -} diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt deleted file mode 100644 index d2ca3f88cd..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt +++ /dev/null @@ -1,641 +0,0 @@ -/* - * 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.cts - -import android.app.Instrumentation -import android.content.Context -import android.net.ConnectivityManager -import android.net.KeepalivePacketData -import android.net.LinkAddress -import android.net.LinkProperties -import android.net.Network -import android.net.NetworkAgent -import android.net.NetworkAgent.CMD_ADD_KEEPALIVE_PACKET_FILTER -import android.net.NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT -import android.net.NetworkAgent.CMD_REMOVE_KEEPALIVE_PACKET_FILTER -import android.net.NetworkAgent.CMD_REPORT_NETWORK_STATUS -import android.net.NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED -import android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE -import android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE -import android.net.NetworkAgent.INVALID_NETWORK -import android.net.NetworkAgent.VALID_NETWORK -import android.net.NetworkAgentConfig -import android.net.NetworkCapabilities -import android.net.NetworkProvider -import android.net.NetworkRequest -import android.net.SocketKeepalive -import android.net.StringNetworkSpecifier -import android.net.Uri -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnAddKeepalivePacketFilter -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnAutomaticReconnectDisabled -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnBandwidthUpdateRequested -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnNetworkUnwanted -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnRemoveKeepalivePacketFilter -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnSaveAcceptUnvalidated -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnSignalStrengthThresholdsUpdated -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnStartSocketKeepalive -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnStopSocketKeepalive -import android.net.cts.NetworkAgentTest.TestableNetworkAgent.CallbackEntry.OnValidationStatus -import android.os.Build -import android.os.Bundle -import android.os.Handler -import android.os.HandlerThread -import android.os.Looper -import android.os.Message -import android.os.Messenger -import androidx.test.InstrumentationRegistry -import androidx.test.runner.AndroidJUnit4 -import com.android.internal.util.AsyncChannel -import com.android.net.module.util.ArrayTrackRecord -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.RecorderCallback.CallbackEntry.Available -import com.android.testutils.RecorderCallback.CallbackEntry.Lost -import com.android.testutils.TestableNetworkCallback -import org.junit.After -import org.junit.Assert.assertArrayEquals -import org.junit.Assert.fail -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import java.net.InetAddress -import java.time.Duration -import java.util.UUID -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertFalse -import kotlin.test.assertNotNull -import kotlin.test.assertNull -import kotlin.test.assertTrue - -// This test doesn't really have a constraint on how fast the methods should return. If it's -// going to fail, it will simply wait forever, so setting a high timeout lowers the flake ratio -// without affecting the run time of successful runs. Thus, set a very high timeout. -private const val DEFAULT_TIMEOUT_MS = 5000L -// When waiting for a NetworkCallback to determine there was no timeout, waiting is the -// only possible thing (the relevant handler is the one in the real ConnectivityService, -// and then there is the Binder call), so have a short timeout for this as it will be -// exhausted every time. -private const val NO_CALLBACK_TIMEOUT = 200L -// Any legal score (0~99) for the test network would do, as it is going to be kept up by the -// requests filed by the test and should never match normal internet requests. 70 is the default -// score of Ethernet networks, it's as good a value as any other. -private const val TEST_NETWORK_SCORE = 70 -private const val BETTER_NETWORK_SCORE = 75 -private const val FAKE_NET_ID = 1098 -private val instrumentation: Instrumentation - get() = InstrumentationRegistry.getInstrumentation() -private val context: Context - get() = InstrumentationRegistry.getContext() -private fun Message(what: Int, arg1: Int, arg2: Int, obj: Any?) = Message.obtain().also { - it.what = what - it.arg1 = arg1 - it.arg2 = arg2 - it.obj = obj -} - -@RunWith(AndroidJUnit4::class) -class NetworkAgentTest { - @Rule @JvmField - val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.Q) - - private val LOCAL_IPV4_ADDRESS = InetAddress.parseNumericAddress("192.0.2.1") - private val REMOTE_IPV4_ADDRESS = InetAddress.parseNumericAddress("192.0.2.2") - - private val mCM = context.getSystemService(ConnectivityManager::class.java) - private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread") - private val mFakeConnectivityService by lazy { FakeConnectivityService(mHandlerThread.looper) } - - private class Provider(context: Context, looper: Looper) : - NetworkProvider(context, looper, "NetworkAgentTest NetworkProvider") - - private val agentsToCleanUp = mutableListOf() - private val callbacksToCleanUp = mutableListOf() - - @Before - fun setUp() { - instrumentation.getUiAutomation().adoptShellPermissionIdentity() - mHandlerThread.start() - } - - @After - fun tearDown() { - agentsToCleanUp.forEach { it.unregister() } - callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) } - mHandlerThread.quitSafely() - instrumentation.getUiAutomation().dropShellPermissionIdentity() - } - - /** - * A fake that helps simulating ConnectivityService talking to a harnessed agent. - * This fake only supports speaking to one harnessed agent at a time because it - * only keeps track of one async channel. - */ - private class FakeConnectivityService(looper: Looper) { - private val CMD_EXPECT_DISCONNECT = 1 - private var disconnectExpected = false - private val msgHistory = ArrayTrackRecord().newReadHead() - private val asyncChannel = AsyncChannel() - private val handler = object : Handler(looper) { - override fun handleMessage(msg: Message) { - msgHistory.add(Message.obtain(msg)) // make a copy as the original will be recycled - when (msg.what) { - CMD_EXPECT_DISCONNECT -> disconnectExpected = true - AsyncChannel.CMD_CHANNEL_HALF_CONNECTED -> - asyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION) - AsyncChannel.CMD_CHANNEL_DISCONNECTED -> - if (!disconnectExpected) { - fail("Agent unexpectedly disconnected") - } else { - disconnectExpected = false - } - } - } - } - - fun connect(agentMsngr: Messenger) = asyncChannel.connect(context, handler, agentMsngr) - - fun disconnect() = asyncChannel.disconnect() - - fun sendMessage(what: Int, arg1: Int = 0, arg2: Int = 0, obj: Any? = null) = - asyncChannel.sendMessage(Message(what, arg1, arg2, obj)) - - fun expectMessage(what: Int) = - assertNotNull(msgHistory.poll(DEFAULT_TIMEOUT_MS) { it.what == what }) - - fun willExpectDisconnectOnce() = handler.sendEmptyMessage(CMD_EXPECT_DISCONNECT) - } - - private open class TestableNetworkAgent( - looper: Looper, - val nc: NetworkCapabilities, - val lp: LinkProperties, - conf: NetworkAgentConfig - ) : NetworkAgent(context, looper, TestableNetworkAgent::class.java.simpleName /* tag */, - nc, lp, TEST_NETWORK_SCORE, conf, Provider(context, looper)) { - private val history = ArrayTrackRecord().newReadHead() - - sealed class CallbackEntry { - object OnBandwidthUpdateRequested : CallbackEntry() - object OnNetworkUnwanted : CallbackEntry() - data class OnAddKeepalivePacketFilter( - val slot: Int, - val packet: KeepalivePacketData - ) : CallbackEntry() - data class OnRemoveKeepalivePacketFilter(val slot: Int) : CallbackEntry() - data class OnStartSocketKeepalive( - val slot: Int, - val interval: Int, - val packet: KeepalivePacketData - ) : CallbackEntry() - data class OnStopSocketKeepalive(val slot: Int) : CallbackEntry() - data class OnSaveAcceptUnvalidated(val accept: Boolean) : CallbackEntry() - object OnAutomaticReconnectDisabled : CallbackEntry() - data class OnValidationStatus(val status: Int, val uri: Uri?) : CallbackEntry() - data class OnSignalStrengthThresholdsUpdated(val thresholds: IntArray) : CallbackEntry() - } - - fun getName(): String? = (nc.getNetworkSpecifier() as? StringNetworkSpecifier)?.specifier - - override fun onBandwidthUpdateRequested() { - history.add(OnBandwidthUpdateRequested) - } - - override fun onNetworkUnwanted() { - history.add(OnNetworkUnwanted) - } - - override fun onAddKeepalivePacketFilter(slot: Int, packet: KeepalivePacketData) { - history.add(OnAddKeepalivePacketFilter(slot, packet)) - } - - override fun onRemoveKeepalivePacketFilter(slot: Int) { - history.add(OnRemoveKeepalivePacketFilter(slot)) - } - - override fun onStartSocketKeepalive( - slot: Int, - interval: Duration, - packet: KeepalivePacketData - ) { - history.add(OnStartSocketKeepalive(slot, interval.seconds.toInt(), packet)) - } - - override fun onStopSocketKeepalive(slot: Int) { - history.add(OnStopSocketKeepalive(slot)) - } - - override fun onSaveAcceptUnvalidated(accept: Boolean) { - history.add(OnSaveAcceptUnvalidated(accept)) - } - - override fun onAutomaticReconnectDisabled() { - history.add(OnAutomaticReconnectDisabled) - } - - override fun onSignalStrengthThresholdsUpdated(thresholds: IntArray) { - history.add(OnSignalStrengthThresholdsUpdated(thresholds)) - } - - fun expectEmptySignalStrengths() { - expectCallback().let { - // intArrayOf() without arguments makes an empty array - assertArrayEquals(intArrayOf(), it.thresholds) - } - } - - override fun onValidationStatus(status: Int, uri: Uri?) { - history.add(OnValidationStatus(status, uri)) - } - - // Expects the initial validation event that always occurs immediately after registering - // a NetworkAgent whose network does not require validation (which test networks do - // not, since they lack the INTERNET capability). It always contains the default argument - // for the URI. - fun expectNoInternetValidationStatus() = expectCallback().let { - assertEquals(it.status, VALID_NETWORK) - // The returned Uri is parsed from the empty string, which means it's an - // instance of the (private) Uri.StringUri. There are no real good ways - // to check this, the least bad is to just convert it to a string and - // make sure it's empty. - assertEquals("", it.uri.toString()) - } - - inline fun expectCallback(): T { - val foundCallback = history.poll(DEFAULT_TIMEOUT_MS) - assertTrue(foundCallback is T, "Expected ${T::class} but found $foundCallback") - return foundCallback - } - - fun assertNoCallback() { - assertTrue(waitForIdle(DEFAULT_TIMEOUT_MS), - "Handler didn't became idle after ${DEFAULT_TIMEOUT_MS}ms") - assertNull(history.peek()) - } - } - - private fun requestNetwork(request: NetworkRequest, callback: TestableNetworkCallback) { - mCM.requestNetwork(request, callback) - callbacksToCleanUp.add(callback) - } - - private fun registerNetworkCallback( - request: NetworkRequest, - callback: TestableNetworkCallback - ) { - mCM.registerNetworkCallback(request, callback) - callbacksToCleanUp.add(callback) - } - - private fun createNetworkAgent(name: String? = null): TestableNetworkAgent { - val nc = NetworkCapabilities().apply { - addTransportType(NetworkCapabilities.TRANSPORT_TEST) - removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) - removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) - addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) - addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - if (null != name) { - setNetworkSpecifier(StringNetworkSpecifier(name)) - } - } - val lp = LinkProperties().apply { - addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 0)) - } - val config = NetworkAgentConfig.Builder().build() - return TestableNetworkAgent(mHandlerThread.looper, nc, lp, config).also { - agentsToCleanUp.add(it) - } - } - - private fun createConnectedNetworkAgent(name: String? = null): - Pair { - val request: NetworkRequest = NetworkRequest.Builder() - .clearCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_TEST) - .build() - val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) - requestNetwork(request, callback) - val agent = createNetworkAgent(name) - agent.register() - agent.markConnected() - return agent to callback - } - - private fun createNetworkAgentWithFakeCS() = createNetworkAgent().also { - mFakeConnectivityService.connect(it.registerForTest(Network(FAKE_NET_ID))) - } - - @Test - fun testConnectAndUnregister() { - val (agent, callback) = createConnectedNetworkAgent() - callback.expectAvailableThenValidatedCallbacks(agent.network) - agent.expectEmptySignalStrengths() - agent.expectNoInternetValidationStatus() - agent.unregister() - callback.expectCallback(agent.network) - agent.expectCallback() - assertFailsWith("Must not be able to register an agent twice") { - agent.register() - } - } - - @Test - fun testOnBandwidthUpdateRequested() { - val (agent, callback) = createConnectedNetworkAgent() - callback.expectAvailableThenValidatedCallbacks(agent.network) - agent.expectEmptySignalStrengths() - agent.expectNoInternetValidationStatus() - mCM.requestBandwidthUpdate(agent.network) - agent.expectCallback() - agent.unregister() - } - - @Test - fun testSignalStrengthThresholds() { - val thresholds = intArrayOf(30, 50, 65) - val callbacks = thresholds.map { strength -> - val request = NetworkRequest.Builder() - .clearCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_TEST) - .setSignalStrength(strength) - .build() - TestableNetworkCallback(DEFAULT_TIMEOUT_MS).also { - registerNetworkCallback(request, it) - } - } - createConnectedNetworkAgent().let { (agent, callback) -> - callback.expectAvailableThenValidatedCallbacks(agent.network) - agent.expectCallback().let { - assertArrayEquals(it.thresholds, thresholds) - } - agent.expectNoInternetValidationStatus() - - // Send signal strength and check that the callbacks are called appropriately. - val nc = NetworkCapabilities(agent.nc) - nc.setSignalStrength(20) - agent.sendNetworkCapabilities(nc) - callbacks.forEach { it.assertNoCallback(NO_CALLBACK_TIMEOUT) } - - nc.setSignalStrength(40) - agent.sendNetworkCapabilities(nc) - callbacks[0].expectAvailableCallbacks(agent.network) - callbacks[1].assertNoCallback(NO_CALLBACK_TIMEOUT) - callbacks[2].assertNoCallback(NO_CALLBACK_TIMEOUT) - - nc.setSignalStrength(80) - agent.sendNetworkCapabilities(nc) - callbacks[0].expectCapabilitiesThat(agent.network) { it.signalStrength == 80 } - callbacks[1].expectAvailableCallbacks(agent.network) - callbacks[2].expectAvailableCallbacks(agent.network) - - nc.setSignalStrength(55) - agent.sendNetworkCapabilities(nc) - callbacks[0].expectCapabilitiesThat(agent.network) { it.signalStrength == 55 } - callbacks[1].expectCapabilitiesThat(agent.network) { it.signalStrength == 55 } - callbacks[2].expectCallback(agent.network) - } - callbacks.forEach { - mCM.unregisterNetworkCallback(it) - } - } - - @Test - fun testSocketKeepalive(): Unit = createNetworkAgentWithFakeCS().let { agent -> - val packet = object : KeepalivePacketData( - LOCAL_IPV4_ADDRESS /* srcAddress */, 1234 /* srcPort */, - REMOTE_IPV4_ADDRESS /* dstAddress */, 4567 /* dstPort */, - ByteArray(100 /* size */) { it.toByte() /* init */ }) {} - val slot = 4 - val interval = 37 - - mFakeConnectivityService.sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, - arg1 = slot, obj = packet) - mFakeConnectivityService.sendMessage(CMD_START_SOCKET_KEEPALIVE, - arg1 = slot, arg2 = interval, obj = packet) - - agent.expectCallback().let { - assertEquals(it.slot, slot) - assertEquals(it.packet, packet) - } - agent.expectCallback().let { - assertEquals(it.slot, slot) - assertEquals(it.interval, interval) - assertEquals(it.packet, packet) - } - - agent.assertNoCallback() - - // Check that when the agent sends a keepalive event, ConnectivityService receives the - // expected message. - agent.sendSocketKeepaliveEvent(slot, SocketKeepalive.ERROR_UNSUPPORTED) - mFakeConnectivityService.expectMessage(NetworkAgent.EVENT_SOCKET_KEEPALIVE).let() { - assertEquals(slot, it.arg1) - assertEquals(SocketKeepalive.ERROR_UNSUPPORTED, it.arg2) - } - - mFakeConnectivityService.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, arg1 = slot) - mFakeConnectivityService.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, arg1 = slot) - agent.expectCallback().let { - assertEquals(it.slot, slot) - } - agent.expectCallback().let { - assertEquals(it.slot, slot) - } - } - - @Test - fun testSendUpdates(): Unit = createConnectedNetworkAgent().let { (agent, callback) -> - callback.expectAvailableThenValidatedCallbacks(agent.network) - agent.expectEmptySignalStrengths() - agent.expectNoInternetValidationStatus() - val ifaceName = "adhocIface" - val lp = LinkProperties(agent.lp) - lp.setInterfaceName(ifaceName) - agent.sendLinkProperties(lp) - callback.expectLinkPropertiesThat(agent.network) { - it.getInterfaceName() == ifaceName - } - val nc = NetworkCapabilities(agent.nc) - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) - agent.sendNetworkCapabilities(nc) - callback.expectCapabilitiesThat(agent.network) { - it.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) - } - } - - @Test - fun testSendScore() { - // This test will create two networks and check that the one with the stronger - // score wins out for a request that matches them both. - // First create requests to make sure both networks are kept up, using the - // specifier so they are specific to each network - val name1 = UUID.randomUUID().toString() - val name2 = UUID.randomUUID().toString() - val request1 = NetworkRequest.Builder() - .clearCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_TEST) - .setNetworkSpecifier(StringNetworkSpecifier(name1)) - .build() - val request2 = NetworkRequest.Builder() - .clearCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_TEST) - .setNetworkSpecifier(StringNetworkSpecifier(name2)) - .build() - val callback1 = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) - val callback2 = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) - requestNetwork(request1, callback1) - requestNetwork(request2, callback2) - - // Then file the interesting request - val request = NetworkRequest.Builder() - .clearCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_TEST) - .build() - val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) - requestNetwork(request, callback) - - // Connect the first Network - createConnectedNetworkAgent(name1).let { (agent1, _) -> - callback.expectAvailableThenValidatedCallbacks(agent1.network) - // Upgrade agent1 to a better score so that there is no ambiguity when - // agent2 connects that agent1 is still better - agent1.sendNetworkScore(BETTER_NETWORK_SCORE - 1) - // Connect the second agent - createConnectedNetworkAgent(name2).let { (agent2, _) -> - agent2.markConnected() - // The callback should not see anything yet - callback.assertNoCallback(NO_CALLBACK_TIMEOUT) - // Now update the score and expect the callback now prefers agent2 - agent2.sendNetworkScore(BETTER_NETWORK_SCORE) - callback.expectCallback(agent2.network) - } - } - - // tearDown() will unregister the requests and agents - } - - @Test - fun testSetAcceptUnvalidated() { - createNetworkAgentWithFakeCS().let { agent -> - mFakeConnectivityService.sendMessage(CMD_SAVE_ACCEPT_UNVALIDATED, 1) - agent.expectCallback().let { - assertTrue(it.accept) - } - agent.assertNoCallback() - } - } - - @Test - fun testSetAcceptUnvalidatedPreventAutomaticReconnect() { - createNetworkAgentWithFakeCS().let { agent -> - mFakeConnectivityService.sendMessage(CMD_SAVE_ACCEPT_UNVALIDATED, 0) - mFakeConnectivityService.sendMessage(CMD_PREVENT_AUTOMATIC_RECONNECT) - agent.expectCallback().let { - assertFalse(it.accept) - } - agent.expectCallback() - agent.assertNoCallback() - // When automatic reconnect is turned off, the network is torn down and - // ConnectivityService sends a disconnect. This in turn causes the agent - // to send a DISCONNECTED message to CS. - mFakeConnectivityService.willExpectDisconnectOnce() - mFakeConnectivityService.disconnect() - mFakeConnectivityService.expectMessage(AsyncChannel.CMD_CHANNEL_DISCONNECTED) - agent.expectCallback() - } - } - - @Test - fun testPreventAutomaticReconnect() { - createNetworkAgentWithFakeCS().let { agent -> - mFakeConnectivityService.sendMessage(CMD_PREVENT_AUTOMATIC_RECONNECT) - agent.expectCallback() - agent.assertNoCallback() - mFakeConnectivityService.willExpectDisconnectOnce() - mFakeConnectivityService.disconnect() - mFakeConnectivityService.expectMessage(AsyncChannel.CMD_CHANNEL_DISCONNECTED) - agent.expectCallback() - } - } - - @Test - fun testValidationStatus() = createNetworkAgentWithFakeCS().let { agent -> - val uri = Uri.parse("http://www.google.com") - val bundle = Bundle().apply { - putString(NetworkAgent.REDIRECT_URL_KEY, uri.toString()) - } - mFakeConnectivityService.sendMessage(CMD_REPORT_NETWORK_STATUS, - arg1 = VALID_NETWORK, obj = bundle) - agent.expectCallback().let { - assertEquals(it.status, VALID_NETWORK) - assertEquals(it.uri, uri) - } - - mFakeConnectivityService.sendMessage(CMD_REPORT_NETWORK_STATUS, - arg1 = INVALID_NETWORK, obj = Bundle()) - agent.expectCallback().let { - assertEquals(it.status, INVALID_NETWORK) - assertNull(it.uri) - } - } - - @Test - fun testTemporarilyUnmeteredCapability() { - // This test will create a networks with/without NET_CAPABILITY_TEMPORARILY_NOT_METERED - // and check that the callback reflects the capability changes. - // First create a request to make sure the network is kept up - val request1 = NetworkRequest.Builder() - .clearCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_TEST) - .build() - val callback1 = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS).also { - registerNetworkCallback(request1, it) - } - requestNetwork(request1, callback1) - - // Then file the interesting request - val request = NetworkRequest.Builder() - .clearCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_TEST) - .build() - val callback = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS) - requestNetwork(request, callback) - - // Connect the network - createConnectedNetworkAgent().let { (agent, _) -> - callback.expectAvailableThenValidatedCallbacks(agent.network) - - // Send TEMP_NOT_METERED and check that the callback is called appropriately. - val nc1 = NetworkCapabilities(agent.nc) - .addCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED) - agent.sendNetworkCapabilities(nc1) - callback.expectCapabilitiesThat(agent.network) { - it.hasCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED) - } - - // Remove TEMP_NOT_METERED and check that the callback is called appropriately. - val nc2 = NetworkCapabilities(agent.nc) - .removeCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED) - agent.sendNetworkCapabilities(nc2) - callback.expectCapabilitiesThat(agent.network) { - !it.hasCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED) - } - } - - // tearDown() will unregister the requests and agents - } -} diff --git a/tests/cts/net/src/android/net/cts/NetworkInfoTest.kt b/tests/cts/net/src/android/net/cts/NetworkInfoTest.kt deleted file mode 100644 index fa15e8f82c..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkInfoTest.kt +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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.cts - -import android.os.Build -import android.content.Context -import android.net.ConnectivityManager -import android.net.NetworkInfo -import android.net.NetworkInfo.DetailedState -import android.net.NetworkInfo.State -import android.telephony.TelephonyManager -import androidx.test.filters.SmallTest -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.runner.AndroidJUnit4 -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull -import org.junit.Assert.assertNull -import org.junit.Assert.assertTrue -import org.junit.Assert.fail -import org.junit.Rule -import org.junit.runner.RunWith -import org.junit.Test - -const val TYPE_MOBILE = ConnectivityManager.TYPE_MOBILE -const val TYPE_WIFI = ConnectivityManager.TYPE_WIFI -const val MOBILE_TYPE_NAME = "mobile" -const val WIFI_TYPE_NAME = "WIFI" -const val LTE_SUBTYPE_NAME = "LTE" - -@SmallTest -@RunWith(AndroidJUnit4::class) -class NetworkInfoTest { - @Rule @JvmField - val ignoreRule = DevSdkIgnoreRule() - - @Test - fun testAccessNetworkInfoProperties() { - val cm = InstrumentationRegistry.getInstrumentation().context - .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - val ni = cm.getAllNetworkInfo() - assertTrue(ni.isNotEmpty()) - - for (netInfo in ni) { - when (netInfo.getType()) { - TYPE_MOBILE -> assertNetworkInfo(netInfo, MOBILE_TYPE_NAME) - TYPE_WIFI -> assertNetworkInfo(netInfo, WIFI_TYPE_NAME) - // TODO: Add BLUETOOTH_TETHER testing - } - } - } - - private fun assertNetworkInfo(netInfo: NetworkInfo, expectedTypeName: String) { - assertTrue(expectedTypeName.equals(netInfo.getTypeName(), ignoreCase = true)) - assertNotNull(netInfo.toString()) - - if (!netInfo.isConnectedOrConnecting()) return - - assertTrue(netInfo.isAvailable()) - if (State.CONNECTED == netInfo.getState()) { - assertTrue(netInfo.isConnected()) - } - assertTrue(State.CONNECTING == netInfo.getState() || - State.CONNECTED == netInfo.getState()) - assertTrue(DetailedState.SCANNING == netInfo.getDetailedState() || - DetailedState.CONNECTING == netInfo.getDetailedState() || - DetailedState.AUTHENTICATING == netInfo.getDetailedState() || - DetailedState.CONNECTED == netInfo.getDetailedState()) - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - fun testConstructor() { - val networkInfo = NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE, - MOBILE_TYPE_NAME, LTE_SUBTYPE_NAME) - - assertEquals(TYPE_MOBILE, networkInfo.type) - assertEquals(TelephonyManager.NETWORK_TYPE_LTE, networkInfo.subtype) - assertEquals(MOBILE_TYPE_NAME, networkInfo.typeName) - assertEquals(LTE_SUBTYPE_NAME, networkInfo.subtypeName) - assertEquals(DetailedState.IDLE, networkInfo.detailedState) - assertEquals(State.UNKNOWN, networkInfo.state) - assertNull(networkInfo.reason) - assertNull(networkInfo.extraInfo) - - try { - NetworkInfo(ConnectivityManager.MAX_NETWORK_TYPE + 1, - TelephonyManager.NETWORK_TYPE_LTE, MOBILE_TYPE_NAME, LTE_SUBTYPE_NAME) - fail("Unexpected behavior. Network type is invalid.") - } catch (e: IllegalArgumentException) { - // Expected behavior. - } - } - - @Test - fun testSetDetailedState() { - val networkInfo = NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE, - MOBILE_TYPE_NAME, LTE_SUBTYPE_NAME) - val reason = "TestNetworkInfo" - val extraReason = "setDetailedState test" - - networkInfo.setDetailedState(DetailedState.CONNECTED, reason, extraReason) - assertEquals(DetailedState.CONNECTED, networkInfo.detailedState) - assertEquals(State.CONNECTED, networkInfo.state) - assertEquals(reason, networkInfo.reason) - assertEquals(extraReason, networkInfo.extraInfo) - } -} diff --git a/tests/cts/net/src/android/net/cts/NetworkInfo_DetailedStateTest.java b/tests/cts/net/src/android/net/cts/NetworkInfo_DetailedStateTest.java deleted file mode 100644 index 590ce89579..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkInfo_DetailedStateTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2009 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.cts; - - -import android.net.NetworkInfo.DetailedState; -import android.test.AndroidTestCase; - -public class NetworkInfo_DetailedStateTest extends AndroidTestCase { - - public void testValueOf() { - assertEquals(DetailedState.AUTHENTICATING, DetailedState.valueOf("AUTHENTICATING")); - assertEquals(DetailedState.CONNECTED, DetailedState.valueOf("CONNECTED")); - assertEquals(DetailedState.CONNECTING, DetailedState.valueOf("CONNECTING")); - assertEquals(DetailedState.DISCONNECTED, DetailedState.valueOf("DISCONNECTED")); - assertEquals(DetailedState.DISCONNECTING, DetailedState.valueOf("DISCONNECTING")); - assertEquals(DetailedState.FAILED, DetailedState.valueOf("FAILED")); - assertEquals(DetailedState.IDLE, DetailedState.valueOf("IDLE")); - assertEquals(DetailedState.OBTAINING_IPADDR, DetailedState.valueOf("OBTAINING_IPADDR")); - assertEquals(DetailedState.SCANNING, DetailedState.valueOf("SCANNING")); - assertEquals(DetailedState.SUSPENDED, DetailedState.valueOf("SUSPENDED")); - } - - public void testValues() { - DetailedState[] expected = DetailedState.values(); - assertEquals(13, expected.length); - assertEquals(DetailedState.IDLE, expected[0]); - assertEquals(DetailedState.SCANNING, expected[1]); - assertEquals(DetailedState.CONNECTING, expected[2]); - assertEquals(DetailedState.AUTHENTICATING, expected[3]); - assertEquals(DetailedState.OBTAINING_IPADDR, expected[4]); - assertEquals(DetailedState.CONNECTED, expected[5]); - assertEquals(DetailedState.SUSPENDED, expected[6]); - assertEquals(DetailedState.DISCONNECTING, expected[7]); - assertEquals(DetailedState.DISCONNECTED, expected[8]); - assertEquals(DetailedState.FAILED, expected[9]); - assertEquals(DetailedState.BLOCKED, expected[10]); - assertEquals(DetailedState.VERIFYING_POOR_LINK, expected[11]); - assertEquals(DetailedState.CAPTIVE_PORTAL_CHECK, expected[12]); - } - -} diff --git a/tests/cts/net/src/android/net/cts/NetworkInfo_StateTest.java b/tests/cts/net/src/android/net/cts/NetworkInfo_StateTest.java deleted file mode 100644 index 5303ef1281..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkInfo_StateTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2009 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.cts; - -import android.net.NetworkInfo.State; -import android.test.AndroidTestCase; - -public class NetworkInfo_StateTest extends AndroidTestCase { - - public void testValueOf() { - assertEquals(State.CONNECTED, State.valueOf("CONNECTED")); - assertEquals(State.CONNECTING, State.valueOf("CONNECTING")); - assertEquals(State.DISCONNECTED, State.valueOf("DISCONNECTED")); - assertEquals(State.DISCONNECTING, State.valueOf("DISCONNECTING")); - assertEquals(State.SUSPENDED, State.valueOf("SUSPENDED")); - assertEquals(State.UNKNOWN, State.valueOf("UNKNOWN")); - } - - public void testValues() { - State[] expected = State.values(); - assertEquals(6, expected.length); - assertEquals(State.CONNECTING, expected[0]); - assertEquals(State.CONNECTED, expected[1]); - assertEquals(State.SUSPENDED, expected[2]); - assertEquals(State.DISCONNECTING, expected[3]); - assertEquals(State.DISCONNECTED, expected[4]); - assertEquals(State.UNKNOWN, expected[5]); - } -} diff --git a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java deleted file mode 100644 index d118c8a0ca..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2018 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.cts; - -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; -import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; -import static android.net.NetworkCapabilities.TRANSPORT_WIFI; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import android.net.MacAddress; -import android.net.MatchAllNetworkSpecifier; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.net.NetworkSpecifier; -import android.net.UidRange; -import android.net.wifi.WifiNetworkSpecifier; -import android.os.Build; -import android.os.PatternMatcher; -import android.os.Process; -import android.util.ArraySet; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -public class NetworkRequestTest { - @Rule - public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); - - private static final String TEST_SSID = "TestSSID"; - private static final String OTHER_SSID = "OtherSSID"; - private static final int TEST_UID = 2097; - private static final String TEST_PACKAGE_NAME = "test.package.name"; - private static final MacAddress ARBITRARY_ADDRESS = MacAddress.fromString("3:5:8:12:9:2"); - - private class LocalNetworkSpecifier extends NetworkSpecifier { - private final int mId; - - LocalNetworkSpecifier(int id) { - mId = id; - } - - @Override - public boolean canBeSatisfiedBy(NetworkSpecifier other) { - return other instanceof LocalNetworkSpecifier - && mId == ((LocalNetworkSpecifier) other).mId; - } - } - - @Test - public void testCapabilities() { - assertTrue(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build() - .hasCapability(NET_CAPABILITY_MMS)); - assertFalse(new NetworkRequest.Builder().removeCapability(NET_CAPABILITY_MMS).build() - .hasCapability(NET_CAPABILITY_MMS)); - - final NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build(); - // Verify request has no capabilities - verifyNoCapabilities(nr); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testTemporarilyNotMeteredCapability() { - assertTrue(new NetworkRequest.Builder() - .addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED).build() - .hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); - assertFalse(new NetworkRequest.Builder() - .removeCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED).build() - .hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); - } - - private void verifyNoCapabilities(NetworkRequest nr) { - // NetworkCapabilities.mNetworkCapabilities is defined as type long - final int MAX_POSSIBLE_CAPABILITY = Long.SIZE; - for(int bit = 0; bit < MAX_POSSIBLE_CAPABILITY; bit++) { - assertFalse(nr.hasCapability(bit)); - } - } - - @Test - public void testTransports() { - assertTrue(new NetworkRequest.Builder().addTransportType(TRANSPORT_BLUETOOTH).build() - .hasTransport(TRANSPORT_BLUETOOTH)); - assertFalse(new NetworkRequest.Builder().removeTransportType(TRANSPORT_BLUETOOTH).build() - .hasTransport(TRANSPORT_BLUETOOTH)); - } - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testSpecifier() { - assertNull(new NetworkRequest.Builder().build().getNetworkSpecifier()); - final WifiNetworkSpecifier specifier = new WifiNetworkSpecifier.Builder() - .setSsidPattern(new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL)) - .setBssidPattern(ARBITRARY_ADDRESS, ARBITRARY_ADDRESS) - .build(); - final NetworkSpecifier obtainedSpecifier = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(specifier) - .build() - .getNetworkSpecifier(); - assertEquals(obtainedSpecifier, specifier); - - assertNull(new NetworkRequest.Builder() - .clearCapabilities() - .build() - .getNetworkSpecifier()); - } - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testRequestorPackageName() { - assertNull(new NetworkRequest.Builder().build().getRequestorPackageName()); - final String pkgName = "android.net.test"; - final NetworkCapabilities nc = new NetworkCapabilities.Builder() - .setRequestorPackageName(pkgName) - .build(); - final NetworkRequest nr = new NetworkRequest.Builder() - .setCapabilities(nc) - .build(); - assertEquals(pkgName, nr.getRequestorPackageName()); - assertNull(new NetworkRequest.Builder() - .clearCapabilities() - .build() - .getRequestorPackageName()); - } - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testCanBeSatisfiedBy() { - final LocalNetworkSpecifier specifier1 = new LocalNetworkSpecifier(1234 /* id */); - final LocalNetworkSpecifier specifier2 = new LocalNetworkSpecifier(5678 /* id */); - - final NetworkCapabilities capCellularMmsInternet = new NetworkCapabilities() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_MMS) - .addCapability(NET_CAPABILITY_INTERNET); - final NetworkCapabilities capCellularVpnMmsInternet = - new NetworkCapabilities(capCellularMmsInternet).addTransportType(TRANSPORT_VPN); - final NetworkCapabilities capCellularMmsInternetSpecifier1 = - new NetworkCapabilities(capCellularMmsInternet).setNetworkSpecifier(specifier1); - final NetworkCapabilities capVpnInternetSpecifier1 = new NetworkCapabilities() - .addCapability(NET_CAPABILITY_INTERNET) - .addTransportType(TRANSPORT_VPN) - .setNetworkSpecifier(specifier1); - final NetworkCapabilities capCellularMmsInternetMatchallspecifier = - new NetworkCapabilities(capCellularMmsInternet) - .setNetworkSpecifier(new MatchAllNetworkSpecifier()); - final NetworkCapabilities capCellularMmsInternetSpecifier2 = - new NetworkCapabilities(capCellularMmsInternet).setNetworkSpecifier(specifier2); - - final NetworkRequest requestCellularInternetSpecifier1 = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_INTERNET) - .setNetworkSpecifier(specifier1) - .build(); - assertFalse(requestCellularInternetSpecifier1.canBeSatisfiedBy(null)); - assertFalse(requestCellularInternetSpecifier1.canBeSatisfiedBy(new NetworkCapabilities())); - assertTrue(requestCellularInternetSpecifier1.canBeSatisfiedBy( - capCellularMmsInternetMatchallspecifier)); - assertFalse(requestCellularInternetSpecifier1.canBeSatisfiedBy(capCellularMmsInternet)); - assertTrue(requestCellularInternetSpecifier1.canBeSatisfiedBy( - capCellularMmsInternetSpecifier1)); - assertFalse(requestCellularInternetSpecifier1.canBeSatisfiedBy(capCellularVpnMmsInternet)); - assertFalse(requestCellularInternetSpecifier1.canBeSatisfiedBy( - capCellularMmsInternetSpecifier2)); - - final NetworkRequest requestCellularInternet = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_INTERNET) - .build(); - assertTrue(requestCellularInternet.canBeSatisfiedBy(capCellularMmsInternet)); - assertTrue(requestCellularInternet.canBeSatisfiedBy(capCellularMmsInternetSpecifier1)); - assertTrue(requestCellularInternet.canBeSatisfiedBy(capCellularMmsInternetSpecifier2)); - assertFalse(requestCellularInternet.canBeSatisfiedBy(capVpnInternetSpecifier1)); - assertTrue(requestCellularInternet.canBeSatisfiedBy(capCellularVpnMmsInternet)); - } - - @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testInvariantInCanBeSatisfiedBy() { - // Test invariant that result of NetworkRequest.canBeSatisfiedBy() should be the same with - // NetworkCapabilities.satisfiedByNetworkCapabilities(). - final LocalNetworkSpecifier specifier1 = new LocalNetworkSpecifier(1234 /* id */); - final int uid = Process.myUid(); - final ArraySet ranges = new ArraySet<>(); - ranges.add(new UidRange(uid, uid)); - final NetworkRequest requestCombination = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_INTERNET) - .setLinkUpstreamBandwidthKbps(1000) - .setNetworkSpecifier(specifier1) - .setSignalStrength(-123) - .setUids(ranges).build(); - final NetworkCapabilities capCell = new NetworkCapabilities.Builder() - .addTransportType(TRANSPORT_CELLULAR).build(); - assertCorrectlySatisfies(false, requestCombination, capCell); - - final NetworkCapabilities capCellInternet = new NetworkCapabilities.Builder(capCell) - .addCapability(NET_CAPABILITY_INTERNET).build(); - assertCorrectlySatisfies(false, requestCombination, capCellInternet); - - final NetworkCapabilities capCellInternetBW = - new NetworkCapabilities.Builder(capCellInternet) - .setLinkUpstreamBandwidthKbps(1024).build(); - assertCorrectlySatisfies(false, requestCombination, capCellInternetBW); - - final NetworkCapabilities capCellInternetBWSpecifier1 = - new NetworkCapabilities.Builder(capCellInternetBW) - .setNetworkSpecifier(specifier1).build(); - assertCorrectlySatisfies(false, requestCombination, capCellInternetBWSpecifier1); - - final NetworkCapabilities capCellInternetBWSpecifier1Signal = - new NetworkCapabilities.Builder(capCellInternetBWSpecifier1) - .setSignalStrength(-123).build(); - assertCorrectlySatisfies(true, requestCombination, - capCellInternetBWSpecifier1Signal); - - final NetworkCapabilities capCellInternetBWSpecifier1SignalUid = - new NetworkCapabilities.Builder(capCellInternetBWSpecifier1Signal) - .setOwnerUid(uid) - .setAdministratorUids(new int [] {uid}).build(); - assertCorrectlySatisfies(true, requestCombination, - capCellInternetBWSpecifier1SignalUid); - } - - private void assertCorrectlySatisfies(boolean expect, NetworkRequest request, - NetworkCapabilities nc) { - assertEquals(expect, request.canBeSatisfiedBy(nc)); - assertEquals( - request.canBeSatisfiedBy(nc), - request.networkCapabilities.satisfiedByNetworkCapabilities(nc)); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testRequestorUid() { - final NetworkCapabilities nc = new NetworkCapabilities(); - // Verify default value is INVALID_UID - assertEquals(Process.INVALID_UID, new NetworkRequest.Builder() - .setCapabilities(nc).build().getRequestorUid()); - - nc.setRequestorUid(1314); - final NetworkRequest nr = new NetworkRequest.Builder().setCapabilities(nc).build(); - assertEquals(1314, nr.getRequestorUid()); - - assertEquals(Process.INVALID_UID, new NetworkRequest.Builder() - .clearCapabilities().build().getRequestorUid()); - } -} diff --git a/tests/cts/net/src/android/net/cts/NetworkStackDependenciesTest.kt b/tests/cts/net/src/android/net/cts/NetworkStackDependenciesTest.kt deleted file mode 100644 index 1a7f9555f6..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkStackDependenciesTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.cts - -import android.content.pm.PackageManager -import android.net.cts.util.CtsNetUtils -import android.net.wifi.WifiManager -import android.os.Build -import androidx.test.filters.SdkSuppress -import androidx.test.platform.app.InstrumentationRegistry -import org.junit.Assume.assumeTrue -import org.junit.Test -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - -/** - * Basic tests for APIs used by the network stack module. - */ -class NetworkStackDependenciesTest { - @Test - @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.Q) - fun testGetFrequency() { - // WifiInfo#getFrequency was missing a CTS test in Q: this test is run as part of MTS on Q - // devices to ensure it behaves correctly. - val context = InstrumentationRegistry.getInstrumentation().getContext() - assumeTrue("This test only applies to devices that support wifi", - context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) - val wifiManager = context.getSystemService(WifiManager::class.java) - assertNotNull(wifiManager, "Device supports wifi but there is no WifiManager") - - CtsNetUtils(context).ensureWifiConnected() - val wifiInfo = wifiManager.getConnectionInfo() - // The NetworkStack can handle any value of getFrequency; unknown frequencies will not be - // classified in metrics, but this is expected behavior. It is only important that the - // method does not crash. Still verify that the frequency is positive - val frequency = wifiInfo.getFrequency() - assertTrue(frequency > 0, "Frequency must be > 0") - } -} \ No newline at end of file diff --git a/tests/cts/net/src/android/net/cts/NetworkStatsBinderTest.java b/tests/cts/net/src/android/net/cts/NetworkStatsBinderTest.java deleted file mode 100644 index 1a48983028..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkStatsBinderTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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.cts; - -import static android.os.Process.INVALID_UID; - -import static org.junit.Assert.assertEquals; - -import android.annotation.NonNull; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.net.INetworkStatsService; -import android.net.TrafficStats; -import android.os.Build; -import android.os.IBinder; -import android.os.Process; -import android.os.RemoteException; -import android.test.AndroidTestCase; -import android.util.SparseArray; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.CollectionUtils; -import com.android.testutils.DevSdkIgnoreRule; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; -import java.util.function.Predicate; - -@RunWith(AndroidJUnit4.class) -public class NetworkStatsBinderTest { - // NOTE: These are shamelessly copied from TrafficStats. - private static final int TYPE_RX_BYTES = 0; - private static final int TYPE_RX_PACKETS = 1; - private static final int TYPE_TX_BYTES = 2; - private static final int TYPE_TX_PACKETS = 3; - - @Rule - public DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule( - Build.VERSION_CODES.Q /* ignoreClassUpTo */); - - private final SparseArray> mUidStatsQueryOpArray = new SparseArray<>(); - - @Before - public void setUp() throws Exception { - mUidStatsQueryOpArray.put(TYPE_RX_BYTES, uid -> TrafficStats.getUidRxBytes(uid)); - mUidStatsQueryOpArray.put(TYPE_RX_PACKETS, uid -> TrafficStats.getUidRxPackets(uid)); - mUidStatsQueryOpArray.put(TYPE_TX_BYTES, uid -> TrafficStats.getUidTxBytes(uid)); - mUidStatsQueryOpArray.put(TYPE_TX_PACKETS, uid -> TrafficStats.getUidTxPackets(uid)); - } - - private long getUidStatsFromBinder(int uid, int type) throws Exception { - Method getServiceMethod = Class.forName("android.os.ServiceManager") - .getDeclaredMethod("getService", new Class[]{String.class}); - IBinder binder = (IBinder) getServiceMethod.invoke(null, Context.NETWORK_STATS_SERVICE); - INetworkStatsService nss = INetworkStatsService.Stub.asInterface(binder); - return nss.getUidStats(uid, type); - } - - private int getFirstAppUidThat(@NonNull Predicate predicate) { - PackageManager pm = InstrumentationRegistry.getContext().getPackageManager(); - List apps = pm.getInstalledPackages(0 /* flags */); - final PackageInfo match = CollectionUtils.find(apps, - it -> it.applicationInfo != null && predicate.test(it.applicationInfo.uid)); - if (match != null) return match.applicationInfo.uid; - return INVALID_UID; - } - - @Test - public void testAccessUidStatsFromBinder() throws Exception { - final int myUid = Process.myUid(); - final List testUidList = new ArrayList<>(); - - // Prepare uid list for testing. - testUidList.add(INVALID_UID); - testUidList.add(Process.ROOT_UID); - testUidList.add(Process.SYSTEM_UID); - testUidList.add(myUid); - testUidList.add(Process.LAST_APPLICATION_UID); - testUidList.add(Process.LAST_APPLICATION_UID + 1); - // If available, pick another existing uid for testing that is not already contained - // in the list above. - final int notMyUid = getFirstAppUidThat(uid -> uid >= 0 && !testUidList.contains(uid)); - if (notMyUid != INVALID_UID) testUidList.add(notMyUid); - - for (final int uid : testUidList) { - for (int i = 0; i < mUidStatsQueryOpArray.size(); i++) { - final int type = mUidStatsQueryOpArray.keyAt(i); - try { - final long uidStatsFromBinder = getUidStatsFromBinder(uid, type); - final long uidTrafficStats = mUidStatsQueryOpArray.get(type).apply(uid); - - // Verify that UNSUPPORTED is returned if the uid is not current app uid. - if (uid != myUid) { - assertEquals(uidStatsFromBinder, TrafficStats.UNSUPPORTED); - } - // Verify that returned result is the same with the result get from - // TrafficStats. - // TODO: If the test is flaky then it should instead assert that the values - // are approximately similar. - assertEquals("uidStats is not matched for query type " + type - + ", uid=" + uid + ", myUid=" + myUid, uidTrafficStats, - uidStatsFromBinder); - } catch (IllegalAccessException e) { - /* Java language access prevents exploitation. */ - return; - } catch (InvocationTargetException e) { - /* Underlying method has been changed. */ - return; - } catch (ClassNotFoundException e) { - /* not vulnerable if hidden API no longer available */ - return; - } catch (NoSuchMethodException e) { - /* not vulnerable if hidden API no longer available */ - return; - } catch (RemoteException e) { - return; - } - } - } - } -} diff --git a/tests/cts/net/src/android/net/cts/NetworkValidationTest.kt b/tests/cts/net/src/android/net/cts/NetworkValidationTest.kt deleted file mode 100644 index 5290f0db28..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkValidationTest.kt +++ /dev/null @@ -1,245 +0,0 @@ -/* - * 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.cts - -import android.Manifest.permission.MANAGE_TEST_NETWORKS -import android.Manifest.permission.NETWORK_SETTINGS -import android.content.Context -import android.content.pm.PackageManager -import android.net.ConnectivityManager -import android.net.EthernetManager -import android.net.InetAddresses -import android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL -import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED -import android.net.NetworkCapabilities.TRANSPORT_ETHERNET -import android.net.NetworkCapabilities.TRANSPORT_TEST -import android.net.NetworkRequest -import android.net.TestNetworkInterface -import android.net.TestNetworkManager -import android.net.Uri -import android.net.dhcp.DhcpDiscoverPacket -import android.net.dhcp.DhcpPacket -import android.net.dhcp.DhcpPacket.DHCP_MESSAGE_TYPE -import android.net.dhcp.DhcpPacket.DHCP_MESSAGE_TYPE_DISCOVER -import android.net.dhcp.DhcpPacket.DHCP_MESSAGE_TYPE_REQUEST -import android.net.dhcp.DhcpRequestPacket -import android.os.Build -import android.os.HandlerThread -import android.platform.test.annotations.AppModeFull -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.runner.AndroidJUnit4 -import com.android.net.module.util.Inet4AddressUtils.getBroadcastAddress -import com.android.net.module.util.Inet4AddressUtils.getPrefixMaskAsInet4Address -import com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY -import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DhcpClientPacketFilter -import com.android.testutils.DhcpOptionFilter -import com.android.testutils.RecorderCallback.CallbackEntry -import com.android.testutils.TapPacketReader -import com.android.testutils.TestHttpServer -import com.android.testutils.TestableNetworkCallback -import com.android.testutils.runAsShell -import fi.iki.elonen.NanoHTTPD.Response.Status -import org.junit.After -import org.junit.Assume.assumeFalse -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import java.net.Inet4Address -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertTrue -import kotlin.test.fail - -private const val MAX_PACKET_LENGTH = 1500 -private const val TEST_TIMEOUT_MS = 10_000L - -private const val TEST_LEASE_TIMEOUT_SECS = 3600 * 12 -private const val TEST_PREFIX_LENGTH = 24 - -private const val TEST_LOGIN_URL = "https://login.capport.android.com" -private const val TEST_VENUE_INFO_URL = "https://venueinfo.capport.android.com" -private const val TEST_DOMAIN_NAME = "lan" -private const val TEST_MTU = 1500.toShort() - -@AppModeFull(reason = "Instant apps cannot create test networks") -@RunWith(AndroidJUnit4::class) -class NetworkValidationTest { - @JvmField - @Rule - val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.Q) - - private val context by lazy { InstrumentationRegistry.getInstrumentation().context } - private val tnm by lazy { context.assertHasService(TestNetworkManager::class.java) } - private val eth by lazy { context.assertHasService(EthernetManager::class.java) } - private val cm by lazy { context.assertHasService(ConnectivityManager::class.java) } - - private val handlerThread = HandlerThread(NetworkValidationTest::class.java.simpleName) - private val serverIpAddr = InetAddresses.parseNumericAddress("192.0.2.222") as Inet4Address - private val clientIpAddr = InetAddresses.parseNumericAddress("192.0.2.111") as Inet4Address - private val httpServer = TestHttpServer() - private val ethRequest = NetworkRequest.Builder() - // ETHERNET|TEST transport networks do not have NET_CAPABILITY_TRUSTED - .removeCapability(NET_CAPABILITY_TRUSTED) - .addTransportType(TRANSPORT_ETHERNET) - .addTransportType(TRANSPORT_TEST).build() - private val ethRequestCb = TestableNetworkCallback() - - private lateinit var iface: TestNetworkInterface - private lateinit var reader: TapPacketReader - private lateinit var capportUrl: Uri - - private var testSkipped = false - - @Before - fun setUp() { - // This test requires using a tap interface as an ethernet interface. - val pm = context.getPackageManager() - testSkipped = !pm.hasSystemFeature(PackageManager.FEATURE_ETHERNET) && - context.getSystemService(EthernetManager::class.java) == null - assumeFalse(testSkipped) - - // Register a request so the network does not get torn down - cm.requestNetwork(ethRequest, ethRequestCb) - runAsShell(NETWORK_SETTINGS, MANAGE_TEST_NETWORKS) { - eth.setIncludeTestInterfaces(true) - // Keeping a reference to the test interface also makes sure the ParcelFileDescriptor - // does not go out of scope, which would cause it to close the underlying FileDescriptor - // in its finalizer. - iface = tnm.createTapInterface() - } - - handlerThread.start() - reader = TapPacketReader( - handlerThread.threadHandler, - iface.fileDescriptor.fileDescriptor, - MAX_PACKET_LENGTH) - reader.startAsyncForTest() - httpServer.start() - - // Pad the listening port to make sure it is always of length 5. This ensures the URL has - // always the same length so the test can use constant IP and UDP header lengths. - // The maximum port number is 65535 so a length of 5 is always enough. - capportUrl = Uri.parse("http://localhost:${httpServer.listeningPort}/testapi.html?par=val") - } - - @After - fun tearDown() { - if (testSkipped) return - cm.unregisterNetworkCallback(ethRequestCb) - - runAsShell(NETWORK_SETTINGS) { eth.setIncludeTestInterfaces(false) } - - httpServer.stop() - handlerThread.threadHandler.post { reader.stop() } - handlerThread.quitSafely() - - iface.fileDescriptor.close() - } - - @Test - fun testCapportApiCallbacks() { - httpServer.addResponse(capportUrl, Status.OK, content = """ - |{ - | "captive": true, - | "user-portal-url": "$TEST_LOGIN_URL", - | "venue-info-url": "$TEST_VENUE_INFO_URL" - |} - """.trimMargin()) - - // Handle the DHCP handshake that includes the capport API URL - val discover = reader.assertDhcpPacketReceived( - DhcpDiscoverPacket::class.java, TEST_TIMEOUT_MS, DHCP_MESSAGE_TYPE_DISCOVER) - reader.sendResponse(makeOfferPacket(discover.clientMac, discover.transactionId)) - - val request = reader.assertDhcpPacketReceived( - DhcpRequestPacket::class.java, TEST_TIMEOUT_MS, DHCP_MESSAGE_TYPE_REQUEST) - assertEquals(discover.transactionId, request.transactionId) - assertEquals(clientIpAddr, request.mRequestedIp) - reader.sendResponse(makeAckPacket(request.clientMac, request.transactionId)) - - // The first request received by the server should be for the portal API - assertTrue(httpServer.requestsRecord.poll(TEST_TIMEOUT_MS, 0)?.matches(capportUrl) ?: false, - "The device did not fetch captive portal API data within timeout") - - // Expect network callbacks with capport info - val testCb = TestableNetworkCallback(TEST_TIMEOUT_MS) - // LinkProperties do not contain captive portal info if the callback is registered without - // NETWORK_SETTINGS permissions. - val lp = runAsShell(NETWORK_SETTINGS) { - cm.registerNetworkCallback(ethRequest, testCb) - - try { - val ncCb = testCb.eventuallyExpect { - it.caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) - } - testCb.eventuallyExpect { - it.network == ncCb.network && it.lp.captivePortalData != null - }.lp - } finally { - cm.unregisterNetworkCallback(testCb) - } - } - - assertEquals(capportUrl, lp.captivePortalApiUrl) - with(lp.captivePortalData) { - assertNotNull(this) - assertTrue(isCaptive) - assertEquals(Uri.parse(TEST_LOGIN_URL), userPortalUrl) - assertEquals(Uri.parse(TEST_VENUE_INFO_URL), venueInfoUrl) - } - } - - private fun makeOfferPacket(clientMac: ByteArray, transactionId: Int) = - DhcpPacket.buildOfferPacket(DhcpPacket.ENCAP_L2, transactionId, - false /* broadcast */, serverIpAddr, IPV4_ADDR_ANY /* relayIp */, clientIpAddr, - clientMac, TEST_LEASE_TIMEOUT_SECS, - getPrefixMaskAsInet4Address(TEST_PREFIX_LENGTH), - getBroadcastAddress(clientIpAddr, TEST_PREFIX_LENGTH), - listOf(serverIpAddr) /* gateways */, listOf(serverIpAddr) /* dnsServers */, - serverIpAddr, TEST_DOMAIN_NAME, null /* hostname */, true /* metered */, - TEST_MTU, capportUrl.toString()) - - private fun makeAckPacket(clientMac: ByteArray, transactionId: Int) = - DhcpPacket.buildAckPacket(DhcpPacket.ENCAP_L2, transactionId, - false /* broadcast */, serverIpAddr, IPV4_ADDR_ANY /* relayIp */, clientIpAddr, - clientIpAddr /* requestClientIp */, clientMac, TEST_LEASE_TIMEOUT_SECS, - getPrefixMaskAsInet4Address(TEST_PREFIX_LENGTH), - getBroadcastAddress(clientIpAddr, TEST_PREFIX_LENGTH), - listOf(serverIpAddr) /* gateways */, listOf(serverIpAddr) /* dnsServers */, - serverIpAddr, TEST_DOMAIN_NAME, null /* hostname */, true /* metered */, - TEST_MTU, false /* rapidCommit */, capportUrl.toString()) -} - -private fun TapPacketReader.assertDhcpPacketReceived( - packetType: Class, - timeoutMs: Long, - type: Byte -): T { - val packetBytes = poll(timeoutMs, DhcpClientPacketFilter() - .and(DhcpOptionFilter(DHCP_MESSAGE_TYPE, type))) - ?: fail("${packetType.simpleName} not received within timeout") - val packet = DhcpPacket.decodeFullPacket(packetBytes, packetBytes.size, DhcpPacket.ENCAP_L2) - assertTrue(packetType.isInstance(packet), - "Expected ${packetType.simpleName} but got ${packet.javaClass.simpleName}") - return packetType.cast(packet) -} - -private fun Context.assertHasService(manager: Class): T { - return getSystemService(manager) ?: fail("Service $manager not found") -} diff --git a/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt b/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt deleted file mode 100644 index f6fc75b5f4..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.cts - -import android.Manifest -import android.net.util.NetworkStackUtils -import android.provider.DeviceConfig -import com.android.testutils.runAsShell - -/** - * Collection of utility methods for configuring network validation. - */ -internal object NetworkValidationTestUtil { - - /** - * Clear the test network validation URLs. - */ - fun clearValidationTestUrlsDeviceConfig() { - setHttpsUrlDeviceConfig(null) - setHttpUrlDeviceConfig(null) - setUrlExpirationDeviceConfig(null) - } - - /** - * Set the test validation HTTPS URL. - * - * @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL - */ - fun setHttpsUrlDeviceConfig(url: String?) = - setConfig(NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL, url) - - /** - * Set the test validation HTTP URL. - * - * @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL - */ - fun setHttpUrlDeviceConfig(url: String?) = - setConfig(NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL, url) - - /** - * Set the test validation URL expiration. - * - * @see NetworkStackUtils.TEST_URL_EXPIRATION_TIME - */ - fun setUrlExpirationDeviceConfig(timestamp: Long?) = - setConfig(NetworkStackUtils.TEST_URL_EXPIRATION_TIME, timestamp?.toString()) - - private fun setConfig(configKey: String, value: String?) { - runAsShell(Manifest.permission.WRITE_DEVICE_CONFIG) { - DeviceConfig.setProperty( - DeviceConfig.NAMESPACE_CONNECTIVITY, configKey, value, false /* makeDefault */) - } - } -} \ No newline at end of file diff --git a/tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java b/tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java deleted file mode 100644 index 81a9e30dd5..0000000000 --- a/tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2018 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.cts; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assume.assumeTrue; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.platform.test.annotations.AppModeFull; -import android.os.FileUtils; -import android.os.ParcelFileDescriptor; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.compatibility.common.util.ApiLevelUtil; -import com.android.compatibility.common.util.SystemUtil; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Formatter; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class NetworkWatchlistTest { - - private static final String TEST_WATCHLIST_XML = "assets/network_watchlist_config_for_test.xml"; - private static final String TEST_EMPTY_WATCHLIST_XML = - "assets/network_watchlist_config_empty_for_test.xml"; - private static final String TMP_CONFIG_PATH = - "/data/local/tmp/network_watchlist_config_for_test.xml"; - // Generated from sha256sum network_watchlist_config_for_test.xml - private static final String TEST_WATCHLIST_CONFIG_HASH = - "B5FC4636994180D54E1E912F78178AB1D8BD2BE71D90CA9F5BBC3284E4D04ED4"; - - private ConnectivityManager mConnectivityManager; - private boolean mHasFeature; - - @Before - public void setUp() throws Exception { - mHasFeature = isAtLeastP(); - mConnectivityManager = - (ConnectivityManager) InstrumentationRegistry.getContext().getSystemService( - Context.CONNECTIVITY_SERVICE); - assumeTrue(mHasFeature); - // Set empty watchlist test config before testing - setWatchlistConfig(TEST_EMPTY_WATCHLIST_XML); - // Verify test watchlist config is not set before testing - byte[] result = mConnectivityManager.getNetworkWatchlistConfigHash(); - assertNotNull("Watchlist config does not exist", result); - assertNotEquals(TEST_WATCHLIST_CONFIG_HASH, byteArrayToHexString(result)); - } - - @After - public void tearDown() throws Exception { - if (mHasFeature) { - // Set empty watchlist test config after testing - setWatchlistConfig(TEST_EMPTY_WATCHLIST_XML); - } - } - - private void cleanup() throws IOException { - runCommand("rm " + TMP_CONFIG_PATH); - } - - private boolean isAtLeastP() throws Exception { - // TODO: replace with ApiLevelUtil.isAtLeast(Build.VERSION_CODES.P) when the P API level - // constant is defined. - return ApiLevelUtil.getCodename().compareToIgnoreCase("P") >= 0; - } - - /** - * Test if ConnectivityManager.getNetworkWatchlistConfigHash() correctly - * returns the hash of config we set. - */ - @Test - @AppModeFull(reason = "Cannot access resource file in instant app mode") - public void testGetWatchlistConfigHash() throws Exception { - // Set watchlist config file for test - setWatchlistConfig(TEST_WATCHLIST_XML); - // Test if watchlist config hash value is correct - byte[] result = mConnectivityManager.getNetworkWatchlistConfigHash(); - Assert.assertEquals(TEST_WATCHLIST_CONFIG_HASH, byteArrayToHexString(result)); - } - - private static String byteArrayToHexString(byte[] bytes) { - Formatter formatter = new Formatter(); - for (byte b : bytes) { - formatter.format("%02X", b); - } - return formatter.toString(); - } - - private void saveResourceToFile(String res, String filePath) throws IOException { - // App can't access /data/local/tmp directly, so we pipe resource to file through stdin. - ParcelFileDescriptor stdin = pipeFromStdin(filePath); - pipeResourceToFileDescriptor(res, stdin); - } - - /* Pipe stdin to a file in filePath. Returns PFD for stdin. */ - private ParcelFileDescriptor pipeFromStdin(String filePath) { - // Not all devices have symlink for /dev/stdin, so use /proc/self/fd/0 directly. - // /dev/stdin maps to /proc/self/fd/0. - return runRwCommand("cp /proc/self/fd/0 " + filePath)[1]; - } - - private void pipeResourceToFileDescriptor(String res, ParcelFileDescriptor pfd) - throws IOException { - InputStream resStream = getClass().getClassLoader().getResourceAsStream(res); - FileOutputStream fdStream = new ParcelFileDescriptor.AutoCloseOutputStream(pfd); - - FileUtils.copy(resStream, fdStream); - - try { - fdStream.close(); - } catch (IOException e) { - } - } - - private static String runCommand(String command) throws IOException { - return SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), command); - } - - private static ParcelFileDescriptor[] runRwCommand(String command) { - return InstrumentationRegistry.getInstrumentation() - .getUiAutomation().executeShellCommandRw(command); - } - - private void setWatchlistConfig(String watchlistConfigFile) throws Exception { - cleanup(); - saveResourceToFile(watchlistConfigFile, TMP_CONFIG_PATH); - final String cmdResult = runCommand( - "cmd network_watchlist set-test-config " + TMP_CONFIG_PATH).trim(); - assertThat(cmdResult).contains("Success"); - cleanup(); - } -} diff --git a/tests/cts/net/src/android/net/cts/PacketUtils.java b/tests/cts/net/src/android/net/cts/PacketUtils.java deleted file mode 100644 index 0aedecb5ad..0000000000 --- a/tests/cts/net/src/android/net/cts/PacketUtils.java +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright (C) 2018 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.cts; - -import static android.system.OsConstants.IPPROTO_IPV6; -import static android.system.OsConstants.IPPROTO_UDP; - -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.nio.ShortBuffer; -import java.security.GeneralSecurityException; -import java.security.SecureRandom; -import java.util.Arrays; - -import javax.crypto.Cipher; -import javax.crypto.Mac; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -public class PacketUtils { - private static final String TAG = PacketUtils.class.getSimpleName(); - - private static final int DATA_BUFFER_LEN = 4096; - - static final int IP4_HDRLEN = 20; - static final int IP6_HDRLEN = 40; - static final int UDP_HDRLEN = 8; - static final int TCP_HDRLEN = 20; - static final int TCP_HDRLEN_WITH_TIMESTAMP_OPT = TCP_HDRLEN + 12; - - // Not defined in OsConstants - static final int IPPROTO_IPV4 = 4; - static final int IPPROTO_ESP = 50; - - // Encryption parameters - static final int AES_GCM_IV_LEN = 8; - static final int AES_CBC_IV_LEN = 16; - static final int AES_GCM_BLK_SIZE = 4; - static final int AES_CBC_BLK_SIZE = 16; - - // Encryption algorithms - static final String AES = "AES"; - static final String AES_CBC = "AES/CBC/NoPadding"; - static final String HMAC_SHA_256 = "HmacSHA256"; - - public interface Payload { - byte[] getPacketBytes(IpHeader header) throws Exception; - - void addPacketBytes(IpHeader header, ByteBuffer resultBuffer) throws Exception; - - short length(); - - int getProtocolId(); - } - - public abstract static class IpHeader { - - public final byte proto; - public final InetAddress srcAddr; - public final InetAddress dstAddr; - public final Payload payload; - - public IpHeader(int proto, InetAddress src, InetAddress dst, Payload payload) { - this.proto = (byte) proto; - this.srcAddr = src; - this.dstAddr = dst; - this.payload = payload; - } - - public abstract byte[] getPacketBytes() throws Exception; - - public abstract int getProtocolId(); - } - - public static class Ip4Header extends IpHeader { - private short checksum; - - public Ip4Header(int proto, Inet4Address src, Inet4Address dst, Payload payload) { - super(proto, src, dst, payload); - } - - public byte[] getPacketBytes() throws Exception { - ByteBuffer resultBuffer = buildHeader(); - payload.addPacketBytes(this, resultBuffer); - - return getByteArrayFromBuffer(resultBuffer); - } - - public ByteBuffer buildHeader() { - ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN); - - // Version, IHL - bb.put((byte) (0x45)); - - // DCSP, ECN - bb.put((byte) 0); - - // Total Length - bb.putShort((short) (IP4_HDRLEN + payload.length())); - - // Empty for Identification, Flags and Fragment Offset - bb.putShort((short) 0); - bb.put((byte) 0x40); - bb.put((byte) 0x00); - - // TTL - bb.put((byte) 64); - - // Protocol - bb.put(proto); - - // Header Checksum - final int ipChecksumOffset = bb.position(); - bb.putShort((short) 0); - - // Src/Dst addresses - bb.put(srcAddr.getAddress()); - bb.put(dstAddr.getAddress()); - - bb.putShort(ipChecksumOffset, calculateChecksum(bb)); - - return bb; - } - - private short calculateChecksum(ByteBuffer bb) { - int checksum = 0; - - // Calculate sum of 16-bit values, excluding checksum. IPv4 headers are always 32-bit - // aligned, so no special cases needed for unaligned values. - ShortBuffer shortBuffer = ByteBuffer.wrap(getByteArrayFromBuffer(bb)).asShortBuffer(); - while (shortBuffer.hasRemaining()) { - short val = shortBuffer.get(); - - // Wrap as needed - checksum = addAndWrapForChecksum(checksum, val); - } - - return onesComplement(checksum); - } - - public int getProtocolId() { - return IPPROTO_IPV4; - } - } - - public static class Ip6Header extends IpHeader { - public Ip6Header(int nextHeader, Inet6Address src, Inet6Address dst, Payload payload) { - super(nextHeader, src, dst, payload); - } - - public byte[] getPacketBytes() throws Exception { - ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN); - - // Version | Traffic Class (First 4 bits) - bb.put((byte) 0x60); - - // Traffic class (Last 4 bits), Flow Label - bb.put((byte) 0); - bb.put((byte) 0); - bb.put((byte) 0); - - // Payload Length - bb.putShort((short) payload.length()); - - // Next Header - bb.put(proto); - - // Hop Limit - bb.put((byte) 64); - - // Src/Dst addresses - bb.put(srcAddr.getAddress()); - bb.put(dstAddr.getAddress()); - - // Payload - payload.addPacketBytes(this, bb); - - return getByteArrayFromBuffer(bb); - } - - public int getProtocolId() { - return IPPROTO_IPV6; - } - } - - public static class BytePayload implements Payload { - public final byte[] payload; - - public BytePayload(byte[] payload) { - this.payload = payload; - } - - public int getProtocolId() { - return -1; - } - - public byte[] getPacketBytes(IpHeader header) { - ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN); - - addPacketBytes(header, bb); - return getByteArrayFromBuffer(bb); - } - - public void addPacketBytes(IpHeader header, ByteBuffer resultBuffer) { - resultBuffer.put(payload); - } - - public short length() { - return (short) payload.length; - } - } - - public static class UdpHeader implements Payload { - - public final short srcPort; - public final short dstPort; - public final Payload payload; - - public UdpHeader(int srcPort, int dstPort, Payload payload) { - this.srcPort = (short) srcPort; - this.dstPort = (short) dstPort; - this.payload = payload; - } - - public int getProtocolId() { - return IPPROTO_UDP; - } - - public short length() { - return (short) (payload.length() + 8); - } - - public byte[] getPacketBytes(IpHeader header) throws Exception { - ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN); - - addPacketBytes(header, bb); - return getByteArrayFromBuffer(bb); - } - - public void addPacketBytes(IpHeader header, ByteBuffer resultBuffer) throws Exception { - // Source, Destination port - resultBuffer.putShort(srcPort); - resultBuffer.putShort(dstPort); - - // Payload Length - resultBuffer.putShort(length()); - - // Get payload bytes for checksum + payload - ByteBuffer payloadBuffer = ByteBuffer.allocate(DATA_BUFFER_LEN); - payload.addPacketBytes(header, payloadBuffer); - byte[] payloadBytes = getByteArrayFromBuffer(payloadBuffer); - - // Checksum - resultBuffer.putShort(calculateChecksum(header, payloadBytes)); - - // Payload - resultBuffer.put(payloadBytes); - } - - private short calculateChecksum(IpHeader header, byte[] payloadBytes) throws Exception { - int newChecksum = 0; - ShortBuffer srcBuffer = ByteBuffer.wrap(header.srcAddr.getAddress()).asShortBuffer(); - ShortBuffer dstBuffer = ByteBuffer.wrap(header.dstAddr.getAddress()).asShortBuffer(); - - while (srcBuffer.hasRemaining() || dstBuffer.hasRemaining()) { - short val = srcBuffer.hasRemaining() ? srcBuffer.get() : dstBuffer.get(); - - // Wrap as needed - newChecksum = addAndWrapForChecksum(newChecksum, val); - } - - // Add pseudo-header values. Proto is 0-padded, so just use the byte. - newChecksum = addAndWrapForChecksum(newChecksum, header.proto); - newChecksum = addAndWrapForChecksum(newChecksum, length()); - newChecksum = addAndWrapForChecksum(newChecksum, srcPort); - newChecksum = addAndWrapForChecksum(newChecksum, dstPort); - newChecksum = addAndWrapForChecksum(newChecksum, length()); - - ShortBuffer payloadShortBuffer = ByteBuffer.wrap(payloadBytes).asShortBuffer(); - while (payloadShortBuffer.hasRemaining()) { - newChecksum = addAndWrapForChecksum(newChecksum, payloadShortBuffer.get()); - } - if (payload.length() % 2 != 0) { - newChecksum = - addAndWrapForChecksum( - newChecksum, (payloadBytes[payloadBytes.length - 1] << 8)); - } - - return onesComplement(newChecksum); - } - } - - public static class EspHeader implements Payload { - public final int nextHeader; - public final int spi; - public final int seqNum; - public final byte[] key; - public final byte[] payload; - - /** - * Generic constructor for ESP headers. - * - *

For Tunnel mode, payload will be a full IP header + attached payloads - * - *

For Transport mode, payload will be only the attached payloads, but with the checksum - * calculated using the pre-encryption IP header - */ - public EspHeader(int nextHeader, int spi, int seqNum, byte[] key, byte[] payload) { - this.nextHeader = nextHeader; - this.spi = spi; - this.seqNum = seqNum; - this.key = key; - this.payload = payload; - } - - public int getProtocolId() { - return IPPROTO_ESP; - } - - public short length() { - // ALWAYS uses AES-CBC, HMAC-SHA256 (128b trunc len) - return (short) - calculateEspPacketSize(payload.length, AES_CBC_IV_LEN, AES_CBC_BLK_SIZE, 128); - } - - public byte[] getPacketBytes(IpHeader header) throws Exception { - ByteBuffer bb = ByteBuffer.allocate(DATA_BUFFER_LEN); - - addPacketBytes(header, bb); - return getByteArrayFromBuffer(bb); - } - - public void addPacketBytes(IpHeader header, ByteBuffer resultBuffer) throws Exception { - ByteBuffer espPayloadBuffer = ByteBuffer.allocate(DATA_BUFFER_LEN); - espPayloadBuffer.putInt(spi); - espPayloadBuffer.putInt(seqNum); - espPayloadBuffer.put(getCiphertext(key)); - - espPayloadBuffer.put(getIcv(getByteArrayFromBuffer(espPayloadBuffer)), 0, 16); - resultBuffer.put(getByteArrayFromBuffer(espPayloadBuffer)); - } - - private byte[] getIcv(byte[] authenticatedSection) throws GeneralSecurityException { - Mac sha256HMAC = Mac.getInstance(HMAC_SHA_256); - SecretKeySpec authKey = new SecretKeySpec(key, HMAC_SHA_256); - sha256HMAC.init(authKey); - - return sha256HMAC.doFinal(authenticatedSection); - } - - /** - * Encrypts and builds ciphertext block. Includes the IV, Padding and Next-Header blocks - * - *

The ciphertext does NOT include the SPI/Sequence numbers, or the ICV. - */ - private byte[] getCiphertext(byte[] key) throws GeneralSecurityException { - int paddedLen = calculateEspEncryptedLength(payload.length, AES_CBC_BLK_SIZE); - ByteBuffer paddedPayload = ByteBuffer.allocate(paddedLen); - paddedPayload.put(payload); - - // Add padding - consecutive integers from 0x01 - int pad = 1; - while (paddedPayload.position() < paddedPayload.limit()) { - paddedPayload.put((byte) pad++); - } - - paddedPayload.position(paddedPayload.limit() - 2); - paddedPayload.put((byte) (paddedLen - 2 - payload.length)); // Pad length - paddedPayload.put((byte) nextHeader); - - // Generate Initialization Vector - byte[] iv = new byte[AES_CBC_IV_LEN]; - new SecureRandom().nextBytes(iv); - IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); - SecretKeySpec secretKeySpec = new SecretKeySpec(key, AES); - - // Encrypt payload - Cipher cipher = Cipher.getInstance(AES_CBC); - cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); - byte[] encrypted = cipher.doFinal(getByteArrayFromBuffer(paddedPayload)); - - // Build ciphertext - ByteBuffer cipherText = ByteBuffer.allocate(AES_CBC_IV_LEN + encrypted.length); - cipherText.put(iv); - cipherText.put(encrypted); - - return getByteArrayFromBuffer(cipherText); - } - } - - private static int addAndWrapForChecksum(int currentChecksum, int value) { - currentChecksum += value & 0x0000ffff; - - // Wrap anything beyond the first 16 bits, and add to lower order bits - return (currentChecksum >>> 16) + (currentChecksum & 0x0000ffff); - } - - private static short onesComplement(int val) { - val = (val >>> 16) + (val & 0xffff); - - if (val == 0) return 0; - return (short) ((~val) & 0xffff); - } - - public static int calculateEspPacketSize( - int payloadLen, int cryptIvLength, int cryptBlockSize, int authTruncLen) { - final int ESP_HDRLEN = 4 + 4; // SPI + Seq# - final int ICV_LEN = authTruncLen / 8; // Auth trailer; based on truncation length - payloadLen += cryptIvLength; // Initialization Vector - - // Align to block size of encryption algorithm - payloadLen = calculateEspEncryptedLength(payloadLen, cryptBlockSize); - return payloadLen + ESP_HDRLEN + ICV_LEN; - } - - private static int calculateEspEncryptedLength(int payloadLen, int cryptBlockSize) { - payloadLen += 2; // ESP trailer - - // Align to block size of encryption algorithm - return payloadLen + calculateEspPadLen(payloadLen, cryptBlockSize); - } - - private static int calculateEspPadLen(int payloadLen, int cryptBlockSize) { - return (cryptBlockSize - (payloadLen % cryptBlockSize)) % cryptBlockSize; - } - - private static byte[] getByteArrayFromBuffer(ByteBuffer buffer) { - return Arrays.copyOfRange(buffer.array(), 0, buffer.position()); - } - - public static IpHeader getIpHeader( - int protocol, InetAddress src, InetAddress dst, Payload payload) { - if ((src instanceof Inet6Address) != (dst instanceof Inet6Address)) { - throw new IllegalArgumentException("Invalid src/dst address combination"); - } - - if (src instanceof Inet6Address) { - return new Ip6Header(protocol, (Inet6Address) src, (Inet6Address) dst, payload); - } else { - return new Ip4Header(protocol, (Inet4Address) src, (Inet4Address) dst, payload); - } - } - - /* - * Debug printing - */ - private static final char[] hexArray = "0123456789ABCDEF".toCharArray(); - - public static String bytesToHex(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) { - sb.append(hexArray[b >>> 4]); - sb.append(hexArray[b & 0x0F]); - sb.append(' '); - } - return sb.toString(); - } -} diff --git a/tests/cts/net/src/android/net/cts/ProxyInfoTest.java b/tests/cts/net/src/android/net/cts/ProxyInfoTest.java deleted file mode 100644 index 1c5624ce38..0000000000 --- a/tests/cts/net/src/android/net/cts/ProxyInfoTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2019 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.cts; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import android.net.ProxyInfo; -import android.net.Uri; -import android.os.Build; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -@RunWith(AndroidJUnit4.class) -public final class ProxyInfoTest { - private static final String TEST_HOST = "test.example.com"; - private static final int TEST_PORT = 5566; - private static final Uri TEST_URI = Uri.parse("https://test.example.com"); - // This matches android.net.ProxyInfo#LOCAL_EXCL_LIST - private static final String LOCAL_EXCL_LIST = ""; - // This matches android.net.ProxyInfo#LOCAL_HOST - private static final String LOCAL_HOST = "localhost"; - // This matches android.net.ProxyInfo#LOCAL_PORT - private static final int LOCAL_PORT = -1; - - @Rule - public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); - - @Test - public void testConstructor() { - final ProxyInfo proxy = new ProxyInfo((ProxyInfo) null); - checkEmpty(proxy); - - assertEquals(proxy, new ProxyInfo(proxy)); - } - - @Test - public void testBuildDirectProxy() { - final ProxyInfo proxy1 = ProxyInfo.buildDirectProxy(TEST_HOST, TEST_PORT); - - assertEquals(TEST_HOST, proxy1.getHost()); - assertEquals(TEST_PORT, proxy1.getPort()); - assertArrayEquals(new String[0], proxy1.getExclusionList()); - assertEquals(Uri.EMPTY, proxy1.getPacFileUrl()); - - final List exclList = new ArrayList<>(); - exclList.add("localhost"); - exclList.add("*.exclusion.com"); - final ProxyInfo proxy2 = ProxyInfo.buildDirectProxy(TEST_HOST, TEST_PORT, exclList); - - assertEquals(TEST_HOST, proxy2.getHost()); - assertEquals(TEST_PORT, proxy2.getPort()); - assertArrayEquals(exclList.toArray(new String[0]), proxy2.getExclusionList()); - assertEquals(Uri.EMPTY, proxy2.getPacFileUrl()); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) - public void testBuildPacProxy() { - final ProxyInfo proxy1 = ProxyInfo.buildPacProxy(TEST_URI); - - assertEquals(LOCAL_HOST, proxy1.getHost()); - assertEquals(LOCAL_PORT, proxy1.getPort()); - assertArrayEquals(LOCAL_EXCL_LIST.toLowerCase(Locale.ROOT).split(","), - proxy1.getExclusionList()); - assertEquals(TEST_URI, proxy1.getPacFileUrl()); - - final ProxyInfo proxy2 = ProxyInfo.buildPacProxy(TEST_URI, TEST_PORT); - - assertEquals(LOCAL_HOST, proxy2.getHost()); - assertEquals(TEST_PORT, proxy2.getPort()); - assertArrayEquals(LOCAL_EXCL_LIST.toLowerCase(Locale.ROOT).split(","), - proxy2.getExclusionList()); - assertEquals(TEST_URI, proxy2.getPacFileUrl()); - } - - @Test - public void testIsValid() { - final ProxyInfo proxy1 = ProxyInfo.buildDirectProxy(TEST_HOST, TEST_PORT); - assertTrue(proxy1.isValid()); - - // Given empty host - final ProxyInfo proxy2 = ProxyInfo.buildDirectProxy("", TEST_PORT); - assertFalse(proxy2.isValid()); - // Given invalid host - final ProxyInfo proxy3 = ProxyInfo.buildDirectProxy(".invalid.com", TEST_PORT); - assertFalse(proxy3.isValid()); - // Given invalid port. - final ProxyInfo proxy4 = ProxyInfo.buildDirectProxy(TEST_HOST, 0); - assertFalse(proxy4.isValid()); - // Given another invalid port - final ProxyInfo proxy5 = ProxyInfo.buildDirectProxy(TEST_HOST, 65536); - assertFalse(proxy5.isValid()); - // Given invalid exclusion list - final List exclList = new ArrayList<>(); - exclList.add(".invalid.com"); - exclList.add("%.test.net"); - final ProxyInfo proxy6 = ProxyInfo.buildDirectProxy(TEST_HOST, TEST_PORT, exclList); - assertFalse(proxy6.isValid()); - } - - private void checkEmpty(ProxyInfo proxy) { - assertNull(proxy.getHost()); - assertEquals(0, proxy.getPort()); - assertNull(proxy.getExclusionList()); - assertEquals(Uri.EMPTY, proxy.getPacFileUrl()); - } -} diff --git a/tests/cts/net/src/android/net/cts/ProxyTest.java b/tests/cts/net/src/android/net/cts/ProxyTest.java deleted file mode 100644 index 467d12f9dc..0000000000 --- a/tests/cts/net/src/android/net/cts/ProxyTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2009 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.cts; - - -import android.net.Proxy; -import android.test.AndroidTestCase; - -public class ProxyTest extends AndroidTestCase { - - public void testConstructor() { - new Proxy(); - } - - public void testAccessProperties() { - final int minValidPort = 0; - final int maxValidPort = 65535; - int defaultPort = Proxy.getDefaultPort(); - if(null == Proxy.getDefaultHost()) { - assertEquals(-1, defaultPort); - } else { - assertTrue(defaultPort >= minValidPort && defaultPort <= maxValidPort); - } - } -} diff --git a/tests/cts/net/src/android/net/cts/RssiCurveTest.java b/tests/cts/net/src/android/net/cts/RssiCurveTest.java deleted file mode 100644 index d651b7186b..0000000000 --- a/tests/cts/net/src/android/net/cts/RssiCurveTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.cts; - -import static com.google.common.truth.Truth.assertThat; - -import android.net.RssiCurve; - -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** CTS tests for {@link RssiCurve}. */ -@RunWith(AndroidJUnit4.class) -public class RssiCurveTest { - - @Test - public void lookupScore_constantCurve() { - // One bucket from rssi=-100 to 100 with score 10. - RssiCurve curve = new RssiCurve(-100, 200, new byte[] { 10 }); - assertThat(curve.lookupScore(-200)).isEqualTo(10); - assertThat(curve.lookupScore(-100)).isEqualTo(10); - assertThat(curve.lookupScore(0)).isEqualTo(10); - assertThat(curve.lookupScore(100)).isEqualTo(10); - assertThat(curve.lookupScore(200)).isEqualTo(10); - } - - @Test - public void lookupScore_changingCurve() { - // One bucket from -100 to 0 with score -10, and one bucket from 0 to 100 with score 10. - RssiCurve curve = new RssiCurve(-100, 100, new byte[] { -10, 10 }); - assertThat(curve.lookupScore(-200)).isEqualTo(-10); - assertThat(curve.lookupScore(-100)).isEqualTo(-10); - assertThat(curve.lookupScore(-50)).isEqualTo(-10); - assertThat(curve.lookupScore(0)).isEqualTo(10); - assertThat(curve.lookupScore(50)).isEqualTo(10); - assertThat(curve.lookupScore(100)).isEqualTo(10); - assertThat(curve.lookupScore(200)).isEqualTo(10); - } - - @Test - public void lookupScore_linearCurve() { - // Curve starting at -110, with 15 buckets of width 10 whose scores increases by 10 with - // each bucket. The current active network gets a boost of 15 to its RSSI. - RssiCurve curve = new RssiCurve( - -110, - 10, - new byte[] { -20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 }, - 15); - - assertThat(curve.lookupScore(-120)).isEqualTo(-20); - assertThat(curve.lookupScore(-120, false)).isEqualTo(-20); - assertThat(curve.lookupScore(-120, true)).isEqualTo(-20); - - assertThat(curve.lookupScore(-111)).isEqualTo(-20); - assertThat(curve.lookupScore(-111, false)).isEqualTo(-20); - assertThat(curve.lookupScore(-111, true)).isEqualTo(-10); - - assertThat(curve.lookupScore(-110)).isEqualTo(-20); - assertThat(curve.lookupScore(-110, false)).isEqualTo(-20); - assertThat(curve.lookupScore(-110, true)).isEqualTo(-10); - - assertThat(curve.lookupScore(-105)).isEqualTo(-20); - assertThat(curve.lookupScore(-105, false)).isEqualTo(-20); - assertThat(curve.lookupScore(-105, true)).isEqualTo(0); - - assertThat(curve.lookupScore(-100)).isEqualTo(-10); - assertThat(curve.lookupScore(-100, false)).isEqualTo(-10); - assertThat(curve.lookupScore(-100, true)).isEqualTo(0); - - assertThat(curve.lookupScore(-50)).isEqualTo(40); - assertThat(curve.lookupScore(-50, false)).isEqualTo(40); - assertThat(curve.lookupScore(-50, true)).isEqualTo(50); - - assertThat(curve.lookupScore(0)).isEqualTo(90); - assertThat(curve.lookupScore(0, false)).isEqualTo(90); - assertThat(curve.lookupScore(0, true)).isEqualTo(100); - - assertThat(curve.lookupScore(30)).isEqualTo(120); - assertThat(curve.lookupScore(30, false)).isEqualTo(120); - assertThat(curve.lookupScore(30, true)).isEqualTo(120); - - assertThat(curve.lookupScore(40)).isEqualTo(120); - assertThat(curve.lookupScore(40, false)).isEqualTo(120); - assertThat(curve.lookupScore(40, true)).isEqualTo(120); - } -} diff --git a/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java b/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java deleted file mode 100644 index cbe54f8036..0000000000 --- a/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2008 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.cts; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.net.SSLCertificateSocketFactory; -import android.platform.test.annotations.AppModeFull; -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSession; -import libcore.javax.net.ssl.SSLConfigurationAsserts; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class SSLCertificateSocketFactoryTest { - // TEST_HOST should point to a web server with a valid TLS certificate. - private static final String TEST_HOST = "www.google.com"; - private static final int HTTPS_PORT = 443; - private HostnameVerifier mDefaultVerifier; - private SSLCertificateSocketFactory mSocketFactory; - private InetAddress mLocalAddress; - // InetAddress obtained by resolving TEST_HOST. - private InetAddress mTestHostAddress; - // SocketAddress combining mTestHostAddress and HTTPS_PORT. - private List mTestSocketAddresses; - - @Before - public void setUp() { - // Expected state before each test method is that - // HttpsURLConnection.getDefaultHostnameVerifier() will return the system default. - mDefaultVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); - mSocketFactory = (SSLCertificateSocketFactory) - SSLCertificateSocketFactory.getDefault(1000 /* handshakeTimeoutMillis */); - assertNotNull(mSocketFactory); - InetAddress[] addresses; - try { - addresses = InetAddress.getAllByName(TEST_HOST); - mTestHostAddress = addresses[0]; - } catch (UnknownHostException uhe) { - throw new AssertionError( - "Unable to test SSLCertificateSocketFactory: cannot resolve " + TEST_HOST, uhe); - } - - mTestSocketAddresses = Arrays.stream(addresses) - .map(addr -> new InetSocketAddress(addr, HTTPS_PORT)) - .collect(Collectors.toList()); - - // Find the local IP address which will be used to connect to TEST_HOST. - try { - Socket testSocket = new Socket(TEST_HOST, HTTPS_PORT); - mLocalAddress = testSocket.getLocalAddress(); - testSocket.close(); - } catch (IOException ioe) { - throw new AssertionError("" - + "Unable to test SSLCertificateSocketFactory: cannot connect to " - + TEST_HOST, ioe); - } - } - - // Restore the system default hostname verifier after each test. - @After - public void restoreDefaultHostnameVerifier() { - HttpsURLConnection.setDefaultHostnameVerifier(mDefaultVerifier); - } - - @Test - public void testDefaultConfiguration() throws Exception { - SSLConfigurationAsserts.assertSSLSocketFactoryDefaultConfiguration(mSocketFactory); - } - - @Test - public void testAccessProperties() { - mSocketFactory.getSupportedCipherSuites(); - mSocketFactory.getDefaultCipherSuites(); - } - - /** - * Tests the {@code createSocket()} cases which are expected to fail with {@code IOException}. - */ - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void createSocket_io_error_expected() { - // Connect to the localhost HTTPS port. Should result in connection refused IOException - // because no service should be listening on that port. - InetAddress localhostAddress = InetAddress.getLoopbackAddress(); - try { - mSocketFactory.createSocket(localhostAddress, HTTPS_PORT); - fail(); - } catch (IOException e) { - // expected - } - - // Same, but also binding to a local address. - try { - mSocketFactory.createSocket(localhostAddress, HTTPS_PORT, localhostAddress, 0); - fail(); - } catch (IOException e) { - // expected - } - - // Same, wrapping an existing plain socket which is in an unconnected state. - try { - Socket socket = new Socket(); - mSocketFactory.createSocket(socket, "localhost", HTTPS_PORT, true); - fail(); - } catch (IOException e) { - // expected - } - } - - /** - * Tests hostname verification for - * {@link SSLCertificateSocketFactory#createSocket(String, int)}. - * - *

This method should return a socket which is fully connected (i.e. TLS handshake complete) - * and whose peer TLS certificate has been verified to have the correct hostname. - * - *

{@link SSLCertificateSocketFactory} is documented to verify hostnames using - * the {@link HostnameVerifier} returned by - * {@link HttpsURLConnection#getDefaultHostnameVerifier}, so this test connects twice, - * once with the system default {@link HostnameVerifier} which is expected to succeed, - * and once after installing a {@link NegativeHostnameVerifier} which will cause - * {@link SSLCertificateSocketFactory#verifyHostname} to throw a - * {@link SSLPeerUnverifiedException}. - * - *

These tests only test the hostname verification logic in SSLCertificateSocketFactory, - * other TLS failure modes and the default HostnameVerifier are tested elsewhere, see - * {@link com.squareup.okhttp.internal.tls.HostnameVerifierTest} and - * https://android.googlesource.com/platform/external/boringssl/+/refs/heads/master/src/ssl/test - * - *

Tests the following behaviour:- - *

    - *
  • TEST_SERVER is available and has a valid TLS certificate - *
  • {@code createSocket()} verifies the remote hostname is correct using - * {@link HttpsURLConnection#getDefaultHostnameVerifier} - *
  • {@link SSLPeerUnverifiedException} is thrown when the remote hostname is invalid - *
- * - *

See also http://b/2807618. - */ - @Test - public void createSocket_simple_with_hostname_verification() throws Exception { - Socket socket = mSocketFactory.createSocket(TEST_HOST, HTTPS_PORT); - assertConnectedSocket(socket); - socket.close(); - - HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier()); - try { - mSocketFactory.createSocket(TEST_HOST, HTTPS_PORT); - fail(); - } catch (SSLPeerUnverifiedException expected) { - // expected - } - } - - /** - * Tests hostname verification for - * {@link SSLCertificateSocketFactory#createSocket(Socket, String, int, boolean)}. - * - *

This method should return a socket which is fully connected (i.e. TLS handshake complete) - * and whose peer TLS certificate has been verified to have the correct hostname. - * - *

The TLS socket returned is wrapped around the plain socket passed into - * {@code createSocket()}. - * - *

See {@link #createSocket_simple_with_hostname_verification()} for test methodology. - */ - @Test - public void createSocket_wrapped_with_hostname_verification() throws Exception { - Socket underlying = new Socket(TEST_HOST, HTTPS_PORT); - Socket socket = mSocketFactory.createSocket(underlying, TEST_HOST, HTTPS_PORT, true); - assertConnectedSocket(socket); - socket.close(); - - HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier()); - try { - underlying = new Socket(TEST_HOST, HTTPS_PORT); - mSocketFactory.createSocket(underlying, TEST_HOST, HTTPS_PORT, true); - fail(); - } catch (SSLPeerUnverifiedException expected) { - // expected - } - } - - /** - * Tests hostname verification for - * {@link SSLCertificateSocketFactory#createSocket(String, int, InetAddress, int)}. - * - *

This method should return a socket which is fully connected (i.e. TLS handshake complete) - * and whose peer TLS certificate has been verified to have the correct hostname. - * - *

The TLS socket returned is also bound to the local address determined in {@link #setUp} to - * be used for connections to TEST_HOST, and a wildcard port. - * - *

See {@link #createSocket_simple_with_hostname_verification()} for test methodology. - */ - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void createSocket_bound_with_hostname_verification() throws Exception { - Socket socket = mSocketFactory.createSocket(TEST_HOST, HTTPS_PORT, mLocalAddress, 0); - assertConnectedSocket(socket); - socket.close(); - - HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier()); - try { - mSocketFactory.createSocket(TEST_HOST, HTTPS_PORT, mLocalAddress, 0); - fail(); - } catch (SSLPeerUnverifiedException expected) { - // expected - } - } - - /** - * Tests hostname verification for - * {@link SSLCertificateSocketFactory#createSocket(InetAddress, int)}. - * - *

This method should return a socket which the documentation describes as "unconnected", - * which actually means that the socket is fully connected at the TCP layer but TLS handshaking - * and hostname verification have not yet taken place. - * - *

Behaviour is tested by installing a {@link NegativeHostnameVerifier} and by calling - * {@link #assertConnectedSocket} to ensure TLS handshaking but no hostname verification takes - * place. Next, {@link SSLCertificateSocketFactory#verifyHostname} is called to ensure - * that hostname verification is using the {@link HostnameVerifier} returned by - * {@link HttpsURLConnection#getDefaultHostnameVerifier} as documented. - * - *

Tests the following behaviour:- - *

    - *
  • TEST_SERVER is available and has a valid TLS certificate - *
  • {@code createSocket()} does not verify the remote hostname - *
  • Calling {@link SSLCertificateSocketFactory#verifyHostname} on the returned socket - * throws {@link SSLPeerUnverifiedException} if the remote hostname is invalid - *
- */ - @Test - public void createSocket_simple_no_hostname_verification() throws Exception{ - HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier()); - Socket socket = mSocketFactory.createSocket(mTestHostAddress, HTTPS_PORT); - // Need to provide the expected hostname here or the TLS handshake will - // be unable to supply SNI to the remote host. - mSocketFactory.setHostname(socket, TEST_HOST); - assertConnectedSocket(socket); - try { - SSLCertificateSocketFactory.verifyHostname(socket, TEST_HOST); - fail(); - } catch (SSLPeerUnverifiedException expected) { - // expected - } - HttpsURLConnection.setDefaultHostnameVerifier(mDefaultVerifier); - SSLCertificateSocketFactory.verifyHostname(socket, TEST_HOST); - socket.close(); - } - - /** - * Tests hostname verification for - * {@link SSLCertificateSocketFactory#createSocket(InetAddress, int, InetAddress, int)}. - * - *

This method should return a socket which the documentation describes as "unconnected", - * which actually means that the socket is fully connected at the TCP layer but TLS handshaking - * and hostname verification have not yet taken place. - * - *

The TLS socket returned is also bound to the local address determined in {@link #setUp} to - * be used for connections to TEST_HOST, and a wildcard port. - * - *

See {@link #createSocket_simple_no_hostname_verification()} for test methodology. - */ - @Test - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void createSocket_bound_no_hostname_verification() throws Exception{ - HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier()); - Socket socket = - mSocketFactory.createSocket(mTestHostAddress, HTTPS_PORT, mLocalAddress, 0); - // Need to provide the expected hostname here or the TLS handshake will - // be unable to supply SNI to the peer. - mSocketFactory.setHostname(socket, TEST_HOST); - assertConnectedSocket(socket); - try { - SSLCertificateSocketFactory.verifyHostname(socket, TEST_HOST); - fail(); - } catch (SSLPeerUnverifiedException expected) { - // expected - } - HttpsURLConnection.setDefaultHostnameVerifier(mDefaultVerifier); - SSLCertificateSocketFactory.verifyHostname(socket, TEST_HOST); - socket.close(); - } - - /** - * Asserts a socket is fully connected to the expected peer. - * - *

For the variants of createSocket which verify the remote hostname, - * {@code socket} should already be fully connected. - * - *

For the non-verifying variants, retrieving the input stream will trigger a TLS handshake - * and so may throw an exception, for example if the peer's certificate is invalid. - * - *

Does no hostname verification. - */ - private void assertConnectedSocket(Socket socket) throws Exception { - assertNotNull(socket); - assertTrue(socket.isConnected()); - assertNotNull(socket.getInputStream()); - assertNotNull(socket.getOutputStream()); - assertTrue(mTestSocketAddresses.contains(socket.getRemoteSocketAddress())); - } - - /** - * A HostnameVerifier which always returns false to simulate a server returning a - * certificate which does not match the expected hostname. - */ - private static class NegativeHostnameVerifier implements HostnameVerifier { - @Override - public boolean verify(String hostname, SSLSession sslSession) { - return false; - } - } -} diff --git a/tests/cts/net/src/android/net/cts/TheaterModeTest.java b/tests/cts/net/src/android/net/cts/TheaterModeTest.java deleted file mode 100644 index d1ddeaa375..0000000000 --- a/tests/cts/net/src/android/net/cts/TheaterModeTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.cts; - -import android.content.ContentResolver; -import android.content.Context; -import android.platform.test.annotations.AppModeFull; -import android.provider.Settings; -import android.test.AndroidTestCase; -import android.util.Log; - -public class TheaterModeTest extends AndroidTestCase { - private static final String TAG = "TheaterModeTest"; - private static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth"; - private static final String FEATURE_WIFI = "android.hardware.wifi"; - private static final int TIMEOUT_MS = 10 * 1000; - private boolean mHasFeature; - private Context mContext; - private ContentResolver resolver; - - public void setup() { - mContext= getContext(); - resolver = mContext.getContentResolver(); - mHasFeature = (mContext.getPackageManager().hasSystemFeature(FEATURE_BLUETOOTH) - || mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI)); - } - - @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps") - public void testTheaterMode() { - setup(); - if (!mHasFeature) { - Log.i(TAG, "The device doesn't support network bluetooth or wifi feature"); - return; - } - - for (int testCount = 0; testCount < 2; testCount++) { - if (!doOneTest()) { - fail("Theater mode failed to change in " + TIMEOUT_MS + "msec"); - return; - } - } - } - - private boolean doOneTest() { - boolean theaterModeOn = isTheaterModeOn(); - - setTheaterModeOn(!theaterModeOn); - try { - Thread.sleep(TIMEOUT_MS); - } catch (InterruptedException e) { - Log.e(TAG, "Sleep time interrupted.", e); - } - - if (theaterModeOn == isTheaterModeOn()) { - return false; - } - return true; - } - - private void setTheaterModeOn(boolean enabling) { - // Change the system setting for theater mode - Settings.Global.putInt(resolver, Settings.Global.THEATER_MODE_ON, enabling ? 1 : 0); - } - - private boolean isTheaterModeOn() { - // Read the system setting for theater mode - return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.THEATER_MODE_ON, 0) != 0; - } -} diff --git a/tests/cts/net/src/android/net/cts/TrafficStatsTest.java b/tests/cts/net/src/android/net/cts/TrafficStatsTest.java deleted file mode 100755 index 37bdd44fbf..0000000000 --- a/tests/cts/net/src/android/net/cts/TrafficStatsTest.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2010 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.cts; - -import android.net.NetworkStats; -import android.net.TrafficStats; -import android.os.Process; -import android.platform.test.annotations.AppModeFull; -import android.test.AndroidTestCase; -import android.util.Log; -import android.util.Range; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -public class TrafficStatsTest extends AndroidTestCase { - private static final String LOG_TAG = "TrafficStatsTest"; - - /** Verify the given value is in range [lower, upper] */ - private void assertInRange(String tag, long value, long lower, long upper) { - final Range range = new Range(lower, upper); - assertTrue(tag + ": " + value + " is not within range [" + lower + ", " + upper + "]", - range.contains(value)); - } - - public void testValidMobileStats() { - // We can't assume a mobile network is even present in this test, so - // we simply assert that a valid value is returned. - - assertTrue(TrafficStats.getMobileTxPackets() >= 0); - assertTrue(TrafficStats.getMobileRxPackets() >= 0); - assertTrue(TrafficStats.getMobileTxBytes() >= 0); - assertTrue(TrafficStats.getMobileRxBytes() >= 0); - } - - public void testValidTotalStats() { - assertTrue(TrafficStats.getTotalTxPackets() >= 0); - assertTrue(TrafficStats.getTotalRxPackets() >= 0); - assertTrue(TrafficStats.getTotalTxBytes() >= 0); - assertTrue(TrafficStats.getTotalRxBytes() >= 0); - } - - public void testValidPacketStats() { - assertTrue(TrafficStats.getTxPackets("lo") >= 0); - assertTrue(TrafficStats.getRxPackets("lo") >= 0); - } - - public void testThreadStatsTag() throws Exception { - TrafficStats.setThreadStatsTag(0xf00d); - assertTrue("Tag didn't stick", TrafficStats.getThreadStatsTag() == 0xf00d); - - final CountDownLatch latch = new CountDownLatch(1); - - new Thread("TrafficStatsTest.testThreadStatsTag") { - @Override - public void run() { - assertTrue("Tag leaked", TrafficStats.getThreadStatsTag() != 0xf00d); - TrafficStats.setThreadStatsTag(0xcafe); - assertTrue("Tag didn't stick", TrafficStats.getThreadStatsTag() == 0xcafe); - latch.countDown(); - } - }.start(); - - latch.await(5, TimeUnit.SECONDS); - assertTrue("Tag lost", TrafficStats.getThreadStatsTag() == 0xf00d); - - TrafficStats.clearThreadStatsTag(); - assertTrue("Tag not cleared", TrafficStats.getThreadStatsTag() != 0xf00d); - } - - long tcpPacketToIpBytes(long packetCount, long bytes) { - // ip header + tcp header + data. - // Tcp header is mostly 32. Syn has different tcp options -> 40. Don't care. - return packetCount * (20 + 32 + bytes); - } - - @AppModeFull(reason = "Socket cannot bind in instant app mode") - public void testTrafficStatsForLocalhost() throws IOException { - final long mobileTxPacketsBefore = TrafficStats.getMobileTxPackets(); - final long mobileRxPacketsBefore = TrafficStats.getMobileRxPackets(); - final long mobileTxBytesBefore = TrafficStats.getMobileTxBytes(); - final long mobileRxBytesBefore = TrafficStats.getMobileRxBytes(); - final long totalTxPacketsBefore = TrafficStats.getTotalTxPackets(); - final long totalRxPacketsBefore = TrafficStats.getTotalRxPackets(); - final long totalTxBytesBefore = TrafficStats.getTotalTxBytes(); - final long totalRxBytesBefore = TrafficStats.getTotalRxBytes(); - final long uidTxBytesBefore = TrafficStats.getUidTxBytes(Process.myUid()); - final long uidRxBytesBefore = TrafficStats.getUidRxBytes(Process.myUid()); - final long uidTxPacketsBefore = TrafficStats.getUidTxPackets(Process.myUid()); - final long uidRxPacketsBefore = TrafficStats.getUidRxPackets(Process.myUid()); - final long ifaceTxPacketsBefore = TrafficStats.getTxPackets("lo"); - final long ifaceRxPacketsBefore = TrafficStats.getRxPackets("lo"); - - // Transfer 1MB of data across an explicitly localhost socket. - final int byteCount = 1024; - final int packetCount = 1024; - - TrafficStats.startDataProfiling(null); - final ServerSocket server = new ServerSocket(0); - new Thread("TrafficStatsTest.testTrafficStatsForLocalhost") { - @Override - public void run() { - try { - final Socket socket = new Socket("localhost", server.getLocalPort()); - // Make sure that each write()+flush() turns into a packet: - // disable Nagle. - socket.setTcpNoDelay(true); - final OutputStream out = socket.getOutputStream(); - final byte[] buf = new byte[byteCount]; - TrafficStats.setThreadStatsTag(0x42); - TrafficStats.tagSocket(socket); - for (int i = 0; i < packetCount; i++) { - out.write(buf); - out.flush(); - try { - // Bug: 10668088, Even with Nagle disabled, and flushing the 1024 bytes - // the kernel still regroups data into a larger packet. - Thread.sleep(5); - } catch (InterruptedException e) { - } - } - out.close(); - socket.close(); - } catch (IOException e) { - Log.i(LOG_TAG, "Badness during writes to socket: " + e); - } - } - }.start(); - - int read = 0; - try { - final Socket socket = server.accept(); - socket.setTcpNoDelay(true); - TrafficStats.setThreadStatsTag(0x43); - TrafficStats.tagSocket(socket); - final InputStream in = socket.getInputStream(); - final byte[] buf = new byte[byteCount]; - while (read < byteCount * packetCount) { - int n = in.read(buf); - assertTrue("Unexpected EOF", n > 0); - read += n; - } - } finally { - server.close(); - } - assertTrue("Not all data read back", read >= byteCount * packetCount); - - // It's too fast to call getUidTxBytes function. - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - } - final NetworkStats testStats = TrafficStats.stopDataProfiling(null); - - final long mobileTxPacketsAfter = TrafficStats.getMobileTxPackets(); - final long mobileRxPacketsAfter = TrafficStats.getMobileRxPackets(); - final long mobileTxBytesAfter = TrafficStats.getMobileTxBytes(); - final long mobileRxBytesAfter = TrafficStats.getMobileRxBytes(); - final long totalTxPacketsAfter = TrafficStats.getTotalTxPackets(); - final long totalRxPacketsAfter = TrafficStats.getTotalRxPackets(); - final long totalTxBytesAfter = TrafficStats.getTotalTxBytes(); - final long totalRxBytesAfter = TrafficStats.getTotalRxBytes(); - final long uidTxBytesAfter = TrafficStats.getUidTxBytes(Process.myUid()); - final long uidRxBytesAfter = TrafficStats.getUidRxBytes(Process.myUid()); - final long uidTxPacketsAfter = TrafficStats.getUidTxPackets(Process.myUid()); - final long uidRxPacketsAfter = TrafficStats.getUidRxPackets(Process.myUid()); - final long uidTxDeltaBytes = uidTxBytesAfter - uidTxBytesBefore; - final long uidTxDeltaPackets = uidTxPacketsAfter - uidTxPacketsBefore; - final long uidRxDeltaBytes = uidRxBytesAfter - uidRxBytesBefore; - final long uidRxDeltaPackets = uidRxPacketsAfter - uidRxPacketsBefore; - final long ifaceTxPacketsAfter = TrafficStats.getTxPackets("lo"); - final long ifaceRxPacketsAfter = TrafficStats.getRxPackets("lo"); - final long ifaceTxDeltaPackets = ifaceTxPacketsAfter - ifaceTxPacketsBefore; - final long ifaceRxDeltaPackets = ifaceRxPacketsAfter - ifaceRxPacketsBefore; - - // Localhost traffic *does* count against per-UID stats. - /* - * Calculations: - * - bytes - * bytes is approx: packets * data + packets * acks; - * but sometimes there are less acks than packets, so we set a lower - * limit of 1 ack. - * - setup/teardown - * + 7 approx.: syn, syn-ack, ack, fin-ack, ack, fin-ack, ack; - * but sometimes the last find-acks just vanish, so we set a lower limit of +5. - */ - final int maxExpectedExtraPackets = 7; - final int minExpectedExtraPackets = 5; - - // Some other tests don't cleanup connections correctly. - // They have the same UID, so we discount their lingering traffic - // which happens only on non-localhost, such as TCP FIN retranmission packets - final long deltaTxOtherPackets = (totalTxPacketsAfter - totalTxPacketsBefore) - - uidTxDeltaPackets; - final long deltaRxOtherPackets = (totalRxPacketsAfter - totalRxPacketsBefore) - - uidRxDeltaPackets; - if (deltaTxOtherPackets > 0 || deltaRxOtherPackets > 0) { - Log.i(LOG_TAG, "lingering traffic data: " + deltaTxOtherPackets + "/" - + deltaRxOtherPackets); - } - - // Check that the per-uid stats obtained from data profiling contain the expected values. - // The data profiling snapshot is generated from the readNetworkStatsDetail() method in - // networkStatsService, so it's possible to verify that the detailed stats for a given - // uid are correct. - final NetworkStats.Entry entry = testStats.getTotal(null, Process.myUid()); - final long pktBytes = tcpPacketToIpBytes(packetCount, byteCount); - final long pktWithNoDataBytes = tcpPacketToIpBytes(packetCount, 0); - final long minExpExtraPktBytes = tcpPacketToIpBytes(minExpectedExtraPackets, 0); - final long maxExpExtraPktBytes = tcpPacketToIpBytes(maxExpectedExtraPackets, 0); - final long deltaTxOtherPktBytes = tcpPacketToIpBytes(deltaTxOtherPackets, 0); - final long deltaRxOtherPktBytes = tcpPacketToIpBytes(deltaRxOtherPackets, 0); - assertInRange("txPackets detail", entry.txPackets, packetCount + minExpectedExtraPackets, - uidTxDeltaPackets); - assertInRange("rxPackets detail", entry.rxPackets, packetCount + minExpectedExtraPackets, - uidRxDeltaPackets); - assertInRange("txBytes detail", entry.txBytes, pktBytes + minExpExtraPktBytes, - uidTxDeltaBytes); - assertInRange("rxBytes detail", entry.rxBytes, pktBytes + minExpExtraPktBytes, - uidRxDeltaBytes); - assertInRange("uidtxp", uidTxDeltaPackets, packetCount + minExpectedExtraPackets, - packetCount + packetCount + maxExpectedExtraPackets + deltaTxOtherPackets); - assertInRange("uidrxp", uidRxDeltaPackets, packetCount + minExpectedExtraPackets, - packetCount + packetCount + maxExpectedExtraPackets + deltaRxOtherPackets); - assertInRange("uidtxb", uidTxDeltaBytes, pktBytes + minExpExtraPktBytes, - pktBytes + pktWithNoDataBytes + maxExpExtraPktBytes + deltaTxOtherPktBytes); - assertInRange("uidrxb", uidRxDeltaBytes, pktBytes + minExpExtraPktBytes, - pktBytes + pktWithNoDataBytes + maxExpExtraPktBytes + deltaRxOtherPktBytes); - assertInRange("iftxp", ifaceTxDeltaPackets, packetCount + minExpectedExtraPackets, - packetCount + packetCount + maxExpectedExtraPackets + deltaTxOtherPackets); - assertInRange("ifrxp", ifaceRxDeltaPackets, packetCount + minExpectedExtraPackets, - packetCount + packetCount + maxExpectedExtraPackets + deltaRxOtherPackets); - - // Localhost traffic *does* count against total stats. - // Check the total stats increased after test data transfer over localhost has been made. - assertTrue("ttxp: " + totalTxPacketsBefore + " -> " + totalTxPacketsAfter, - totalTxPacketsAfter >= totalTxPacketsBefore + uidTxDeltaPackets); - assertTrue("trxp: " + totalRxPacketsBefore + " -> " + totalRxPacketsAfter, - totalRxPacketsAfter >= totalRxPacketsBefore + uidRxDeltaPackets); - assertTrue("ttxb: " + totalTxBytesBefore + " -> " + totalTxBytesAfter, - totalTxBytesAfter >= totalTxBytesBefore + uidTxDeltaBytes); - assertTrue("trxb: " + totalRxBytesBefore + " -> " + totalRxBytesAfter, - totalRxBytesAfter >= totalRxBytesBefore + uidRxDeltaBytes); - assertTrue("iftxp: " + ifaceTxPacketsBefore + " -> " + ifaceTxPacketsAfter, - totalTxPacketsAfter >= totalTxPacketsBefore + ifaceTxDeltaPackets); - assertTrue("ifrxp: " + ifaceRxPacketsBefore + " -> " + ifaceRxPacketsAfter, - totalRxPacketsAfter >= totalRxPacketsBefore + ifaceRxDeltaPackets); - - // Localhost traffic should *not* count against mobile stats, - // There might be some other traffic, but nowhere near 1MB. - assertInRange("mtxp", mobileTxPacketsAfter, mobileTxPacketsBefore, - mobileTxPacketsBefore + 500); - assertInRange("mrxp", mobileRxPacketsAfter, mobileRxPacketsBefore, - mobileRxPacketsBefore + 500); - assertInRange("mtxb", mobileTxBytesAfter, mobileTxBytesBefore, - mobileTxBytesBefore + 200000); - assertInRange("mrxb", mobileRxBytesAfter, mobileRxBytesBefore, - mobileRxBytesBefore + 200000); - } -} diff --git a/tests/cts/net/src/android/net/cts/TunUtils.java b/tests/cts/net/src/android/net/cts/TunUtils.java deleted file mode 100644 index adaba9d398..0000000000 --- a/tests/cts/net/src/android/net/cts/TunUtils.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2018 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.cts; - -import static android.net.cts.PacketUtils.IP4_HDRLEN; -import static android.net.cts.PacketUtils.IP6_HDRLEN; -import static android.net.cts.PacketUtils.IPPROTO_ESP; -import static android.net.cts.PacketUtils.UDP_HDRLEN; -import static android.system.OsConstants.IPPROTO_UDP; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.os.ParcelFileDescriptor; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; - -public class TunUtils { - private static final String TAG = TunUtils.class.getSimpleName(); - - protected static final int IP4_ADDR_OFFSET = 12; - protected static final int IP4_ADDR_LEN = 4; - protected static final int IP6_ADDR_OFFSET = 8; - protected static final int IP6_ADDR_LEN = 16; - protected static final int IP4_PROTO_OFFSET = 9; - protected static final int IP6_PROTO_OFFSET = 6; - - private static final int DATA_BUFFER_LEN = 4096; - private static final int TIMEOUT = 1000; - - private final List mPackets = new ArrayList<>(); - private final ParcelFileDescriptor mTunFd; - private final Thread mReaderThread; - - public TunUtils(ParcelFileDescriptor tunFd) { - mTunFd = tunFd; - - // Start background reader thread - mReaderThread = - new Thread( - () -> { - try { - // Loop will exit and thread will quit when tunFd is closed. - // Receiving either EOF or an exception will exit this reader loop. - // FileInputStream in uninterruptable, so there's no good way to - // ensure that this thread shuts down except upon FD closure. - while (true) { - byte[] intercepted = receiveFromTun(); - if (intercepted == null) { - // Exit once we've hit EOF - return; - } else if (intercepted.length > 0) { - // Only save packet if we've received any bytes. - synchronized (mPackets) { - mPackets.add(intercepted); - mPackets.notifyAll(); - } - } - } - } catch (IOException ignored) { - // Simply exit this reader thread - return; - } - }); - mReaderThread.start(); - } - - private byte[] receiveFromTun() throws IOException { - FileInputStream in = new FileInputStream(mTunFd.getFileDescriptor()); - byte[] inBytes = new byte[DATA_BUFFER_LEN]; - int bytesRead = in.read(inBytes); - - if (bytesRead < 0) { - return null; // return null for EOF - } else if (bytesRead >= DATA_BUFFER_LEN) { - throw new IllegalStateException("Too big packet. Fragmentation unsupported"); - } - return Arrays.copyOf(inBytes, bytesRead); - } - - private byte[] getFirstMatchingPacket(Predicate verifier, int startIndex) { - synchronized (mPackets) { - for (int i = startIndex; i < mPackets.size(); i++) { - byte[] pkt = mPackets.get(i); - if (verifier.test(pkt)) { - return pkt; - } - } - } - return null; - } - - protected byte[] awaitPacket(Predicate verifier) throws Exception { - long endTime = System.currentTimeMillis() + TIMEOUT; - int startIndex = 0; - - synchronized (mPackets) { - while (System.currentTimeMillis() < endTime) { - final byte[] pkt = getFirstMatchingPacket(verifier, startIndex); - if (pkt != null) { - return pkt; // We've found the packet we're looking for. - } - - startIndex = mPackets.size(); - - // Try to prevent waiting too long. If waitTimeout <= 0, we've already hit timeout - long waitTimeout = endTime - System.currentTimeMillis(); - if (waitTimeout > 0) { - mPackets.wait(waitTimeout); - } - } - } - - fail("No packet found matching verifier"); - throw new IllegalStateException("Impossible condition; should have thrown in fail()"); - } - - public byte[] awaitEspPacketNoPlaintext( - int spi, byte[] plaintext, boolean useEncap, int expectedPacketSize) throws Exception { - final byte[] espPkt = awaitPacket( - (pkt) -> isEspFailIfSpecifiedPlaintextFound(pkt, spi, useEncap, plaintext)); - - // Validate packet size - assertEquals(expectedPacketSize, espPkt.length); - - return espPkt; // We've found the packet we're looking for. - } - - private static boolean isSpiEqual(byte[] pkt, int espOffset, int spi) { - // Check SPI byte by byte. - return pkt[espOffset] == (byte) ((spi >>> 24) & 0xff) - && pkt[espOffset + 1] == (byte) ((spi >>> 16) & 0xff) - && pkt[espOffset + 2] == (byte) ((spi >>> 8) & 0xff) - && pkt[espOffset + 3] == (byte) (spi & 0xff); - } - - /** - * Variant of isEsp that also fails the test if the provided plaintext is found - * - * @param pkt the packet bytes to verify - * @param spi the expected SPI to look for - * @param encap whether encap was enabled, and the packet has a UDP header - * @param plaintext the plaintext packet before outbound encryption, which MUST not appear in - * the provided packet. - */ - private static boolean isEspFailIfSpecifiedPlaintextFound( - byte[] pkt, int spi, boolean encap, byte[] plaintext) { - if (Collections.indexOfSubList(Arrays.asList(pkt), Arrays.asList(plaintext)) != -1) { - fail("Banned plaintext packet found"); - } - - return isEsp(pkt, spi, encap); - } - - private static boolean isEsp(byte[] pkt, int spi, boolean encap) { - if (isIpv6(pkt)) { - // IPv6 UDP encap not supported by kernels; assume non-encap. - return pkt[IP6_PROTO_OFFSET] == IPPROTO_ESP && isSpiEqual(pkt, IP6_HDRLEN, spi); - } else { - // Use default IPv4 header length (assuming no options) - if (encap) { - return pkt[IP4_PROTO_OFFSET] == IPPROTO_UDP - && isSpiEqual(pkt, IP4_HDRLEN + UDP_HDRLEN, spi); - } else { - return pkt[IP4_PROTO_OFFSET] == IPPROTO_ESP && isSpiEqual(pkt, IP4_HDRLEN, spi); - } - } - } - - public static boolean isIpv6(byte[] pkt) { - // First nibble shows IP version. 0x60 for IPv6 - return (pkt[0] & (byte) 0xF0) == (byte) 0x60; - } - - private static byte[] getReflectedPacket(byte[] pkt) { - byte[] reflected = Arrays.copyOf(pkt, pkt.length); - - if (isIpv6(pkt)) { - // Set reflected packet's dst to that of the original's src - System.arraycopy( - pkt, // src - IP6_ADDR_OFFSET + IP6_ADDR_LEN, // src offset - reflected, // dst - IP6_ADDR_OFFSET, // dst offset - IP6_ADDR_LEN); // len - // Set reflected packet's src IP to that of the original's dst IP - System.arraycopy( - pkt, // src - IP6_ADDR_OFFSET, // src offset - reflected, // dst - IP6_ADDR_OFFSET + IP6_ADDR_LEN, // dst offset - IP6_ADDR_LEN); // len - } else { - // Set reflected packet's dst to that of the original's src - System.arraycopy( - pkt, // src - IP4_ADDR_OFFSET + IP4_ADDR_LEN, // src offset - reflected, // dst - IP4_ADDR_OFFSET, // dst offset - IP4_ADDR_LEN); // len - // Set reflected packet's src IP to that of the original's dst IP - System.arraycopy( - pkt, // src - IP4_ADDR_OFFSET, // src offset - reflected, // dst - IP4_ADDR_OFFSET + IP4_ADDR_LEN, // dst offset - IP4_ADDR_LEN); // len - } - return reflected; - } - - /** Takes all captured packets, flips the src/dst, and re-injects them. */ - public void reflectPackets() throws IOException { - synchronized (mPackets) { - for (byte[] pkt : mPackets) { - injectPacket(getReflectedPacket(pkt)); - } - } - } - - public void injectPacket(byte[] pkt) throws IOException { - FileOutputStream out = new FileOutputStream(mTunFd.getFileDescriptor()); - out.write(pkt); - out.flush(); - } - - /** Resets the intercepted packets. */ - public void reset() throws IOException { - synchronized (mPackets) { - mPackets.clear(); - } - } -} diff --git a/tests/cts/net/src/android/net/cts/UriTest.java b/tests/cts/net/src/android/net/cts/UriTest.java deleted file mode 100644 index 40b8fb7259..0000000000 --- a/tests/cts/net/src/android/net/cts/UriTest.java +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright (C) 2008 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.cts; - -import android.content.ContentUris; -import android.net.Uri; -import android.os.Parcel; -import android.test.AndroidTestCase; -import java.io.File; -import java.util.Arrays; -import java.util.ArrayList; - -public class UriTest extends AndroidTestCase { - public void testParcelling() { - parcelAndUnparcel(Uri.parse("foo:bob%20lee")); - parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment")); - parcelAndUnparcel(new Uri.Builder() - .scheme("http") - .authority("crazybob.org") - .path("/rss/") - .encodedQuery("a=b") - .fragment("foo") - .build()); - } - - private void parcelAndUnparcel(Uri u) { - Parcel p = Parcel.obtain(); - Uri.writeToParcel(p, u); - p.setDataPosition(0); - assertEquals(u, Uri.CREATOR.createFromParcel(p)); - - p.setDataPosition(0); - u = u.buildUpon().build(); - Uri.writeToParcel(p, u); - p.setDataPosition(0); - assertEquals(u, Uri.CREATOR.createFromParcel(p)); - } - - public void testBuildUpon() { - Uri u = Uri.parse("bob:lee").buildUpon().scheme("robert").build(); - assertEquals("robert", u.getScheme()); - assertEquals("lee", u.getEncodedSchemeSpecificPart()); - assertEquals("lee", u.getSchemeSpecificPart()); - assertNull(u.getQuery()); - assertNull(u.getPath()); - assertNull(u.getAuthority()); - assertNull(u.getHost()); - - Uri a = Uri.fromParts("foo", "bar", "tee"); - Uri b = a.buildUpon().fragment("new").build(); - assertEquals("new", b.getFragment()); - assertEquals("bar", b.getSchemeSpecificPart()); - assertEquals("foo", b.getScheme()); - a = new Uri.Builder() - .scheme("foo") - .encodedOpaquePart("bar") - .fragment("tee") - .build(); - b = a.buildUpon().fragment("new").build(); - assertEquals("new", b.getFragment()); - assertEquals("bar", b.getSchemeSpecificPart()); - assertEquals("foo", b.getScheme()); - - a = Uri.fromParts("scheme", "[2001:db8::dead:e1f]/foo", "bar"); - b = a.buildUpon().fragment("qux").build(); - assertEquals("qux", b.getFragment()); - assertEquals("[2001:db8::dead:e1f]/foo", b.getSchemeSpecificPart()); - assertEquals("scheme", b.getScheme()); - } - - public void testStringUri() { - assertEquals("bob lee", - Uri.parse("foo:bob%20lee").getSchemeSpecificPart()); - assertEquals("bob%20lee", - Uri.parse("foo:bob%20lee").getEncodedSchemeSpecificPart()); - - assertEquals("/bob%20lee", - Uri.parse("foo:/bob%20lee").getEncodedPath()); - assertNull(Uri.parse("foo:bob%20lee").getPath()); - - assertEquals("bob%20lee", - Uri.parse("foo:?bob%20lee").getEncodedQuery()); - assertNull(Uri.parse("foo:bob%20lee").getEncodedQuery()); - assertNull(Uri.parse("foo:bar#?bob%20lee").getQuery()); - - assertEquals("bob%20lee", - Uri.parse("foo:#bob%20lee").getEncodedFragment()); - - Uri uri = Uri.parse("http://localhost:42"); - assertEquals("localhost", uri.getHost()); - assertEquals(42, uri.getPort()); - - uri = Uri.parse("http://bob@localhost:42"); - assertEquals("bob", uri.getUserInfo()); - assertEquals("localhost", uri.getHost()); - assertEquals(42, uri.getPort()); - - uri = Uri.parse("http://bob%20lee@localhost:42"); - assertEquals("bob lee", uri.getUserInfo()); - assertEquals("bob%20lee", uri.getEncodedUserInfo()); - - uri = Uri.parse("http://localhost"); - assertEquals("localhost", uri.getHost()); - assertEquals(-1, uri.getPort()); - - uri = Uri.parse("http://a:a@example.com:a@example2.com/path"); - assertEquals("a:a@example.com:a@example2.com", uri.getAuthority()); - assertEquals("example2.com", uri.getHost()); - assertEquals(-1, uri.getPort()); - assertEquals("/path", uri.getPath()); - - uri = Uri.parse("http://a.foo.com\\.example.com/path"); - assertEquals("a.foo.com", uri.getHost()); - assertEquals(-1, uri.getPort()); - assertEquals("\\.example.com/path", uri.getPath()); - - uri = Uri.parse("https://[2001:db8::dead:e1f]/foo"); - assertEquals("[2001:db8::dead:e1f]", uri.getAuthority()); - assertNull(uri.getUserInfo()); - assertEquals("[2001:db8::dead:e1f]", uri.getHost()); - assertEquals(-1, uri.getPort()); - assertEquals("/foo", uri.getPath()); - assertEquals(null, uri.getFragment()); - assertEquals("//[2001:db8::dead:e1f]/foo", uri.getSchemeSpecificPart()); - - uri = Uri.parse("https://[2001:db8::dead:e1f]/#foo"); - assertEquals("[2001:db8::dead:e1f]", uri.getAuthority()); - assertNull(uri.getUserInfo()); - assertEquals("[2001:db8::dead:e1f]", uri.getHost()); - assertEquals(-1, uri.getPort()); - assertEquals("/", uri.getPath()); - assertEquals("foo", uri.getFragment()); - assertEquals("//[2001:db8::dead:e1f]/", uri.getSchemeSpecificPart()); - - uri = Uri.parse( - "https://some:user@[2001:db8::dead:e1f]:1234/foo?corge=thud&corge=garp#bar"); - assertEquals("some:user@[2001:db8::dead:e1f]:1234", uri.getAuthority()); - assertEquals("some:user", uri.getUserInfo()); - assertEquals("[2001:db8::dead:e1f]", uri.getHost()); - assertEquals(1234, uri.getPort()); - assertEquals("/foo", uri.getPath()); - assertEquals("bar", uri.getFragment()); - assertEquals("//some:user@[2001:db8::dead:e1f]:1234/foo?corge=thud&corge=garp", - uri.getSchemeSpecificPart()); - assertEquals("corge=thud&corge=garp", uri.getQuery()); - assertEquals("thud", uri.getQueryParameter("corge")); - assertEquals(Arrays.asList("thud", "garp"), uri.getQueryParameters("corge")); - } - - public void testCompareTo() { - Uri a = Uri.parse("foo:a"); - Uri b = Uri.parse("foo:b"); - Uri b2 = Uri.parse("foo:b"); - - assertTrue(a.compareTo(b) < 0); - assertTrue(b.compareTo(a) > 0); - assertEquals(0, b.compareTo(b2)); - } - - public void testEqualsAndHashCode() { - Uri a = Uri.parse("http://crazybob.org/test/?foo=bar#tee"); - - Uri b = new Uri.Builder() - .scheme("http") - .authority("crazybob.org") - .path("/test/") - .encodedQuery("foo=bar") - .fragment("tee") - .build(); - - // Try alternate builder methods. - Uri c = new Uri.Builder() - .scheme("http") - .encodedAuthority("crazybob.org") - .encodedPath("/test/") - .encodedQuery("foo=bar") - .encodedFragment("tee") - .build(); - - assertFalse(Uri.EMPTY.equals(null)); - assertEquals(a, b); - assertEquals(b, c); - assertEquals(c, a); - assertEquals(a.hashCode(), b.hashCode()); - assertEquals(b.hashCode(), c.hashCode()); - } - - public void testEncodeAndDecode() { - String encoded = Uri.encode("Bob:/", "/"); - assertEquals(-1, encoded.indexOf(':')); - assertTrue(encoded.indexOf('/') > -1); - assertEncodeDecodeRoundtripExact(null); - assertEncodeDecodeRoundtripExact(""); - assertEncodeDecodeRoundtripExact("Bob"); - assertEncodeDecodeRoundtripExact(":Bob"); - assertEncodeDecodeRoundtripExact("::Bob"); - assertEncodeDecodeRoundtripExact("Bob::Lee"); - assertEncodeDecodeRoundtripExact("Bob:Lee"); - assertEncodeDecodeRoundtripExact("Bob::"); - assertEncodeDecodeRoundtripExact("Bob:"); - assertEncodeDecodeRoundtripExact("::Bob::"); - assertEncodeDecodeRoundtripExact("https:/some:user@[2001:db8::dead:e1f]:1234/foo#bar"); - } - - private static void assertEncodeDecodeRoundtripExact(String s) { - assertEquals(s, Uri.decode(Uri.encode(s, null))); - } - - public void testDecode_emptyString_returnsEmptyString() { - assertEquals("", Uri.decode("")); - } - - public void testDecode_null_returnsNull() { - assertNull(Uri.decode(null)); - } - - public void testDecode_wrongHexDigit() { - // %p in the end. - assertEquals("ab/$\u0102%\u0840\uFFFD\u0000", Uri.decode("ab%2f$%C4%82%25%e0%a1%80%p")); - } - - public void testDecode_secondHexDigitWrong() { - // %1p in the end. - assertEquals("ab/$\u0102%\u0840\uFFFD\u0001", Uri.decode("ab%2f$%c4%82%25%e0%a1%80%1p")); - } - - public void testDecode_endsWithPercent_appendsUnknownCharacter() { - // % in the end. - assertEquals("ab/$\u0102%\u0840\uFFFD", Uri.decode("ab%2f$%c4%82%25%e0%a1%80%")); - } - - public void testDecode_plusNotConverted() { - assertEquals("ab/$\u0102%+\u0840", Uri.decode("ab%2f$%c4%82%25+%e0%a1%80")); - } - - // Last character needs decoding (make sure we are flushing the buffer with chars to decode). - public void testDecode_lastCharacter() { - assertEquals("ab/$\u0102%\u0840", Uri.decode("ab%2f$%c4%82%25%e0%a1%80")); - } - - // Check that a second row of encoded characters is decoded properly (internal buffers are - // reset properly). - public void testDecode_secondRowOfEncoded() { - assertEquals("ab/$\u0102%\u0840aa\u0840", - Uri.decode("ab%2f$%c4%82%25%e0%a1%80aa%e0%a1%80")); - } - - public void testFromFile() { - File f = new File("/tmp/bob"); - Uri uri = Uri.fromFile(f); - assertEquals("file:///tmp/bob", uri.toString()); - try { - Uri.fromFile(null); - fail("testFile fail"); - } catch (NullPointerException e) {} - } - - public void testQueryParameters() { - Uri uri = Uri.parse("content://user"); - assertEquals(null, uri.getQueryParameter("a")); - - uri = uri.buildUpon().appendQueryParameter("a", "b").build(); - assertEquals("b", uri.getQueryParameter("a")); - - uri = uri.buildUpon().appendQueryParameter("a", "b2").build(); - assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a")); - - uri = uri.buildUpon().appendQueryParameter("c", "d").build(); - assertEquals(Arrays.asList("b", "b2"), uri.getQueryParameters("a")); - assertEquals("d", uri.getQueryParameter("c")); - } - - public void testPathOperations() { - Uri uri = Uri.parse("content://user/a/b"); - - assertEquals(2, uri.getPathSegments().size()); - assertEquals("a", uri.getPathSegments().get(0)); - assertEquals("b", uri.getPathSegments().get(1)); - assertEquals("b", uri.getLastPathSegment()); - - Uri first = uri; - uri = uri.buildUpon().appendPath("c").build(); - assertEquals(3, uri.getPathSegments().size()); - assertEquals("c", uri.getPathSegments().get(2)); - assertEquals("c", uri.getLastPathSegment()); - assertEquals("content://user/a/b/c", uri.toString()); - - uri = ContentUris.withAppendedId(uri, 100); - assertEquals(4, uri.getPathSegments().size()); - assertEquals("100", uri.getPathSegments().get(3)); - assertEquals("100", uri.getLastPathSegment()); - assertEquals(100, ContentUris.parseId(uri)); - assertEquals("content://user/a/b/c/100", uri.toString()); - - // Make sure the original URI is still intact. - assertEquals(2, first.getPathSegments().size()); - assertEquals("b", first.getLastPathSegment()); - - try { - first.getPathSegments().get(2); - fail("test path operations"); - } catch (IndexOutOfBoundsException e) {} - - assertEquals(null, Uri.EMPTY.getLastPathSegment()); - - Uri withC = Uri.parse("foo:/a/b/").buildUpon().appendPath("c").build(); - assertEquals("/a/b/c", withC.getPath()); - } - - public void testOpaqueUri() { - Uri uri = Uri.parse("mailto:nobody"); - testOpaqueUri(uri); - - uri = uri.buildUpon().build(); - testOpaqueUri(uri); - - uri = Uri.fromParts("mailto", "nobody", null); - testOpaqueUri(uri); - - uri = uri.buildUpon().build(); - testOpaqueUri(uri); - - uri = new Uri.Builder() - .scheme("mailto") - .opaquePart("nobody") - .build(); - testOpaqueUri(uri); - - uri = uri.buildUpon().build(); - testOpaqueUri(uri); - } - - private void testOpaqueUri(Uri uri) { - assertEquals("mailto", uri.getScheme()); - assertEquals("nobody", uri.getSchemeSpecificPart()); - assertEquals("nobody", uri.getEncodedSchemeSpecificPart()); - - assertNull(uri.getFragment()); - assertTrue(uri.isAbsolute()); - assertTrue(uri.isOpaque()); - assertFalse(uri.isRelative()); - assertFalse(uri.isHierarchical()); - - assertNull(uri.getAuthority()); - assertNull(uri.getEncodedAuthority()); - assertNull(uri.getPath()); - assertNull(uri.getEncodedPath()); - assertNull(uri.getUserInfo()); - assertNull(uri.getEncodedUserInfo()); - assertNull(uri.getQuery()); - assertNull(uri.getEncodedQuery()); - assertNull(uri.getHost()); - assertEquals(-1, uri.getPort()); - - assertTrue(uri.getPathSegments().isEmpty()); - assertNull(uri.getLastPathSegment()); - - assertEquals("mailto:nobody", uri.toString()); - - Uri withFragment = uri.buildUpon().fragment("top").build(); - assertEquals("mailto:nobody#top", withFragment.toString()); - } - - public void testHierarchicalUris() { - testHierarchical("http", "google.com", "/p1/p2", "query", "fragment"); - testHierarchical("file", null, "/p1/p2", null, null); - testHierarchical("content", "contact", "/p1/p2", null, null); - testHierarchical("http", "google.com", "/p1/p2", null, "fragment"); - testHierarchical("http", "google.com", "", null, "fragment"); - testHierarchical("http", "google.com", "", "query", "fragment"); - testHierarchical("http", "google.com", "", "query", null); - testHierarchical("http", null, "/", "query", null); - } - - private static void testHierarchical(String scheme, String authority, - String path, String query, String fragment) { - StringBuilder sb = new StringBuilder(); - - if (authority != null) { - sb.append("//").append(authority); - } - if (path != null) { - sb.append(path); - } - if (query != null) { - sb.append('?').append(query); - } - - String ssp = sb.toString(); - - if (scheme != null) { - sb.insert(0, scheme + ":"); - } - if (fragment != null) { - sb.append('#').append(fragment); - } - - String uriString = sb.toString(); - - Uri uri = Uri.parse(uriString); - - // Run these twice to test caching. - compareHierarchical( - uriString, ssp, uri, scheme, authority, path, query, fragment); - compareHierarchical( - uriString, ssp, uri, scheme, authority, path, query, fragment); - - // Test rebuilt version. - uri = uri.buildUpon().build(); - - // Run these twice to test caching. - compareHierarchical( - uriString, ssp, uri, scheme, authority, path, query, fragment); - compareHierarchical( - uriString, ssp, uri, scheme, authority, path, query, fragment); - - // The decoded and encoded versions of the inputs are all the same. - // We'll test the actual encoding decoding separately. - - // Test building with encoded versions. - Uri built = new Uri.Builder() - .scheme(scheme) - .encodedAuthority(authority) - .encodedPath(path) - .encodedQuery(query) - .encodedFragment(fragment) - .build(); - - compareHierarchical( - uriString, ssp, built, scheme, authority, path, query, fragment); - compareHierarchical( - uriString, ssp, built, scheme, authority, path, query, fragment); - - // Test building with decoded versions. - built = new Uri.Builder() - .scheme(scheme) - .authority(authority) - .path(path) - .query(query) - .fragment(fragment) - .build(); - - compareHierarchical( - uriString, ssp, built, scheme, authority, path, query, fragment); - compareHierarchical( - uriString, ssp, built, scheme, authority, path, query, fragment); - - // Rebuild. - built = built.buildUpon().build(); - - compareHierarchical( - uriString, ssp, built, scheme, authority, path, query, fragment); - compareHierarchical( - uriString, ssp, built, scheme, authority, path, query, fragment); - } - - private static void compareHierarchical(String uriString, String ssp, - Uri uri, - String scheme, String authority, String path, String query, - String fragment) { - assertEquals(scheme, uri.getScheme()); - assertEquals(authority, uri.getAuthority()); - assertEquals(authority, uri.getEncodedAuthority()); - assertEquals(path, uri.getPath()); - assertEquals(path, uri.getEncodedPath()); - assertEquals(query, uri.getQuery()); - assertEquals(query, uri.getEncodedQuery()); - assertEquals(fragment, uri.getFragment()); - assertEquals(fragment, uri.getEncodedFragment()); - assertEquals(ssp, uri.getSchemeSpecificPart()); - - if (scheme != null) { - assertTrue(uri.isAbsolute()); - assertFalse(uri.isRelative()); - } else { - assertFalse(uri.isAbsolute()); - assertTrue(uri.isRelative()); - } - - assertFalse(uri.isOpaque()); - assertTrue(uri.isHierarchical()); - assertEquals(uriString, uri.toString()); - } - - public void testNormalizeScheme() { - assertEquals(Uri.parse(""), Uri.parse("").normalizeScheme()); - assertEquals(Uri.parse("http://www.android.com"), - Uri.parse("http://www.android.com").normalizeScheme()); - assertEquals(Uri.parse("http://USER@WWW.ANDROID.COM:100/ABOUT?foo=blah@bar=bleh#c"), - Uri.parse("HTTP://USER@WWW.ANDROID.COM:100/ABOUT?foo=blah@bar=bleh#c") - .normalizeScheme()); - } - - public void testToSafeString_tel() { - checkToSafeString("tel:xxxxxx", "tel:Google"); - checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890"); - checkToSafeString("tEl:xxx.xxx-xxxx", "tEl:123.456-7890"); - } - - public void testToSafeString_sip() { - checkToSafeString("sip:xxxxxxx@xxxxxxx.xxxxxxxx", "sip:android@android.com:1234"); - checkToSafeString("sIp:xxxxxxx@xxxxxxx.xxx", "sIp:android@android.com"); - } - - public void testToSafeString_sms() { - checkToSafeString("sms:xxxxxx", "sms:123abc"); - checkToSafeString("smS:xxx.xxx-xxxx", "smS:123.456-7890"); - } - - public void testToSafeString_smsto() { - checkToSafeString("smsto:xxxxxx", "smsto:123abc"); - checkToSafeString("SMSTo:xxx.xxx-xxxx", "SMSTo:123.456-7890"); - } - - public void testToSafeString_mailto() { - checkToSafeString("mailto:xxxxxxx@xxxxxxx.xxx", "mailto:android@android.com"); - checkToSafeString("Mailto:xxxxxxx@xxxxxxx.xxxxxxxxxx", - "Mailto:android@android.com/secret"); - } - - public void testToSafeString_nfc() { - checkToSafeString("nfc:xxxxxx", "nfc:123abc"); - checkToSafeString("nfc:xxx.xxx-xxxx", "nfc:123.456-7890"); - checkToSafeString("nfc:xxxxxxx@xxxxxxx.xxx", "nfc:android@android.com"); - } - - public void testToSafeString_http() { - checkToSafeString("http://www.android.com/...", "http://www.android.com"); - checkToSafeString("HTTP://www.android.com/...", "HTTP://www.android.com"); - checkToSafeString("http://www.android.com/...", "http://www.android.com/"); - checkToSafeString("http://www.android.com/...", "http://www.android.com/secretUrl?param"); - checkToSafeString("http://www.android.com/...", - "http://user:pwd@www.android.com/secretUrl?param"); - checkToSafeString("http://www.android.com/...", - "http://user@www.android.com/secretUrl?param"); - checkToSafeString("http://www.android.com/...", "http://www.android.com/secretUrl?param"); - checkToSafeString("http:///...", "http:///path?param"); - checkToSafeString("http:///...", "http://"); - checkToSafeString("http://:12345/...", "http://:12345/"); - } - - public void testToSafeString_https() { - checkToSafeString("https://www.android.com/...", "https://www.android.com/secretUrl?param"); - checkToSafeString("https://www.android.com:8443/...", - "https://user:pwd@www.android.com:8443/secretUrl?param"); - checkToSafeString("https://www.android.com/...", "https://user:pwd@www.android.com"); - checkToSafeString("Https://www.android.com/...", "Https://user:pwd@www.android.com"); - } - - public void testToSafeString_ftp() { - checkToSafeString("ftp://ftp.android.com/...", "ftp://ftp.android.com/"); - checkToSafeString("ftP://ftp.android.com/...", "ftP://anonymous@ftp.android.com/"); - checkToSafeString("ftp://ftp.android.com:2121/...", - "ftp://root:love@ftp.android.com:2121/"); - } - - public void testToSafeString_rtsp() { - checkToSafeString("rtsp://rtsp.android.com/...", "rtsp://rtsp.android.com/"); - checkToSafeString("rtsp://rtsp.android.com/...", "rtsp://rtsp.android.com/video.mov"); - checkToSafeString("rtsp://rtsp.android.com/...", "rtsp://rtsp.android.com/video.mov?param"); - checkToSafeString("RtsP://rtsp.android.com/...", "RtsP://anonymous@rtsp.android.com/"); - checkToSafeString("rtsp://rtsp.android.com:2121/...", - "rtsp://username:password@rtsp.android.com:2121/"); - } - - public void testToSafeString_notSupport() { - checkToSafeString("unsupported://ajkakjah/askdha/secret?secret", - "unsupported://ajkakjah/askdha/secret?secret"); - checkToSafeString("unsupported:ajkakjah/askdha/secret?secret", - "unsupported:ajkakjah/askdha/secret?secret"); - } - - private void checkToSafeString(String expectedSafeString, String original) { - assertEquals(expectedSafeString, Uri.parse(original).toSafeString()); - } -} diff --git a/tests/cts/net/src/android/net/cts/Uri_BuilderTest.java b/tests/cts/net/src/android/net/cts/Uri_BuilderTest.java deleted file mode 100644 index 4088d822cf..0000000000 --- a/tests/cts/net/src/android/net/cts/Uri_BuilderTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2008 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.cts; - -import junit.framework.TestCase; -import android.net.Uri.Builder; -import android.net.Uri; - -public class Uri_BuilderTest extends TestCase { - public void testBuilderOperations() { - Uri uri = Uri.parse("http://google.com/p1?query#fragment"); - Builder builder = uri.buildUpon(); - uri = builder.appendPath("p2").build(); - assertEquals("http", uri.getScheme()); - assertEquals("google.com", uri.getAuthority()); - assertEquals("/p1/p2", uri.getPath()); - assertEquals("query", uri.getQuery()); - assertEquals("fragment", uri.getFragment()); - assertEquals(uri.toString(), builder.toString()); - - uri = Uri.parse("mailto:nobody"); - builder = uri.buildUpon(); - uri = builder.build(); - assertEquals("mailto", uri.getScheme()); - assertEquals("nobody", uri.getSchemeSpecificPart()); - assertEquals(uri.toString(), builder.toString()); - - uri = new Uri.Builder() - .scheme("http") - .encodedAuthority("google.com") - .encodedPath("/p1") - .appendEncodedPath("p2") - .encodedQuery("query") - .appendQueryParameter("query2", null) - .encodedFragment("fragment") - .build(); - assertEquals("http", uri.getScheme()); - assertEquals("google.com", uri.getEncodedAuthority()); - assertEquals("/p1/p2", uri.getEncodedPath()); - assertEquals("query&query2=null", uri.getEncodedQuery()); - assertEquals("fragment", uri.getEncodedFragment()); - - uri = new Uri.Builder() - .scheme("mailto") - .encodedOpaquePart("nobody") - .build(); - assertEquals("mailto", uri.getScheme()); - assertEquals("nobody", uri.getEncodedSchemeSpecificPart()); - } -} diff --git a/tests/cts/net/src/android/net/cts/UrlQuerySanitizerTest.java b/tests/cts/net/src/android/net/cts/UrlQuerySanitizerTest.java deleted file mode 100644 index 5a70928e37..0000000000 --- a/tests/cts/net/src/android/net/cts/UrlQuerySanitizerTest.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2009 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.cts; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import android.net.UrlQuerySanitizer; -import android.net.UrlQuerySanitizer.IllegalCharacterValueSanitizer; -import android.net.UrlQuerySanitizer.ParameterValuePair; -import android.net.UrlQuerySanitizer.ValueSanitizer; -import android.os.Build; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.android.testutils.DevSdkIgnoreRule; -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.List; -import java.util.Set; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class UrlQuerySanitizerTest { - @Rule - public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); - - private static final int ALL_OK = IllegalCharacterValueSanitizer.ALL_OK; - - // URL for test. - private static final String TEST_URL = "http://example.com/?name=Joe+User&age=20&height=175"; - - // Default sanitizer's change when "+". - private static final String EXPECTED_UNDERLINE_NAME = "Joe_User"; - - // IllegalCharacterValueSanitizer sanitizer's change when "+". - private static final String EXPECTED_SPACE_NAME = "Joe User"; - private static final String EXPECTED_AGE = "20"; - private static final String EXPECTED_HEIGHT = "175"; - private static final String NAME = "name"; - private static final String AGE = "age"; - private static final String HEIGHT = "height"; - - @Test - public void testUrlQuerySanitizer() { - MockUrlQuerySanitizer uqs = new MockUrlQuerySanitizer(); - assertFalse(uqs.getAllowUnregisteredParamaters()); - - final String query = "book=thinking in java&price=108"; - final String book = "book"; - final String bookName = "thinking in java"; - final String price = "price"; - final String bookPrice = "108"; - final String notExistPar = "notExistParameter"; - uqs.registerParameters(new String[]{book, price}, UrlQuerySanitizer.getSpaceLegal()); - uqs.parseQuery(query); - assertTrue(uqs.hasParameter(book)); - assertTrue(uqs.hasParameter(price)); - assertFalse(uqs.hasParameter(notExistPar)); - assertEquals(bookName, uqs.getValue(book)); - assertEquals(bookPrice, uqs.getValue(price)); - assertNull(uqs.getValue(notExistPar)); - uqs.clear(); - assertFalse(uqs.hasParameter(book)); - assertFalse(uqs.hasParameter(price)); - - uqs.parseEntry(book, bookName); - assertTrue(uqs.hasParameter(book)); - assertEquals(bookName, uqs.getValue(book)); - uqs.parseEntry(price, bookPrice); - assertTrue(uqs.hasParameter(price)); - assertEquals(bookPrice, uqs.getValue(price)); - assertFalse(uqs.hasParameter(notExistPar)); - assertNull(uqs.getValue(notExistPar)); - - uqs = new MockUrlQuerySanitizer(TEST_URL); - assertTrue(uqs.getAllowUnregisteredParamaters()); - - assertTrue(uqs.hasParameter(NAME)); - assertTrue(uqs.hasParameter(AGE)); - assertTrue(uqs.hasParameter(HEIGHT)); - assertFalse(uqs.hasParameter(notExistPar)); - - assertEquals(EXPECTED_UNDERLINE_NAME, uqs.getValue(NAME)); - assertEquals(EXPECTED_AGE, uqs.getValue(AGE)); - assertEquals(EXPECTED_HEIGHT, uqs.getValue(HEIGHT)); - assertNull(uqs.getValue(notExistPar)); - - final int ContainerLen = 3; - Set urlSet = uqs.getParameterSet(); - assertEquals(ContainerLen, urlSet.size()); - assertTrue(urlSet.contains(NAME)); - assertTrue(urlSet.contains(AGE)); - assertTrue(urlSet.contains(HEIGHT)); - assertFalse(urlSet.contains(notExistPar)); - - List urlList = uqs.getParameterList(); - assertEquals(ContainerLen, urlList.size()); - ParameterValuePair pvp = urlList.get(0); - assertEquals(NAME, pvp.mParameter); - assertEquals(EXPECTED_UNDERLINE_NAME, pvp.mValue); - pvp = urlList.get(1); - assertEquals(AGE, pvp.mParameter); - assertEquals(EXPECTED_AGE, pvp.mValue); - pvp = urlList.get(2); - assertEquals(HEIGHT, pvp.mParameter); - assertEquals(EXPECTED_HEIGHT, pvp.mValue); - - assertFalse(uqs.getPreferFirstRepeatedParameter()); - uqs.addSanitizedEntry(HEIGHT, EXPECTED_HEIGHT + 1); - assertEquals(ContainerLen, urlSet.size()); - assertEquals(ContainerLen + 1, urlList.size()); - assertEquals(EXPECTED_HEIGHT + 1, uqs.getValue(HEIGHT)); - - uqs.setPreferFirstRepeatedParameter(true); - assertTrue(uqs.getPreferFirstRepeatedParameter()); - uqs.addSanitizedEntry(HEIGHT, EXPECTED_HEIGHT); - assertEquals(ContainerLen, urlSet.size()); - assertEquals(ContainerLen + 2, urlList.size()); - assertEquals(EXPECTED_HEIGHT + 1, uqs.getValue(HEIGHT)); - - uqs.registerParameter(NAME, null); - assertNull(uqs.getValueSanitizer(NAME)); - assertNotNull(uqs.getEffectiveValueSanitizer(NAME)); - - uqs.setAllowUnregisteredParamaters(false); - assertFalse(uqs.getAllowUnregisteredParamaters()); - uqs.registerParameter(NAME, null); - assertNull(uqs.getEffectiveValueSanitizer(NAME)); - - ValueSanitizer vs = new IllegalCharacterValueSanitizer(ALL_OK); - uqs.registerParameter(NAME, vs); - uqs.parseUrl(TEST_URL); - assertEquals(EXPECTED_SPACE_NAME, uqs.getValue(NAME)); - assertNotSame(EXPECTED_AGE, uqs.getValue(AGE)); - - String[] register = {NAME, AGE}; - uqs.registerParameters(register, vs); - uqs.parseUrl(TEST_URL); - assertEquals(EXPECTED_SPACE_NAME, uqs.getValue(NAME)); - assertEquals(EXPECTED_AGE, uqs.getValue(AGE)); - assertNotSame(EXPECTED_HEIGHT, uqs.getValue(HEIGHT)); - - uqs.setUnregisteredParameterValueSanitizer(vs); - assertEquals(vs, uqs.getUnregisteredParameterValueSanitizer()); - - vs = UrlQuerySanitizer.getAllIllegal(); - assertEquals("Joe_User", vs.sanitize("Joe\0User")); - vs = UrlQuerySanitizer.getAllButNulLegal(); - assertEquals("Joe User", vs.sanitize("Joe\0User")); - vs = UrlQuerySanitizer.getAllButWhitespaceLegal(); - assertEquals("Joe_User", vs.sanitize("Joe User")); - vs = UrlQuerySanitizer.getAmpAndSpaceLegal(); - assertEquals("Joe User&", vs.sanitize("Joe User&")); - vs = UrlQuerySanitizer.getAmpLegal(); - assertEquals("Joe_User&", vs.sanitize("Joe User&")); - vs = UrlQuerySanitizer.getSpaceLegal(); - assertEquals("Joe User ", vs.sanitize("Joe User&")); - vs = UrlQuerySanitizer.getUrlAndSpaceLegal(); - assertEquals("Joe User&Smith%B5'\'", vs.sanitize("Joe User&Smith%B5'\'")); - vs = UrlQuerySanitizer.getUrlLegal(); - assertEquals("Joe_User&Smith%B5'\'", vs.sanitize("Joe User&Smith%B5'\'")); - - String escape = "Joe"; - assertEquals(escape, uqs.unescape(escape)); - String expectedPlus = "Joe User"; - String expectedPercentSignHex = "title=" + Character.toString((char)181); - String initialPlus = "Joe+User"; - String initialPercentSign = "title=%B5"; - assertEquals(expectedPlus, uqs.unescape(initialPlus)); - assertEquals(expectedPercentSignHex, uqs.unescape(initialPercentSign)); - String expectedPlusThenPercentSign = "Joe Random, User"; - String plusThenPercentSign = "Joe+Random%2C%20User"; - assertEquals(expectedPlusThenPercentSign, uqs.unescape(plusThenPercentSign)); - String expectedPercentSignThenPlus = "Joe, Random User"; - String percentSignThenPlus = "Joe%2C+Random+User"; - assertEquals(expectedPercentSignThenPlus, uqs.unescape(percentSignThenPlus)); - - assertTrue(uqs.decodeHexDigit('0') >= 0); - assertTrue(uqs.decodeHexDigit('b') >= 0); - assertTrue(uqs.decodeHexDigit('F') >= 0); - assertTrue(uqs.decodeHexDigit('$') < 0); - - assertTrue(uqs.isHexDigit('0')); - assertTrue(uqs.isHexDigit('b')); - assertTrue(uqs.isHexDigit('F')); - assertFalse(uqs.isHexDigit('$')); - - uqs.clear(); - assertEquals(0, urlSet.size()); - assertEquals(0, urlList.size()); - - uqs.setPreferFirstRepeatedParameter(true); - assertTrue(uqs.getPreferFirstRepeatedParameter()); - uqs.setPreferFirstRepeatedParameter(false); - assertFalse(uqs.getPreferFirstRepeatedParameter()); - - UrlQuerySanitizer uq = new UrlQuerySanitizer(); - uq.setPreferFirstRepeatedParameter(true); - final String PARA_ANSWER = "answer"; - uq.registerParameter(PARA_ANSWER, new MockValueSanitizer()); - uq.parseUrl("http://www.google.com/question?answer=13&answer=42"); - assertEquals("13", uq.getValue(PARA_ANSWER)); - - uq.setPreferFirstRepeatedParameter(false); - uq.parseQuery("http://www.google.com/question?answer=13&answer=42"); - assertEquals("42", uq.getValue(PARA_ANSWER)); - - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) // Only fixed in R - public void testScriptUrlOk_73822755() { - ValueSanitizer sanitizer = new UrlQuerySanitizer.IllegalCharacterValueSanitizer( - UrlQuerySanitizer.IllegalCharacterValueSanitizer.SCRIPT_URL_OK); - assertEquals("javascript:alert()", sanitizer.sanitize("javascript:alert()")); - } - - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) // Only fixed in R - public void testScriptUrlBlocked_73822755() { - ValueSanitizer sanitizer = UrlQuerySanitizer.getUrlAndSpaceLegal(); - assertEquals("", sanitizer.sanitize("javascript:alert()")); - } - - private static class MockValueSanitizer implements ValueSanitizer{ - - public String sanitize(String value) { - return value; - } - } - - class MockUrlQuerySanitizer extends UrlQuerySanitizer { - public MockUrlQuerySanitizer() { - super(); - } - - public MockUrlQuerySanitizer(String url) { - super(url); - } - - @Override - protected void addSanitizedEntry(String parameter, String value) { - super.addSanitizedEntry(parameter, value); - } - - @Override - protected void clear() { - super.clear(); - } - - @Override - protected int decodeHexDigit(char c) { - return super.decodeHexDigit(c); - } - - @Override - protected boolean isHexDigit(char c) { - return super.isHexDigit(c); - } - - @Override - protected void parseEntry(String parameter, String value) { - super.parseEntry(parameter, value); - } - } -} diff --git a/tests/cts/net/src/android/net/cts/UrlQuerySanitizer_IllegalCharacterValueSanitizerTest.java b/tests/cts/net/src/android/net/cts/UrlQuerySanitizer_IllegalCharacterValueSanitizerTest.java deleted file mode 100644 index f86af3114e..0000000000 --- a/tests/cts/net/src/android/net/cts/UrlQuerySanitizer_IllegalCharacterValueSanitizerTest.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2009 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.cts; - -import android.net.UrlQuerySanitizer; -import android.net.UrlQuerySanitizer.IllegalCharacterValueSanitizer; -import android.test.AndroidTestCase; - -public class UrlQuerySanitizer_IllegalCharacterValueSanitizerTest extends AndroidTestCase { - static final int SPACE_OK = IllegalCharacterValueSanitizer.SPACE_OK; - public void testSanitize() { - IllegalCharacterValueSanitizer sanitizer = new IllegalCharacterValueSanitizer(SPACE_OK); - assertEquals("Joe User", sanitizer.sanitize("Joecommon/android-3.x kernel trees. If you are not running one of these kernels, the - * functionality can be obtained by cherry-picking the following patches from David Miller's - * net-next tree: - *

    - *
  • 6d0bfe2 net: ipv6: Add IPv6 support to the ping socket. - *
  • c26d6b4 ping: always initialize ->sin6_scope_id and ->sin6_flowinfo - *
  • fbfe80c net: ipv6: fix wrong ping_v6_sendmsg return value - *
  • a1bdc45 net: ipv6: add missing lock in ping_v6_sendmsg - *
  • cf970c0 ping: prevent NULL pointer dereference on write to msg_name - *
- * or the equivalent backports to the common/android-3.x trees. - */ -public class PingTest extends AndroidTestCase { - /** Maximum size of the packets we're using to test. */ - private static final int MAX_SIZE = 4096; - - /** Size of the ICMPv6 header. */ - private static final int ICMP_HEADER_SIZE = 8; - - /** Number of packets to test. */ - private static final int NUM_PACKETS = 10; - - /** The beginning of an ICMPv6 echo request: type, code, and uninitialized checksum. */ - private static final byte[] PING_HEADER = new byte[] { - (byte) ICMP6_ECHO_REQUEST, (byte) 0x00, (byte) 0x00, (byte) 0x00 - }; - - /** - * Returns a byte array containing an ICMPv6 echo request with the specified payload length. - */ - private byte[] pingPacket(int payloadLength) { - byte[] packet = new byte[payloadLength + ICMP_HEADER_SIZE]; - new Random().nextBytes(packet); - System.arraycopy(PING_HEADER, 0, packet, 0, PING_HEADER.length); - return packet; - } - - /** - * Checks that the first length bytes of two byte arrays are equal. - */ - private void assertArrayBytesEqual(byte[] expected, byte[] actual, int length) { - for (int i = 0; i < length; i++) { - assertEquals("Arrays differ at index " + i + ":", expected[i], actual[i]); - } - } - - /** - * Creates an IPv6 ping socket and sets a receive timeout of 100ms. - */ - private FileDescriptor createPingSocket() throws ErrnoException { - FileDescriptor s = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); - Os.setsockoptTimeval(s, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(100)); - return s; - } - - /** - * Sends a ping packet to a random port on the specified address on the specified socket. - */ - private void sendPing(FileDescriptor s, - InetAddress address, byte[] packet) throws ErrnoException, IOException { - // Pick a random port. Choose a range that gives a reasonable chance of picking a low port. - int port = (int) (Math.random() * 2048); - - // Send the packet. - int ret = Os.sendto(s, ByteBuffer.wrap(packet), 0, address, port); - assertEquals(packet.length, ret); - } - - /** - * Checks that a socket has received a response appropriate to the specified packet. - */ - private void checkResponse(FileDescriptor s, InetAddress dest, - byte[] sent, boolean useRecvfrom) throws ErrnoException, IOException { - ByteBuffer responseBuffer = ByteBuffer.allocate(MAX_SIZE); - int bytesRead; - - // Receive the response. - if (useRecvfrom) { - InetSocketAddress from = new InetSocketAddress(); - bytesRead = Os.recvfrom(s, responseBuffer, 0, from); - - // Check the source address and scope ID. - assertTrue(from.getAddress() instanceof Inet6Address); - Inet6Address fromAddress = (Inet6Address) from.getAddress(); - assertEquals(0, fromAddress.getScopeId()); - assertNull(fromAddress.getScopedInterface()); - assertEquals(dest.getHostAddress(), fromAddress.getHostAddress()); - } else { - bytesRead = Os.read(s, responseBuffer); - } - - // Check the packet length. - assertEquals(sent.length, bytesRead); - - // Check the response is an echo reply. - byte[] response = new byte[bytesRead]; - responseBuffer.flip(); - responseBuffer.get(response, 0, bytesRead); - assertEquals((byte) ICMP6_ECHO_REPLY, response[0]); - - // Find out what ICMP ID was used in the packet that was sent. - int id = ((InetSocketAddress) Os.getsockname(s)).getPort(); - sent[4] = (byte) (id / 256); - sent[5] = (byte) (id % 256); - - // Ensure the response is the same as the packet, except for the type (which is 0x81) - // and the ID and checksum, which are set by the kernel. - response[0] = (byte) 0x80; // Type. - response[2] = response[3] = (byte) 0x00; // Checksum. - assertArrayBytesEqual(response, sent, bytesRead); - } - - /** - * Sends NUM_PACKETS random ping packets to ::1 and checks the replies. - */ - public void testLoopbackPing() throws ErrnoException, IOException { - // Generate a random ping packet and send it to localhost. - InetAddress ipv6Loopback = InetAddress.getByName(null); - assertEquals("::1", ipv6Loopback.getHostAddress()); - - for (int i = 0; i < NUM_PACKETS; i++) { - byte[] packet = pingPacket((int) (Math.random() * (MAX_SIZE - ICMP_HEADER_SIZE))); - FileDescriptor s = createPingSocket(); - // Use both recvfrom and read(). - sendPing(s, ipv6Loopback, packet); - checkResponse(s, ipv6Loopback, packet, true); - sendPing(s, ipv6Loopback, packet); - checkResponse(s, ipv6Loopback, packet, false); - // Check closing the socket doesn't raise an exception. - Os.close(s); - } - } -} diff --git a/tests/cts/net/src/android/net/rtp/cts/AudioCodecTest.java b/tests/cts/net/src/android/net/rtp/cts/AudioCodecTest.java deleted file mode 100644 index 412498c309..0000000000 --- a/tests/cts/net/src/android/net/rtp/cts/AudioCodecTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2012 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.rtp.cts; - -import android.net.rtp.AudioCodec; -import android.test.AndroidTestCase; - -public class AudioCodecTest extends AndroidTestCase { - - private void assertEquals(AudioCodec codec, int type, String rtpmap, String fmtp) { - if (type >= 0) { - assertEquals(codec.type, type); - } else { - assertTrue(codec.type >= 96 && codec.type <= 127); - } - assertEquals(codec.rtpmap.compareToIgnoreCase(rtpmap), 0); - assertEquals(codec.fmtp, fmtp); - } - - public void testConstants() throws Exception { - assertEquals(AudioCodec.PCMU, 0, "PCMU/8000", null); - assertEquals(AudioCodec.PCMA, 8, "PCMA/8000", null); - assertEquals(AudioCodec.GSM, 3, "GSM/8000", null); - assertEquals(AudioCodec.GSM_EFR, -1, "GSM-EFR/8000", null); - assertEquals(AudioCodec.AMR, -1, "AMR/8000", null); - - assertFalse(AudioCodec.AMR.type == AudioCodec.GSM_EFR.type); - } - - public void testGetCodec() throws Exception { - // Bad types. - assertNull(AudioCodec.getCodec(128, "PCMU/8000", null)); - assertNull(AudioCodec.getCodec(-1, "PCMU/8000", null)); - assertNull(AudioCodec.getCodec(96, null, null)); - - // Fixed types. - assertEquals(AudioCodec.getCodec(0, null, null), 0, "PCMU/8000", null); - assertEquals(AudioCodec.getCodec(8, null, null), 8, "PCMA/8000", null); - assertEquals(AudioCodec.getCodec(3, null, null), 3, "GSM/8000", null); - - // Dynamic types. - assertEquals(AudioCodec.getCodec(96, "pcmu/8000", null), 96, "PCMU/8000", null); - assertEquals(AudioCodec.getCodec(97, "pcma/8000", null), 97, "PCMA/8000", null); - assertEquals(AudioCodec.getCodec(98, "gsm/8000", null), 98, "GSM/8000", null); - assertEquals(AudioCodec.getCodec(99, "gsm-efr/8000", null), 99, "GSM-EFR/8000", null); - assertEquals(AudioCodec.getCodec(100, "amr/8000", null), 100, "AMR/8000", null); - } - - public void testGetCodecs() throws Exception { - AudioCodec[] codecs = AudioCodec.getCodecs(); - assertTrue(codecs.length >= 5); - - // The types of the codecs should be different. - boolean[] types = new boolean[128]; - for (AudioCodec codec : codecs) { - assertFalse(types[codec.type]); - types[codec.type] = true; - } - } -} diff --git a/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java b/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java deleted file mode 100644 index fc78e96e11..0000000000 --- a/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2012 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.rtp.cts; - -import android.content.Context; -import android.media.AudioManager; -import android.net.rtp.AudioCodec; -import android.net.rtp.AudioGroup; -import android.net.rtp.AudioStream; -import android.net.rtp.RtpStream; -import android.os.Build; -import android.platform.test.annotations.AppModeFull; -import android.test.AndroidTestCase; - -import androidx.core.os.BuildCompat; - -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; - -@AppModeFull(reason = "RtpStream cannot create in instant app mode") -public class AudioGroupTest extends AndroidTestCase { - - private static final String TAG = AudioGroupTest.class.getSimpleName(); - - private AudioManager mAudioManager; - - private AudioStream mStreamA; - private DatagramSocket mSocketA; - private AudioStream mStreamB; - private DatagramSocket mSocketB; - private AudioGroup mGroup; - - @Override - public void setUp() throws Exception { - mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); - - InetAddress local = InetAddress.getByName("::1"); - - mStreamA = new AudioStream(local); - mStreamA.setMode(RtpStream.MODE_NORMAL); - mStreamA.setCodec(AudioCodec.PCMU); - mSocketA = new DatagramSocket(); - mSocketA.connect(mStreamA.getLocalAddress(), mStreamA.getLocalPort()); - mStreamA.associate(mSocketA.getLocalAddress(), mSocketA.getLocalPort()); - - mStreamB = new AudioStream(local); - mStreamB.setMode(RtpStream.MODE_NORMAL); - mStreamB.setCodec(AudioCodec.PCMU); - mSocketB = new DatagramSocket(); - mSocketB.connect(mStreamB.getLocalAddress(), mStreamB.getLocalPort()); - mStreamB.associate(mSocketB.getLocalAddress(), mSocketB.getLocalPort()); - - // BuildCompat.isAtLeastR is documented to return false on release SDKs (including R) - mGroup = Build.VERSION.SDK_INT > Build.VERSION_CODES.Q || BuildCompat.isAtLeastR() - ? new AudioGroup(mContext) - : new AudioGroup(); // Constructor with context argument was introduced in R - } - - @Override - public void tearDown() throws Exception { - mGroup.clear(); - mStreamA.release(); - mSocketA.close(); - mStreamB.release(); - mSocketB.close(); - mAudioManager.setMode(AudioManager.MODE_NORMAL); - } - - private void assertPacket(DatagramSocket socket, int length) throws Exception { - DatagramPacket packet = new DatagramPacket(new byte[length + 1], length + 1); - socket.setSoTimeout(3000); - socket.receive(packet); - assertEquals(packet.getLength(), length); - } - - private void drain(DatagramSocket socket) throws Exception { - DatagramPacket packet = new DatagramPacket(new byte[1], 1); - socket.setSoTimeout(1); - try { - // Drain the socket by retrieving all the packets queued on it. - // A SocketTimeoutException will be thrown when it becomes empty. - while (true) { - socket.receive(packet); - } - } catch (Exception e) { - // ignore. - } - } - - public void testTraffic() throws Exception { - mStreamA.join(mGroup); - assertPacket(mSocketA, 12 + 160); - - mStreamB.join(mGroup); - assertPacket(mSocketB, 12 + 160); - - mStreamA.join(null); - drain(mSocketA); - - drain(mSocketB); - assertPacket(mSocketB, 12 + 160); - - mStreamA.join(mGroup); - assertPacket(mSocketA, 12 + 160); - } - - public void testSetMode() throws Exception { - mGroup.setMode(AudioGroup.MODE_NORMAL); - assertEquals(mGroup.getMode(), AudioGroup.MODE_NORMAL); - - mGroup.setMode(AudioGroup.MODE_MUTED); - assertEquals(mGroup.getMode(), AudioGroup.MODE_MUTED); - - mStreamA.join(mGroup); - mStreamB.join(mGroup); - - mGroup.setMode(AudioGroup.MODE_NORMAL); - assertEquals(mGroup.getMode(), AudioGroup.MODE_NORMAL); - - mGroup.setMode(AudioGroup.MODE_MUTED); - assertEquals(mGroup.getMode(), AudioGroup.MODE_MUTED); - } - - public void testAdd() throws Exception { - mStreamA.join(mGroup); - assertEquals(mGroup.getStreams().length, 1); - - mStreamB.join(mGroup); - assertEquals(mGroup.getStreams().length, 2); - - mStreamA.join(mGroup); - assertEquals(mGroup.getStreams().length, 2); - } - - public void testRemove() throws Exception { - mStreamA.join(mGroup); - assertEquals(mGroup.getStreams().length, 1); - - mStreamA.join(null); - assertEquals(mGroup.getStreams().length, 0); - - mStreamA.join(mGroup); - assertEquals(mGroup.getStreams().length, 1); - } - - public void testClear() throws Exception { - mStreamA.join(mGroup); - mStreamB.join(mGroup); - mGroup.clear(); - - assertEquals(mGroup.getStreams().length, 0); - assertFalse(mStreamA.isBusy()); - assertFalse(mStreamB.isBusy()); - } - - public void testDoubleClear() throws Exception { - mStreamA.join(mGroup); - mStreamB.join(mGroup); - mGroup.clear(); - mGroup.clear(); - } -} diff --git a/tests/cts/net/src/android/net/rtp/cts/AudioStreamTest.java b/tests/cts/net/src/android/net/rtp/cts/AudioStreamTest.java deleted file mode 100644 index f2db6ee9c4..0000000000 --- a/tests/cts/net/src/android/net/rtp/cts/AudioStreamTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2012 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.rtp.cts; - -import android.net.rtp.AudioCodec; -import android.net.rtp.AudioStream; -import android.platform.test.annotations.AppModeFull; -import android.test.AndroidTestCase; - -import java.net.InetAddress; - -@AppModeFull(reason = "RtpStream cannot create in instant app mode") -public class AudioStreamTest extends AndroidTestCase { - - private void testRtpStream(InetAddress address) throws Exception { - AudioStream stream = new AudioStream(address); - assertEquals(stream.getLocalAddress(), address); - assertEquals(stream.getLocalPort() % 2, 0); - - assertNull(stream.getRemoteAddress()); - assertEquals(stream.getRemotePort(), -1); - stream.associate(address, 1000); - assertEquals(stream.getRemoteAddress(), address); - assertEquals(stream.getRemotePort(), 1000); - - assertFalse(stream.isBusy()); - stream.release(); - } - - public void testV4Stream() throws Exception { - testRtpStream(InetAddress.getByName("127.0.0.1")); - } - - public void testV6Stream() throws Exception { - testRtpStream(InetAddress.getByName("::1")); - } - - public void testSetDtmfType() throws Exception { - AudioStream stream = new AudioStream(InetAddress.getByName("::1")); - - assertEquals(stream.getDtmfType(), -1); - try { - stream.setDtmfType(0); - fail("Expecting IllegalArgumentException"); - } catch (IllegalArgumentException e) { - // ignore - } - stream.setDtmfType(96); - assertEquals(stream.getDtmfType(), 96); - - stream.setCodec(AudioCodec.getCodec(97, "PCMU/8000", null)); - try { - stream.setDtmfType(97); - fail("Expecting IllegalArgumentException"); - } catch (IllegalArgumentException e) { - // ignore - } - stream.release(); - } - - public void testSetCodec() throws Exception { - AudioStream stream = new AudioStream(InetAddress.getByName("::1")); - - assertNull(stream.getCodec()); - stream.setCodec(AudioCodec.getCodec(97, "PCMU/8000", null)); - assertNotNull(stream.getCodec()); - - stream.setDtmfType(96); - try { - stream.setCodec(AudioCodec.getCodec(96, "PCMU/8000", null)); - fail("Expecting IllegalArgumentException"); - } catch (IllegalArgumentException e) { - // ignore - } - stream.release(); - } - - public void testDoubleRelease() throws Exception { - AudioStream stream = new AudioStream(InetAddress.getByName("::1")); - stream.release(); - stream.release(); - } -} diff --git a/tests/cts/net/util/Android.bp b/tests/cts/net/util/Android.bp deleted file mode 100644 index c36d976423..0000000000 --- a/tests/cts/net/util/Android.bp +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (C) 2019 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. -// - -// Common utilities for cts net tests. -java_library { - name: "cts-net-utils", - srcs: ["java/**/*.java", "java/**/*.kt"], - static_libs: [ - "compatibility-device-util-axt", - "junit", - "net-tests-utils", - ], -} \ No newline at end of file diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java deleted file mode 100644 index 34c65416b4..0000000000 --- a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Copyright (C) 2019 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.cts.util; - -import static android.Manifest.permission.NETWORK_SETTINGS; -import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_TEST; -import static android.net.wifi.WifiManager.SCAN_RESULTS_AVAILABLE_ACTION; - -import static com.android.testutils.TestPermissionUtil.runAsShell; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import android.annotation.NonNull; -import android.app.AppOpsManager; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; -import android.net.LinkProperties; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkInfo; -import android.net.NetworkInfo.State; -import android.net.NetworkRequest; -import android.net.TestNetworkManager; -import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; -import android.os.SystemProperties; -import android.provider.Settings; -import android.system.Os; -import android.system.OsConstants; -import android.util.Log; - -import com.android.compatibility.common.util.SystemUtil; - -import junit.framework.AssertionFailedError; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public final class CtsNetUtils { - private static final String TAG = CtsNetUtils.class.getSimpleName(); - private static final int DURATION = 10000; - private static final int SOCKET_TIMEOUT_MS = 2000; - private static final int PRIVATE_DNS_PROBE_MS = 1_000; - - private static final int PRIVATE_DNS_SETTING_TIMEOUT_MS = 10_000; - private static final int CONNECTIVITY_CHANGE_TIMEOUT_SECS = 30; - public static final int HTTP_PORT = 80; - public static final String TEST_HOST = "connectivitycheck.gstatic.com"; - public static final String HTTP_REQUEST = - "GET /generate_204 HTTP/1.0\r\n" + - "Host: " + TEST_HOST + "\r\n" + - "Connection: keep-alive\r\n\r\n"; - // Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent. - public static final String NETWORK_CALLBACK_ACTION = - "ConnectivityManagerTest.NetworkCallbackAction"; - - private final IBinder mBinder = new Binder(); - private final Context mContext; - private final ConnectivityManager mCm; - private final ContentResolver mCR; - private final WifiManager mWifiManager; - private TestNetworkCallback mCellNetworkCallback; - private String mOldPrivateDnsMode; - private String mOldPrivateDnsSpecifier; - - public CtsNetUtils(Context context) { - mContext = context; - mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - mCR = context.getContentResolver(); - } - - /** Checks if FEATURE_IPSEC_TUNNELS is enabled on the device */ - public boolean hasIpsecTunnelsFeature() { - return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS) - || SystemProperties.getInt("ro.product.first_api_level", 0) - >= Build.VERSION_CODES.Q; - } - - /** - * Sets the given appop using shell commands - * - *

Expects caller to hold the shell permission identity. - */ - public void setAppopPrivileged(int appop, boolean allow) { - final String opName = AppOpsManager.opToName(appop); - for (final String pkg : new String[] {"com.android.shell", mContext.getPackageName()}) { - final String cmd = - String.format( - "appops set %s %s %s", - pkg, // Package name - opName, // Appop - (allow ? "allow" : "deny")); // Action - SystemUtil.runShellCommand(cmd); - } - } - - /** Sets up a test network using the provided interface name */ - public TestNetworkCallback setupAndGetTestNetwork(String ifname) throws Exception { - // Build a network request - final NetworkRequest nr = - new NetworkRequest.Builder() - .clearCapabilities() - .addTransportType(TRANSPORT_TEST) - .setNetworkSpecifier(ifname) - .build(); - - final TestNetworkCallback cb = new TestNetworkCallback(); - mCm.requestNetwork(nr, cb); - - // Setup the test network after network request is filed to prevent Network from being - // reaped due to no requests matching it. - mContext.getSystemService(TestNetworkManager.class).setupTestNetwork(ifname, mBinder); - - return cb; - } - - // Toggle WiFi twice, leaving it in the state it started in - public void toggleWifi() { - if (mWifiManager.isWifiEnabled()) { - Network wifiNetwork = getWifiNetwork(); - disconnectFromWifi(wifiNetwork); - connectToWifi(); - } else { - connectToWifi(); - Network wifiNetwork = getWifiNetwork(); - disconnectFromWifi(wifiNetwork); - } - } - - /** - * Enable WiFi and wait for it to become connected to a network. - * - * This method expects to receive a legacy broadcast on connect, which may not be sent if the - * network does not become default or if it is not the first network. - */ - public Network connectToWifi() { - return connectToWifi(true /* expectLegacyBroadcast */); - } - - /** - * Enable WiFi and wait for it to become connected to a network. - * - * A network is considered connected when a {@link NetworkRequest} with TRANSPORT_WIFI - * receives a {@link NetworkCallback#onAvailable(Network)} callback. - */ - public Network ensureWifiConnected() { - return connectToWifi(false /* expectLegacyBroadcast */); - } - - /** - * Enable WiFi and wait for it to become connected to a network. - * - * @param expectLegacyBroadcast Whether to check for a legacy CONNECTIVITY_ACTION connected - * broadcast. The broadcast is typically not sent if the network - * does not become the default network, and is not the first - * network to appear. - * @return The network that was newly connected. - */ - private Network connectToWifi(boolean expectLegacyBroadcast) { - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback); - Network wifiNetwork = null; - - ConnectivityActionReceiver receiver = new ConnectivityActionReceiver( - mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.CONNECTED); - IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - mContext.registerReceiver(receiver, filter); - - boolean connected = false; - final String err = "Wifi must be configured to connect to an access point for this test."; - try { - clearWifiBlacklist(); - SystemUtil.runShellCommand("svc wifi enable"); - final WifiConfiguration config = maybeAddVirtualWifiConfiguration(); - if (config == null) { - // TODO: this may not clear the BSSID blacklist, as opposed to - // mWifiManager.connect(config) - assertTrue("Error reconnecting wifi", runAsShell(NETWORK_SETTINGS, - mWifiManager::reconnect)); - } else { - // When running CTS, devices are expected to have wifi networks pre-configured. - // This condition is only hit on virtual devices. - final Integer error = runAsShell(NETWORK_SETTINGS, () -> { - final ConnectWifiListener listener = new ConnectWifiListener(); - mWifiManager.connect(config, listener); - return listener.connectFuture.get( - CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS); - }); - assertNull("Error connecting to wifi: " + error, error); - } - // Ensure we get an onAvailable callback and possibly a CONNECTIVITY_ACTION. - wifiNetwork = callback.waitForAvailable(); - assertNotNull(err, wifiNetwork); - connected = !expectLegacyBroadcast || receiver.waitForState(); - } catch (InterruptedException ex) { - fail("connectToWifi was interrupted"); - } finally { - mCm.unregisterNetworkCallback(callback); - mContext.unregisterReceiver(receiver); - } - - assertTrue(err, connected); - return wifiNetwork; - } - - private static class ConnectWifiListener implements WifiManager.ActionListener { - /** - * Future completed when the connect process ends. Provides the error code or null if none. - */ - final CompletableFuture connectFuture = new CompletableFuture<>(); - @Override - public void onSuccess() { - connectFuture.complete(null); - } - - @Override - public void onFailure(int reason) { - connectFuture.complete(reason); - } - } - - private WifiConfiguration maybeAddVirtualWifiConfiguration() { - final List configs = runAsShell(NETWORK_SETTINGS, - mWifiManager::getConfiguredNetworks); - // If no network is configured, add a config for virtual access points if applicable - if (configs.size() == 0) { - final List scanResults = getWifiScanResults(); - final WifiConfiguration virtualConfig = maybeConfigureVirtualNetwork(scanResults); - assertNotNull("The device has no configured wifi network", virtualConfig); - - return virtualConfig; - } - // No need to add a configuration: there is already one - return null; - } - - private List getWifiScanResults() { - final CompletableFuture> scanResultsFuture = new CompletableFuture<>(); - runAsShell(NETWORK_SETTINGS, () -> { - final BroadcastReceiver receiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - scanResultsFuture.complete(mWifiManager.getScanResults()); - } - }; - mContext.registerReceiver(receiver, new IntentFilter(SCAN_RESULTS_AVAILABLE_ACTION)); - mWifiManager.startScan(); - }); - - try { - return scanResultsFuture.get(CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS); - } catch (ExecutionException | InterruptedException | TimeoutException e) { - throw new AssertionFailedError("Wifi scan results not received within timeout"); - } - } - - /** - * If a virtual wifi network is detected, add a configuration for that network. - * TODO(b/158150376): have the test infrastructure add virtual wifi networks when appropriate. - */ - private WifiConfiguration maybeConfigureVirtualNetwork(List scanResults) { - // Virtual wifi networks used on the emulator and cloud testing infrastructure - final List virtualSsids = Arrays.asList("VirtWifi", "AndroidWifi"); - Log.d(TAG, "Wifi scan results: " + scanResults); - final ScanResult virtualScanResult = scanResults.stream().filter( - s -> virtualSsids.contains(s.SSID)).findFirst().orElse(null); - - // Only add the virtual configuration if the virtual AP is detected in scans - if (virtualScanResult == null) return null; - - final WifiConfiguration virtualConfig = new WifiConfiguration(); - // ASCII SSIDs need to be surrounded by double quotes - virtualConfig.SSID = "\"" + virtualScanResult.SSID + "\""; - virtualConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - - runAsShell(NETWORK_SETTINGS, () -> { - final int networkId = mWifiManager.addNetwork(virtualConfig); - assertTrue(networkId >= 0); - assertTrue(mWifiManager.enableNetwork(networkId, false /* attemptConnect */)); - }); - return virtualConfig; - } - - /** - * Re-enable wifi networks that were blacklisted, typically because no internet connection was - * detected the last time they were connected. This is necessary to make sure wifi can reconnect - * to them. - */ - private void clearWifiBlacklist() { - runAsShell(NETWORK_SETTINGS, () -> { - for (WifiConfiguration cfg : mWifiManager.getConfiguredNetworks()) { - assertTrue(mWifiManager.enableNetwork(cfg.networkId, false /* attemptConnect */)); - } - }); - } - - /** - * Disable WiFi and wait for it to become disconnected from the network. - * - * This method expects to receive a legacy broadcast on disconnect, which may not be sent if the - * network was not default, or was not the first network. - * - * @param wifiNetworkToCheck If non-null, a network that should be disconnected. This network - * is expected to be able to establish a TCP connection to a remote - * server before disconnecting, and to have that connection closed in - * the process. - */ - public void disconnectFromWifi(Network wifiNetworkToCheck) { - disconnectFromWifi(wifiNetworkToCheck, true /* expectLegacyBroadcast */); - } - - /** - * Disable WiFi and wait for it to become disconnected from the network. - * - * @param wifiNetworkToCheck If non-null, a network that should be disconnected. This network - * is expected to be able to establish a TCP connection to a remote - * server before disconnecting, and to have that connection closed in - * the process. - */ - public void ensureWifiDisconnected(Network wifiNetworkToCheck) { - disconnectFromWifi(wifiNetworkToCheck, false /* expectLegacyBroadcast */); - } - - /** - * Disable WiFi and wait for it to become disconnected from the network. - * - * @param wifiNetworkToCheck If non-null, a network that should be disconnected. This network - * is expected to be able to establish a TCP connection to a remote - * server before disconnecting, and to have that connection closed in - * the process. - * @param expectLegacyBroadcast Whether to check for a legacy CONNECTIVITY_ACTION disconnected - * broadcast. The broadcast is typically not sent if the network - * was not the default network and not the first network to appear. - * The check will always be skipped if the device was not connected - * to wifi in the first place. - */ - private void disconnectFromWifi(Network wifiNetworkToCheck, boolean expectLegacyBroadcast) { - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback); - - ConnectivityActionReceiver receiver = new ConnectivityActionReceiver( - mCm, ConnectivityManager.TYPE_WIFI, NetworkInfo.State.DISCONNECTED); - IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - mContext.registerReceiver(receiver, filter); - - final WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); - final boolean wasWifiConnected = wifiInfo != null && wifiInfo.getNetworkId() != -1; - // Assert that we can establish a TCP connection on wifi. - Socket wifiBoundSocket = null; - if (wifiNetworkToCheck != null) { - assertTrue("Cannot check network " + wifiNetworkToCheck + ": wifi is not connected", - wasWifiConnected); - final NetworkCapabilities nc = mCm.getNetworkCapabilities(wifiNetworkToCheck); - assertNotNull("Network " + wifiNetworkToCheck + " is not connected", nc); - try { - wifiBoundSocket = getBoundSocket(wifiNetworkToCheck, TEST_HOST, HTTP_PORT); - testHttpRequest(wifiBoundSocket); - } catch (IOException e) { - fail("HTTP request before wifi disconnected failed with: " + e); - } - } - - try { - SystemUtil.runShellCommand("svc wifi disable"); - if (wasWifiConnected) { - // Ensure we get both an onLost callback and a CONNECTIVITY_ACTION. - assertNotNull("Did not receive onLost callback after disabling wifi", - callback.waitForLost()); - } - if (wasWifiConnected && expectLegacyBroadcast) { - assertTrue("Wifi failed to reach DISCONNECTED state.", receiver.waitForState()); - } - } catch (InterruptedException ex) { - fail("disconnectFromWifi was interrupted"); - } finally { - mCm.unregisterNetworkCallback(callback); - mContext.unregisterReceiver(receiver); - } - - // Check that the socket is closed when wifi disconnects. - if (wifiBoundSocket != null) { - try { - testHttpRequest(wifiBoundSocket); - fail("HTTP request should not succeed after wifi disconnects"); - } catch (IOException expected) { - assertEquals(Os.strerror(OsConstants.ECONNABORTED), expected.getMessage()); - } - } - } - - public Network getWifiNetwork() { - TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerNetworkCallback(makeWifiNetworkRequest(), callback); - Network network = null; - try { - network = callback.waitForAvailable(); - } catch (InterruptedException e) { - fail("NetworkCallback wait was interrupted."); - } finally { - mCm.unregisterNetworkCallback(callback); - } - assertNotNull("Cannot find Network for wifi. Is wifi connected?", network); - return network; - } - - public Network connectToCell() throws InterruptedException { - if (cellConnectAttempted()) { - throw new IllegalStateException("Already connected"); - } - NetworkRequest cellRequest = new NetworkRequest.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .addCapability(NET_CAPABILITY_INTERNET) - .build(); - mCellNetworkCallback = new TestNetworkCallback(); - mCm.requestNetwork(cellRequest, mCellNetworkCallback); - final Network cellNetwork = mCellNetworkCallback.waitForAvailable(); - assertNotNull("Cell network not available. " + - "Please ensure the device has working mobile data.", cellNetwork); - return cellNetwork; - } - - public void disconnectFromCell() { - if (!cellConnectAttempted()) { - throw new IllegalStateException("Cell connection not attempted"); - } - mCm.unregisterNetworkCallback(mCellNetworkCallback); - mCellNetworkCallback = null; - } - - public boolean cellConnectAttempted() { - return mCellNetworkCallback != null; - } - - private NetworkRequest makeWifiNetworkRequest() { - return new NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .build(); - } - - private void testHttpRequest(Socket s) throws IOException { - OutputStream out = s.getOutputStream(); - InputStream in = s.getInputStream(); - - final byte[] requestBytes = HTTP_REQUEST.getBytes("UTF-8"); - byte[] responseBytes = new byte[4096]; - out.write(requestBytes); - in.read(responseBytes); - assertTrue(new String(responseBytes, "UTF-8").startsWith("HTTP/1.0 204 No Content\r\n")); - } - - private Socket getBoundSocket(Network network, String host, int port) throws IOException { - InetSocketAddress addr = new InetSocketAddress(host, port); - Socket s = network.getSocketFactory().createSocket(); - try { - s.setSoTimeout(SOCKET_TIMEOUT_MS); - s.connect(addr, SOCKET_TIMEOUT_MS); - } catch (IOException e) { - s.close(); - throw e; - } - return s; - } - - public void storePrivateDnsSetting() { - // Store private DNS setting - mOldPrivateDnsMode = Settings.Global.getString(mCR, Settings.Global.PRIVATE_DNS_MODE); - mOldPrivateDnsSpecifier = Settings.Global.getString(mCR, - Settings.Global.PRIVATE_DNS_SPECIFIER); - // It's possible that there is no private DNS default value in Settings. - // Give it a proper default mode which is opportunistic mode. - if (mOldPrivateDnsMode == null) { - mOldPrivateDnsSpecifier = ""; - mOldPrivateDnsMode = PRIVATE_DNS_MODE_OPPORTUNISTIC; - Settings.Global.putString(mCR, - Settings.Global.PRIVATE_DNS_SPECIFIER, mOldPrivateDnsSpecifier); - Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, mOldPrivateDnsMode); - } - } - - public void restorePrivateDnsSetting() throws InterruptedException { - if (mOldPrivateDnsMode == null || mOldPrivateDnsSpecifier == null) { - return; - } - // restore private DNS setting - if ("hostname".equals(mOldPrivateDnsMode)) { - setPrivateDnsStrictMode(mOldPrivateDnsSpecifier); - awaitPrivateDnsSetting("restorePrivateDnsSetting timeout", - mCm.getActiveNetwork(), - mOldPrivateDnsSpecifier, true); - } else { - Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, mOldPrivateDnsMode); - } - } - - public void setPrivateDnsStrictMode(String server) { - // To reduce flake rate, set PRIVATE_DNS_SPECIFIER before PRIVATE_DNS_MODE. This ensures - // that if the previous private DNS mode was not "hostname", the system only sees one - // EVENT_PRIVATE_DNS_SETTINGS_CHANGED event instead of two. - Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_SPECIFIER, server); - final String mode = Settings.Global.getString(mCR, Settings.Global.PRIVATE_DNS_MODE); - // If current private DNS mode is "hostname", we only need to set PRIVATE_DNS_SPECIFIER. - if (!"hostname".equals(mode)) { - Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, "hostname"); - } - } - - public void awaitPrivateDnsSetting(@NonNull String msg, @NonNull Network network, - @NonNull String server, boolean requiresValidatedServers) throws InterruptedException { - CountDownLatch latch = new CountDownLatch(1); - NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); - NetworkCallback callback = new NetworkCallback() { - @Override - public void onLinkPropertiesChanged(Network n, LinkProperties lp) { - if (requiresValidatedServers && lp.getValidatedPrivateDnsServers().isEmpty()) { - return; - } - if (network.equals(n) && server.equals(lp.getPrivateDnsServerName())) { - latch.countDown(); - } - } - }; - mCm.registerNetworkCallback(request, callback); - assertTrue(msg, latch.await(PRIVATE_DNS_SETTING_TIMEOUT_MS, TimeUnit.MILLISECONDS)); - mCm.unregisterNetworkCallback(callback); - // Wait some time for NetworkMonitor's private DNS probe to complete. If we do not do - // this, then the test could complete before the NetworkMonitor private DNS probe - // completes. This would result in tearDown disabling private DNS, and the NetworkMonitor - // private DNS probe getting stuck because there are no longer any private DNS servers to - // query. This then results in the next test not being able to change the private DNS - // setting within the timeout, because the NetworkMonitor thread is blocked in the - // private DNS probe. There is no way to know when the probe has completed: because the - // network is likely already validated, there is no callback that we can listen to, so - // just sleep. - if (requiresValidatedServers) { - Thread.sleep(PRIVATE_DNS_PROBE_MS); - } - } - - /** - * Receiver that captures the last connectivity change's network type and state. Recognizes - * both {@code CONNECTIVITY_ACTION} and {@code NETWORK_CALLBACK_ACTION} intents. - */ - public static class ConnectivityActionReceiver extends BroadcastReceiver { - - private final CountDownLatch mReceiveLatch = new CountDownLatch(1); - - private final int mNetworkType; - private final NetworkInfo.State mNetState; - private final ConnectivityManager mCm; - - public ConnectivityActionReceiver(ConnectivityManager cm, int networkType, - NetworkInfo.State netState) { - this.mCm = cm; - mNetworkType = networkType; - mNetState = netState; - } - - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - NetworkInfo networkInfo = null; - - // When receiving ConnectivityManager.CONNECTIVITY_ACTION, the NetworkInfo parcelable - // is stored in EXTRA_NETWORK_INFO. With a NETWORK_CALLBACK_ACTION, the Network is - // sent in EXTRA_NETWORK and we need to ask the ConnectivityManager for the NetworkInfo. - if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) { - networkInfo = intent.getExtras() - .getParcelable(ConnectivityManager.EXTRA_NETWORK_INFO); - assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK_INFO", - networkInfo); - } else if (NETWORK_CALLBACK_ACTION.equals(action)) { - Network network = intent.getExtras() - .getParcelable(ConnectivityManager.EXTRA_NETWORK); - assertNotNull("ConnectivityActionReceiver expected EXTRA_NETWORK", network); - networkInfo = this.mCm.getNetworkInfo(network); - if (networkInfo == null) { - // When disconnecting, it seems like we get an intent sent with an invalid - // Network; that is, by the time we call ConnectivityManager.getNetworkInfo(), - // it is invalid. Ignore these. - Log.i(TAG, "ConnectivityActionReceiver NETWORK_CALLBACK_ACTION ignoring " - + "invalid network"); - return; - } - } else { - fail("ConnectivityActionReceiver received unxpected intent action: " + action); - } - - assertNotNull("ConnectivityActionReceiver didn't find NetworkInfo", networkInfo); - int networkType = networkInfo.getType(); - State networkState = networkInfo.getState(); - Log.i(TAG, "Network type: " + networkType + " state: " + networkState); - if (networkType == mNetworkType && networkInfo.getState() == mNetState) { - mReceiveLatch.countDown(); - } - } - - public boolean waitForState() throws InterruptedException { - return mReceiveLatch.await(CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS); - } - } - - /** - * Callback used in testRegisterNetworkCallback that allows caller to block on - * {@code onAvailable}. - */ - public static class TestNetworkCallback extends ConnectivityManager.NetworkCallback { - private final CountDownLatch mAvailableLatch = new CountDownLatch(1); - private final CountDownLatch mLostLatch = new CountDownLatch(1); - private final CountDownLatch mUnavailableLatch = new CountDownLatch(1); - - public Network currentNetwork; - public Network lastLostNetwork; - - public Network waitForAvailable() throws InterruptedException { - return mAvailableLatch.await(CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS) - ? currentNetwork : null; - } - - public Network waitForLost() throws InterruptedException { - return mLostLatch.await(CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS) - ? lastLostNetwork : null; - } - - public boolean waitForUnavailable() throws InterruptedException { - return mUnavailableLatch.await(2, TimeUnit.SECONDS); - } - - - @Override - public void onAvailable(Network network) { - currentNetwork = network; - mAvailableLatch.countDown(); - } - - @Override - public void onLost(Network network) { - lastLostNetwork = network; - if (network.equals(currentNetwork)) { - currentNetwork = null; - } - mLostLatch.countDown(); - } - - @Override - public void onUnavailable() { - mUnavailableLatch.countDown(); - } - } -} diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java deleted file mode 100644 index b18c1e72e1..0000000000 --- a/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * 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.cts.util; - -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; -import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; -import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; -import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeTrue; - -import android.content.Context; -import android.net.Network; -import android.net.TetheredClient; -import android.net.TetheringManager; -import android.net.TetheringManager.TetheringEventCallback; -import android.net.TetheringManager.TetheringInterfaceRegexps; -import android.net.TetheringManager.TetheringRequest; -import android.net.wifi.WifiClient; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.SoftApCallback; -import android.os.ConditionVariable; - -import androidx.annotation.NonNull; - -import com.android.net.module.util.ArrayTrackRecord; - -import java.util.Collection; -import java.util.List; - -public final class CtsTetheringUtils { - private TetheringManager mTm; - private WifiManager mWm; - private Context mContext; - - private static final int DEFAULT_TIMEOUT_MS = 60_000; - - public CtsTetheringUtils(Context ctx) { - mContext = ctx; - mTm = mContext.getSystemService(TetheringManager.class); - mWm = mContext.getSystemService(WifiManager.class); - } - - public static class StartTetheringCallback implements TetheringManager.StartTetheringCallback { - private static int TIMEOUT_MS = 30_000; - public static class CallbackValue { - public final int error; - - private CallbackValue(final int e) { - error = e; - } - - public static class OnTetheringStarted extends CallbackValue { - OnTetheringStarted() { super(TETHER_ERROR_NO_ERROR); } - } - - public static class OnTetheringFailed extends CallbackValue { - OnTetheringFailed(final int error) { super(error); } - } - - @Override - public String toString() { - return String.format("%s(%d)", getClass().getSimpleName(), error); - } - } - - private final ArrayTrackRecord.ReadHead mHistory = - new ArrayTrackRecord().newReadHead(); - - @Override - public void onTetheringStarted() { - mHistory.add(new CallbackValue.OnTetheringStarted()); - } - - @Override - public void onTetheringFailed(final int error) { - mHistory.add(new CallbackValue.OnTetheringFailed(error)); - } - - public void verifyTetheringStarted() { - final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true); - assertNotNull("No onTetheringStarted after " + TIMEOUT_MS + " ms", cv); - assertTrue("Fail start tethering:" + cv, - cv instanceof CallbackValue.OnTetheringStarted); - } - - public void expectTetheringFailed(final int expected) throws InterruptedException { - final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true); - assertNotNull("No onTetheringFailed after " + TIMEOUT_MS + " ms", cv); - assertTrue("Expect fail with error code " + expected + ", but received: " + cv, - (cv instanceof CallbackValue.OnTetheringFailed) && (cv.error == expected)); - } - } - - public static boolean isIfaceMatch(final List ifaceRegexs, final List ifaces) { - return isIfaceMatch(ifaceRegexs.toArray(new String[0]), ifaces); - } - - public static boolean isIfaceMatch(final String[] ifaceRegexs, final List ifaces) { - if (ifaceRegexs == null) fail("ifaceRegexs should not be null"); - - if (ifaces == null) return false; - - for (String s : ifaces) { - for (String regex : ifaceRegexs) { - if (s.matches(regex)) { - return true; - } - } - } - return false; - } - - // Must poll the callback before looking at the member. - public static class TestTetheringEventCallback implements TetheringEventCallback { - private static final int TIMEOUT_MS = 30_000; - - public enum CallbackType { - ON_SUPPORTED, - ON_UPSTREAM, - ON_TETHERABLE_REGEX, - ON_TETHERABLE_IFACES, - ON_TETHERED_IFACES, - ON_ERROR, - ON_CLIENTS, - ON_OFFLOAD_STATUS, - }; - - public static class CallbackValue { - public final CallbackType callbackType; - public final Object callbackParam; - public final int callbackParam2; - - private CallbackValue(final CallbackType type, final Object param, final int param2) { - this.callbackType = type; - this.callbackParam = param; - this.callbackParam2 = param2; - } - } - - private final ArrayTrackRecord mHistory = - new ArrayTrackRecord(); - - private final ArrayTrackRecord.ReadHead mCurrent = - mHistory.newReadHead(); - - private TetheringInterfaceRegexps mTetherableRegex; - private List mTetherableIfaces; - private List mTetheredIfaces; - - @Override - public void onTetheringSupported(boolean supported) { - mHistory.add(new CallbackValue(CallbackType.ON_SUPPORTED, null, (supported ? 1 : 0))); - } - - @Override - public void onUpstreamChanged(Network network) { - mHistory.add(new CallbackValue(CallbackType.ON_UPSTREAM, network, 0)); - } - - @Override - public void onTetherableInterfaceRegexpsChanged(TetheringInterfaceRegexps reg) { - mTetherableRegex = reg; - mHistory.add(new CallbackValue(CallbackType.ON_TETHERABLE_REGEX, reg, 0)); - } - - @Override - public void onTetherableInterfacesChanged(List interfaces) { - mTetherableIfaces = interfaces; - mHistory.add(new CallbackValue(CallbackType.ON_TETHERABLE_IFACES, interfaces, 0)); - } - - @Override - public void onTetheredInterfacesChanged(List interfaces) { - mTetheredIfaces = interfaces; - mHistory.add(new CallbackValue(CallbackType.ON_TETHERED_IFACES, interfaces, 0)); - } - - @Override - public void onError(String ifName, int error) { - mHistory.add(new CallbackValue(CallbackType.ON_ERROR, ifName, error)); - } - - @Override - public void onClientsChanged(Collection clients) { - mHistory.add(new CallbackValue(CallbackType.ON_CLIENTS, clients, 0)); - } - - @Override - public void onOffloadStatusChanged(int status) { - mHistory.add(new CallbackValue(CallbackType.ON_OFFLOAD_STATUS, status, 0)); - } - - public void expectTetherableInterfacesChanged(@NonNull List regexs) { - assertNotNull("No expected tetherable ifaces callback", mCurrent.poll(TIMEOUT_MS, - (cv) -> { - if (cv.callbackType != CallbackType.ON_TETHERABLE_IFACES) return false; - final List interfaces = (List) cv.callbackParam; - return isIfaceMatch(regexs, interfaces); - })); - } - - public void expectTetheredInterfacesChanged(@NonNull List regexs) { - assertNotNull("No expected tethered ifaces callback", mCurrent.poll(TIMEOUT_MS, - (cv) -> { - if (cv.callbackType != CallbackType.ON_TETHERED_IFACES) return false; - - final List interfaces = (List) cv.callbackParam; - - // Null regexs means no active tethering. - if (regexs == null) return interfaces.isEmpty(); - - return isIfaceMatch(regexs, interfaces); - })); - } - - public void expectCallbackStarted() { - int receivedBitMap = 0; - // The each bit represent a type from CallbackType.ON_*. - // Expect all of callbacks except for ON_ERROR. - final int expectedBitMap = 0xff ^ (1 << CallbackType.ON_ERROR.ordinal()); - // Receive ON_ERROR on started callback is not matter. It just means tethering is - // failed last time, should able to continue the test this time. - while ((receivedBitMap & expectedBitMap) != expectedBitMap) { - final CallbackValue cv = mCurrent.poll(TIMEOUT_MS, c -> true); - if (cv == null) { - fail("No expected callbacks, " + "expected bitmap: " - + expectedBitMap + ", actual: " + receivedBitMap); - } - - receivedBitMap |= (1 << cv.callbackType.ordinal()); - } - } - - public void expectOneOfOffloadStatusChanged(int... offloadStatuses) { - assertNotNull("No offload status changed", mCurrent.poll(TIMEOUT_MS, (cv) -> { - if (cv.callbackType != CallbackType.ON_OFFLOAD_STATUS) return false; - - final int status = (int) cv.callbackParam; - for (int offloadStatus : offloadStatuses) { - if (offloadStatus == status) return true; - } - - return false; - })); - } - - public void expectErrorOrTethered(final String iface) { - assertNotNull("No expected callback", mCurrent.poll(TIMEOUT_MS, (cv) -> { - if (cv.callbackType == CallbackType.ON_ERROR - && iface.equals((String) cv.callbackParam)) { - return true; - } - if (cv.callbackType == CallbackType.ON_TETHERED_IFACES - && ((List) cv.callbackParam).contains(iface)) { - return true; - } - - return false; - })); - } - - public Network getCurrentValidUpstream() { - final CallbackValue result = mCurrent.poll(TIMEOUT_MS, (cv) -> { - return (cv.callbackType == CallbackType.ON_UPSTREAM) - && cv.callbackParam != null; - }); - - assertNotNull("No valid upstream", result); - return (Network) result.callbackParam; - } - - public void assumeTetheringSupported() { - final ArrayTrackRecord.ReadHead history = - mHistory.newReadHead(); - assertNotNull("No onSupported callback", history.poll(TIMEOUT_MS, (cv) -> { - if (cv.callbackType != CallbackType.ON_SUPPORTED) return false; - - assumeTrue(cv.callbackParam2 == 1 /* supported */); - return true; - })); - } - - public TetheringInterfaceRegexps getTetheringInterfaceRegexps() { - return mTetherableRegex; - } - - public List getTetherableInterfaces() { - return mTetherableIfaces; - } - - public List getTetheredInterfaces() { - return mTetheredIfaces; - } - } - - public TestTetheringEventCallback registerTetheringEventCallback() { - final TestTetheringEventCallback tetherEventCallback = - new TestTetheringEventCallback(); - - mTm.registerTetheringEventCallback(c -> c.run() /* executor */, tetherEventCallback); - tetherEventCallback.expectCallbackStarted(); - - return tetherEventCallback; - } - - public void unregisterTetheringEventCallback(final TestTetheringEventCallback callback) { - mTm.unregisterTetheringEventCallback(callback); - } - - private static List getWifiTetherableInterfaceRegexps( - final TestTetheringEventCallback callback) { - return callback.getTetheringInterfaceRegexps().getTetherableWifiRegexs(); - } - - public static boolean isWifiTetheringSupported(final TestTetheringEventCallback callback) { - return !getWifiTetherableInterfaceRegexps(callback).isEmpty(); - } - - public void startWifiTethering(final TestTetheringEventCallback callback) - throws InterruptedException { - final List wifiRegexs = getWifiTetherableInterfaceRegexps(callback); - assertFalse(isIfaceMatch(wifiRegexs, callback.getTetheredInterfaces())); - - final StartTetheringCallback startTetheringCallback = new StartTetheringCallback(); - final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI) - .setShouldShowEntitlementUi(false).build(); - mTm.startTethering(request, c -> c.run() /* executor */, startTetheringCallback); - startTetheringCallback.verifyTetheringStarted(); - - callback.expectTetheredInterfacesChanged(wifiRegexs); - - callback.expectOneOfOffloadStatusChanged( - TETHER_HARDWARE_OFFLOAD_STARTED, - TETHER_HARDWARE_OFFLOAD_FAILED); - } - - private static class StopSoftApCallback implements SoftApCallback { - private final ConditionVariable mWaiting = new ConditionVariable(); - @Override - public void onStateChanged(int state, int failureReason) { - if (state == WifiManager.WIFI_AP_STATE_DISABLED) mWaiting.open(); - } - - @Override - public void onConnectedClientsChanged(List clients) { } - - public void waitForSoftApStopped() { - if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) { - fail("stopSoftAp Timeout"); - } - } - } - - // Wait for softAp to be disabled. This is necessary on devices where stopping softAp - // deletes the interface. On these devices, tethering immediately stops when the softAp - // interface is removed, but softAp is not yet fully disabled. Wait for softAp to be - // fully disabled, because otherwise the next test might fail because it attempts to - // start softAp before it's fully stopped. - public void expectSoftApDisabled() { - final StopSoftApCallback callback = new StopSoftApCallback(); - try { - mWm.registerSoftApCallback(c -> c.run(), callback); - // registerSoftApCallback will immediately call the callback with the current state, so - // this callback will fire even if softAp is already disabled. - callback.waitForSoftApStopped(); - } finally { - mWm.unregisterSoftApCallback(callback); - } - } - - public void stopWifiTethering(final TestTetheringEventCallback callback) { - mTm.stopTethering(TETHERING_WIFI); - expectSoftApDisabled(); - callback.expectTetheredInterfacesChanged(null); - callback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); - } -} diff --git a/tests/cts/tethering/Android.bp b/tests/cts/tethering/Android.bp deleted file mode 100644 index 85bb0e03f1..0000000000 --- a/tests/cts/tethering/Android.bp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2019 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 { - name: "CtsTetheringTest", - defaults: ["cts_defaults"], - - libs: [ - "android.test.base.stubs", - ], - - srcs: [ - "src/**/*.java", - ], - - static_libs: [ - "TetheringCommonTests", - "TetheringIntegrationTestsLib", - "compatibility-device-util-axt", - "cts-net-utils", - "net-tests-utils", - "ctstestrunner-axt", - "junit", - "junit-params", - ], - - jni_libs: [ - // For mockito extended - "libdexmakerjvmtiagent", - "libstaticjvmtiagent", - ], - - // Change to system current when TetheringManager move to bootclass path. - platform_apis: true, - - // Tag this module as a cts test artifact - test_suites: [ - "cts", - "general-tests", - "mts", - ], - - // Include both the 32 and 64 bit versions - compile_multilib: "both", -} diff --git a/tests/cts/tethering/AndroidManifest.xml b/tests/cts/tethering/AndroidManifest.xml deleted file mode 100644 index 665002e462..0000000000 --- a/tests/cts/tethering/AndroidManifest.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/tests/cts/tethering/AndroidTest.xml b/tests/cts/tethering/AndroidTest.xml deleted file mode 100644 index e752e3a82a..0000000000 --- a/tests/cts/tethering/AndroidTest.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - diff --git a/tests/cts/tethering/OWNERS b/tests/cts/tethering/OWNERS deleted file mode 100644 index cd6abeb6e8..0000000000 --- a/tests/cts/tethering/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# Bug component: 31808 -lorenzo@google.com -satk@google.com - diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java deleted file mode 100644 index 87787b96f7..0000000000 --- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (C) 2019 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.tethering.test; - -import static android.content.pm.PackageManager.FEATURE_TELEPHONY; -import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; -import static android.net.TetheringManager.TETHERING_USB; -import static android.net.TetheringManager.TETHERING_WIFI; -import static android.net.TetheringManager.TETHERING_WIFI_P2P; -import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; -import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; -import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; -import static android.net.cts.util.CtsTetheringUtils.isIfaceMatch; -import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeFalse; -import static org.junit.Assume.assumeTrue; - -import android.app.UiAutomation; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import android.net.LinkAddress; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.TetheringManager; -import android.net.TetheringManager.OnTetheringEntitlementResultListener; -import android.net.TetheringManager.TetheringInterfaceRegexps; -import android.net.TetheringManager.TetheringRequest; -import android.net.cts.util.CtsNetUtils; -import android.net.cts.util.CtsNetUtils.TestNetworkCallback; -import android.net.cts.util.CtsTetheringUtils; -import android.net.cts.util.CtsTetheringUtils.StartTetheringCallback; -import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback; -import android.net.wifi.WifiManager; -import android.os.Bundle; -import android.os.PersistableBundle; -import android.os.ResultReceiver; -import android.telephony.CarrierConfigManager; -import android.telephony.SubscriptionManager; -import android.telephony.TelephonyManager; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -@RunWith(AndroidJUnit4.class) -public class TetheringManagerTest { - - private Context mContext; - - private ConnectivityManager mCm; - private TetheringManager mTM; - private WifiManager mWm; - private PackageManager mPm; - - private TetherChangeReceiver mTetherChangeReceiver; - private CtsNetUtils mCtsNetUtils; - private CtsTetheringUtils mCtsTetheringUtils; - - private static final int DEFAULT_TIMEOUT_MS = 60_000; - - private void adoptShellPermissionIdentity() { - final UiAutomation uiAutomation = - InstrumentationRegistry.getInstrumentation().getUiAutomation(); - uiAutomation.adoptShellPermissionIdentity(); - } - - private void dropShellPermissionIdentity() { - final UiAutomation uiAutomation = - InstrumentationRegistry.getInstrumentation().getUiAutomation(); - uiAutomation.dropShellPermissionIdentity(); - } - - @Before - public void setUp() throws Exception { - adoptShellPermissionIdentity(); - mContext = InstrumentationRegistry.getContext(); - mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - mTM = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE); - mWm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - mPm = mContext.getPackageManager(); - mCtsNetUtils = new CtsNetUtils(mContext); - mCtsTetheringUtils = new CtsTetheringUtils(mContext); - mTetherChangeReceiver = new TetherChangeReceiver(); - final IntentFilter filter = new IntentFilter( - TetheringManager.ACTION_TETHER_STATE_CHANGED); - final Intent intent = mContext.registerReceiver(mTetherChangeReceiver, filter); - if (intent != null) mTetherChangeReceiver.onReceive(null, intent); - } - - @After - public void tearDown() throws Exception { - mTM.stopAllTethering(); - mContext.unregisterReceiver(mTetherChangeReceiver); - dropShellPermissionIdentity(); - } - - private class TetherChangeReceiver extends BroadcastReceiver { - private class TetherState { - final ArrayList mAvailable; - final ArrayList mActive; - final ArrayList mErrored; - - TetherState(Intent intent) { - mAvailable = intent.getStringArrayListExtra( - TetheringManager.EXTRA_AVAILABLE_TETHER); - mActive = intent.getStringArrayListExtra( - TetheringManager.EXTRA_ACTIVE_TETHER); - mErrored = intent.getStringArrayListExtra( - TetheringManager.EXTRA_ERRORED_TETHER); - } - } - - @Override - public void onReceive(Context content, Intent intent) { - String action = intent.getAction(); - if (action.equals(TetheringManager.ACTION_TETHER_STATE_CHANGED)) { - mResult.add(new TetherState(intent)); - } - } - - public final LinkedBlockingQueue mResult = new LinkedBlockingQueue<>(); - - // Expects that tethering reaches the desired state. - // - If active is true, expects that tethering is enabled on at least one interface - // matching ifaceRegexs. - // - If active is false, expects that tethering is disabled on all the interfaces matching - // ifaceRegexs. - // Fails if any interface matching ifaceRegexs becomes errored. - public void expectTethering(final boolean active, final String[] ifaceRegexs) { - while (true) { - final TetherState state = pollAndAssertNoError(DEFAULT_TIMEOUT_MS, ifaceRegexs); - assertNotNull("Did not receive expected state change, active: " + active, state); - - if (isIfaceActive(ifaceRegexs, state) == active) return; - } - } - - private TetherState pollAndAssertNoError(final int timeout, final String[] ifaceRegexs) { - final TetherState state = pollTetherState(timeout); - assertNoErroredIfaces(state, ifaceRegexs); - return state; - } - - private TetherState pollTetherState(final int timeout) { - try { - return mResult.poll(timeout, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - fail("No result after " + timeout + " ms"); - return null; - } - } - - private boolean isIfaceActive(final String[] ifaceRegexs, final TetherState state) { - return isIfaceMatch(ifaceRegexs, state.mActive); - } - - private void assertNoErroredIfaces(final TetherState state, final String[] ifaceRegexs) { - if (state == null || state.mErrored == null) return; - - if (isIfaceMatch(ifaceRegexs, state.mErrored)) { - fail("Found failed tethering interfaces: " + Arrays.toString(state.mErrored.toArray())); - } - } - } - - @Test - public void testStartTetheringWithStateChangeBroadcast() throws Exception { - if (!mTM.isTetheringSupported()) return; - - final String[] wifiRegexs = mTM.getTetherableWifiRegexs(); - if (wifiRegexs.length == 0) return; - - final String[] tetheredIfaces = mTM.getTetheredIfaces(); - assertTrue(tetheredIfaces.length == 0); - - final StartTetheringCallback startTetheringCallback = new StartTetheringCallback(); - final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI) - .setShouldShowEntitlementUi(false).build(); - mTM.startTethering(request, c -> c.run() /* executor */, startTetheringCallback); - startTetheringCallback.verifyTetheringStarted(); - - mTetherChangeReceiver.expectTethering(true /* active */, wifiRegexs); - - mTM.stopTethering(TETHERING_WIFI); - mCtsTetheringUtils.expectSoftApDisabled(); - mTetherChangeReceiver.expectTethering(false /* active */, wifiRegexs); - } - - @Test - public void testTetheringRequest() { - final TetheringRequest tr = new TetheringRequest.Builder(TETHERING_WIFI).build(); - assertEquals(TETHERING_WIFI, tr.getTetheringType()); - assertNull(tr.getLocalIpv4Address()); - assertNull(tr.getClientStaticIpv4Address()); - assertFalse(tr.isExemptFromEntitlementCheck()); - assertTrue(tr.getShouldShowEntitlementUi()); - - final LinkAddress localAddr = new LinkAddress("192.168.24.5/24"); - final LinkAddress clientAddr = new LinkAddress("192.168.24.100/24"); - final TetheringRequest tr2 = new TetheringRequest.Builder(TETHERING_USB) - .setStaticIpv4Addresses(localAddr, clientAddr) - .setExemptFromEntitlementCheck(true) - .setShouldShowEntitlementUi(false).build(); - - assertEquals(localAddr, tr2.getLocalIpv4Address()); - assertEquals(clientAddr, tr2.getClientStaticIpv4Address()); - assertEquals(TETHERING_USB, tr2.getTetheringType()); - assertTrue(tr2.isExemptFromEntitlementCheck()); - assertFalse(tr2.getShouldShowEntitlementUi()); - } - - @Test - public void testRegisterTetheringEventCallback() throws Exception { - final TestTetheringEventCallback tetherEventCallback = - mCtsTetheringUtils.registerTetheringEventCallback(); - tetherEventCallback.assumeTetheringSupported(); - - if (!isWifiTetheringSupported(tetherEventCallback)) { - mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); - return; - } - - mCtsTetheringUtils.startWifiTethering(tetherEventCallback); - - final List tetheredIfaces = tetherEventCallback.getTetheredInterfaces(); - assertEquals(1, tetheredIfaces.size()); - final String wifiTetheringIface = tetheredIfaces.get(0); - - mCtsTetheringUtils.stopWifiTethering(tetherEventCallback); - - try { - final int ret = mTM.tether(wifiTetheringIface); - - // There is no guarantee that the wifi interface will be available after disabling - // the hotspot, so don't fail the test if the call to tether() fails. - assumeTrue(ret == TETHER_ERROR_NO_ERROR); - - // If calling #tether successful, there is a callback to tell the result of tethering - // setup. - tetherEventCallback.expectErrorOrTethered(wifiTetheringIface); - } finally { - mTM.untether(wifiTetheringIface); - mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); - } - } - - @Test - public void testGetTetherableInterfaceRegexps() { - final TestTetheringEventCallback tetherEventCallback = - mCtsTetheringUtils.registerTetheringEventCallback(); - tetherEventCallback.assumeTetheringSupported(); - - final TetheringInterfaceRegexps tetherableRegexs = - tetherEventCallback.getTetheringInterfaceRegexps(); - final List wifiRegexs = tetherableRegexs.getTetherableWifiRegexs(); - final List usbRegexs = tetherableRegexs.getTetherableUsbRegexs(); - final List btRegexs = tetherableRegexs.getTetherableBluetoothRegexs(); - - assertEquals(wifiRegexs, Arrays.asList(mTM.getTetherableWifiRegexs())); - assertEquals(usbRegexs, Arrays.asList(mTM.getTetherableUsbRegexs())); - assertEquals(btRegexs, Arrays.asList(mTM.getTetherableBluetoothRegexs())); - - //Verify that any regex name should only contain in one array. - wifiRegexs.forEach(s -> assertFalse(usbRegexs.contains(s))); - wifiRegexs.forEach(s -> assertFalse(btRegexs.contains(s))); - usbRegexs.forEach(s -> assertFalse(btRegexs.contains(s))); - - mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); - } - - @Test - public void testStopAllTethering() throws Exception { - final TestTetheringEventCallback tetherEventCallback = - mCtsTetheringUtils.registerTetheringEventCallback(); - tetherEventCallback.assumeTetheringSupported(); - - try { - if (!isWifiTetheringSupported(tetherEventCallback)) return; - - // TODO: start ethernet tethering here when TetheringManagerTest is moved to - // TetheringIntegrationTest. - - mCtsTetheringUtils.startWifiTethering(tetherEventCallback); - - mTM.stopAllTethering(); - tetherEventCallback.expectTetheredInterfacesChanged(null); - } finally { - mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); - } - } - - @Test - public void testEnableTetheringPermission() throws Exception { - dropShellPermissionIdentity(); - final StartTetheringCallback startTetheringCallback = new StartTetheringCallback(); - mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(), - c -> c.run() /* executor */, startTetheringCallback); - startTetheringCallback.expectTetheringFailed(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); - } - - private class EntitlementResultListener implements OnTetheringEntitlementResultListener { - private final CompletableFuture future = new CompletableFuture<>(); - - @Override - public void onTetheringEntitlementResult(int result) { - future.complete(result); - } - - public int get(long timeout, TimeUnit unit) throws Exception { - return future.get(timeout, unit); - } - - } - - private void assertEntitlementResult(final Consumer functor, - final int expect) throws Exception { - final EntitlementResultListener listener = new EntitlementResultListener(); - functor.accept(listener); - - assertEquals(expect, listener.get(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } - - @Test - public void testRequestLatestEntitlementResult() throws Exception { - assumeTrue(mTM.isTetheringSupported()); - // Verify that requestLatestTetheringEntitlementResult() can get entitlement - // result(TETHER_ERROR_ENTITLEMENT_UNKNOWN due to invalid downstream type) via listener. - assertEntitlementResult(listener -> mTM.requestLatestTetheringEntitlementResult( - TETHERING_WIFI_P2P, false, c -> c.run(), listener), - TETHER_ERROR_ENTITLEMENT_UNKNOWN); - - // Verify that requestLatestTetheringEntitlementResult() can get entitlement - // result(TETHER_ERROR_ENTITLEMENT_UNKNOWN due to invalid downstream type) via receiver. - assertEntitlementResult(listener -> mTM.requestLatestTetheringEntitlementResult( - TETHERING_WIFI_P2P, - new ResultReceiver(null /* handler */) { - @Override - public void onReceiveResult(int resultCode, Bundle resultData) { - listener.onTetheringEntitlementResult(resultCode); - } - }, false), - TETHER_ERROR_ENTITLEMENT_UNKNOWN); - - // Do not request TETHERING_WIFI entitlement result if TETHERING_WIFI is not available. - assumeTrue(mTM.getTetherableWifiRegexs().length > 0); - - // Verify that null listener will cause IllegalArgumentException. - try { - mTM.requestLatestTetheringEntitlementResult( - TETHERING_WIFI, false, c -> c.run(), null); - } catch (IllegalArgumentException expect) { } - - // Override carrier config to ignore entitlement check. - final PersistableBundle bundle = new PersistableBundle(); - bundle.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, false); - overrideCarrierConfig(bundle); - - // Verify that requestLatestTetheringEntitlementResult() can get entitlement - // result TETHER_ERROR_NO_ERROR due to provisioning bypassed. - assertEntitlementResult(listener -> mTM.requestLatestTetheringEntitlementResult( - TETHERING_WIFI, false, c -> c.run(), listener), TETHER_ERROR_NO_ERROR); - - // Reset carrier config. - overrideCarrierConfig(null); - } - - private void overrideCarrierConfig(PersistableBundle bundle) { - final CarrierConfigManager configManager = (CarrierConfigManager) mContext - .getSystemService(Context.CARRIER_CONFIG_SERVICE); - final int subId = SubscriptionManager.getDefaultSubscriptionId(); - configManager.overrideConfig(subId, bundle); - } - - @Test - public void testTetheringUpstream() throws Exception { - assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); - final TestTetheringEventCallback tetherEventCallback = - mCtsTetheringUtils.registerTetheringEventCallback(); - tetherEventCallback.assumeTetheringSupported(); - final boolean previousWifiEnabledState = mWm.isWifiEnabled(); - - try { - if (!isWifiTetheringSupported(tetherEventCallback)) return; - - if (previousWifiEnabledState) { - mCtsNetUtils.disconnectFromWifi(null); - } - - final TestNetworkCallback networkCallback = new TestNetworkCallback(); - Network activeNetwork = null; - try { - mCm.registerDefaultNetworkCallback(networkCallback); - activeNetwork = networkCallback.waitForAvailable(); - } finally { - mCm.unregisterNetworkCallback(networkCallback); - } - - assertNotNull("No active network. Please ensure the device has working mobile data.", - activeNetwork); - final NetworkCapabilities activeNetCap = mCm.getNetworkCapabilities(activeNetwork); - - // If active nework is ETHERNET, tethering may not use cell network as upstream. - assumeFalse(activeNetCap.hasTransport(TRANSPORT_ETHERNET)); - - assertTrue(activeNetCap.hasTransport(TRANSPORT_CELLULAR)); - - mCtsTetheringUtils.startWifiTethering(tetherEventCallback); - - final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( - Context.TELEPHONY_SERVICE); - final boolean dunRequired = telephonyManager.isTetheringApnRequired(); - final int expectedCap = dunRequired ? NET_CAPABILITY_DUN : NET_CAPABILITY_INTERNET; - final Network network = tetherEventCallback.getCurrentValidUpstream(); - final NetworkCapabilities netCap = mCm.getNetworkCapabilities(network); - assertTrue(netCap.hasTransport(TRANSPORT_CELLULAR)); - assertTrue(netCap.hasCapability(expectedCap)); - - mCtsTetheringUtils.stopWifiTethering(tetherEventCallback); - } finally { - mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); - if (previousWifiEnabledState) { - mCtsNetUtils.connectToWifi(); - } - } - } -}