Merge changes I33bc80cc,Ie84e2cd4
* changes:
EthernetManagerTest: update tests that bring up tap without carrier
TestNetworkService: use IFF_NO_CARRIER to bring up iface without carrier
diff --git a/Cronet/tests/cts/OWNERS b/Cronet/tests/OWNERS
similarity index 100%
rename from Cronet/tests/cts/OWNERS
rename to Cronet/tests/OWNERS
diff --git a/Cronet/tests/common/Android.bp b/Cronet/tests/common/Android.bp
new file mode 100644
index 0000000..5d2f6e5
--- /dev/null
+++ b/Cronet/tests/common/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2023 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.
+//
+
+// Tests in this folder are included both in unit tests and CTS.
+// They must be fast and stable, and exercise public or test APIs.
+
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// TODO: Consider merging with ConnectivityCoverageTests which is a collection of all
+// Connectivity tests being used for coverage. This will depend on how far we decide to
+// go with merging NetHttp and Tethering targets.
+android_test {
+ name: "NetHttpCoverageTests",
+ defaults: ["CronetTestJavaDefaults"],
+ enforce_default_target_sdk_version: true,
+ min_sdk_version: "30",
+ test_suites: ["general-tests", "mts-tethering"],
+ static_libs: [
+ "modules-utils-native-coverage-listener",
+ "CtsNetHttpTestsLib",
+ "NetHttpTestsLibPreJarJar",
+ ],
+ jarjar_rules: ":net-http-test-jarjar-rules",
+ compile_multilib: "both", // Include both the 32 and 64 bit versions
+ jni_libs: [
+ "cronet_aml_components_cronet_android_cronet_tests__testing"
+ ],
+}
diff --git a/Cronet/tests/common/AndroidManifest.xml b/Cronet/tests/common/AndroidManifest.xml
new file mode 100644
index 0000000..b00fc90
--- /dev/null
+++ b/Cronet/tests/common/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.android.net.http.tests.coverage">
+
+ <!-- NetHttpCoverageTests combines CtsNetHttpTestCases and NetHttpTests targets,
+ so permissions and others are declared in their respective manifests -->
+ <application tools:replace="android:label"
+ android:label="NetHttp coverage tests">
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.net.http.tests.coverage"
+ android:label="NetHttp coverage tests">
+ </instrumentation>
+</manifest>
diff --git a/Cronet/tests/common/AndroidTest.xml b/Cronet/tests/common/AndroidTest.xml
new file mode 100644
index 0000000..2ac418f
--- /dev/null
+++ b/Cronet/tests/common/AndroidTest.xml
@@ -0,0 +1,36 @@
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+<configuration description="Runs coverage tests for NetHttp">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="NetHttpCoverageTests.apk" />
+ <option name="install-arg" value="-t" />
+ </target_preparer>
+ <option name="test-tag" value="NetHttpCoverageTests" />
+ <!-- Tethering/Connectivity is a SDK 30+ module -->
+ <!-- TODO Switch back to Sdk30 when b/270049141 is fixed -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.net.http.tests.coverage" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ <option
+ name="device-listeners"
+ value="com.android.modules.utils.testing.NativeCoverageHackInstrumentationListener" />
+ </test>
+</configuration>
diff --git a/Cronet/tests/cts/Android.bp b/Cronet/tests/cts/Android.bp
index 2c28b8d..22eccf9 100644
--- a/Cronet/tests/cts/Android.bp
+++ b/Cronet/tests/cts/Android.bp
@@ -29,6 +29,10 @@
java_defaults {
name: "CronetTestJavaDefaultsEnabled",
enabled: true,
+ // TODO(danstahr): move to unconditional static_libs once the T branch is abandoned
+ static_libs: [
+ "truth",
+ ],
}
java_defaults {
@@ -41,35 +45,44 @@
defaults: [cronet_test_java_defaults],
}
-android_test {
- name: "CtsNetHttpTestCases",
- compile_multilib: "both", // Include both the 32 and 64 bit versions
+android_library {
+ name: "CtsNetHttpTestsLib",
defaults: [
- "CronetTestJavaDefaults",
"cts_defaults",
+ "CronetTestJavaDefaults",
],
sdk_version: "test_current",
+ min_sdk_version: "30",
srcs: [
"src/**/*.java",
"src/**/*.kt",
],
static_libs: [
- "androidx.test.rules",
- "androidx.core_core",
+ "androidx.test.ext.junit",
"ctstestrunner-axt",
"ctstestserver",
"junit",
"hamcrest-library",
+ "kotlin-test",
+ "mockito-target",
],
libs: [
- "android.test.runner",
"android.test.base",
- "android.test.mock",
"androidx.annotation_annotation",
- "framework-tethering",
+ "framework-connectivity",
"org.apache.http.legacy",
],
+ lint: { test: true }
+}
+android_test {
+ name: "CtsNetHttpTestCases",
+ defaults: [
+ "cts_defaults",
+ "CronetTestJavaDefaults",
+ ],
+ sdk_version: "test_current",
+ static_libs: ["CtsNetHttpTestsLib"],
// Tag this as a cts test artifact
test_suites: [
"cts",
diff --git a/Cronet/tests/cts/AndroidManifest.xml b/Cronet/tests/cts/AndroidManifest.xml
index eaa24aa..26900b2 100644
--- a/Cronet/tests/cts/AndroidManifest.xml
+++ b/Cronet/tests/cts/AndroidManifest.xml
@@ -31,7 +31,5 @@
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.net.http.cts"
android:label="CTS tests of android.net.http">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener"/>
</instrumentation>
</manifest>
diff --git a/Cronet/tests/cts/src/android/net/http/cts/BidirectionalStreamTest.kt b/Cronet/tests/cts/src/android/net/http/cts/BidirectionalStreamTest.kt
new file mode 100644
index 0000000..bead1f8
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/BidirectionalStreamTest.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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.http.cts
+
+import android.content.Context
+import android.net.http.BidirectionalStream
+import android.net.http.HttpEngine
+import android.net.http.cts.util.TestBidirectionalStreamCallback
+import android.net.http.cts.util.TestBidirectionalStreamCallback.ResponseStep
+import android.net.http.cts.util.assumeOKStatusCode
+import android.net.http.cts.util.skipIfNoInternetConnection
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import org.hamcrest.MatcherAssert
+import org.hamcrest.Matchers
+import org.junit.After
+import org.junit.Before
+import org.junit.runner.RunWith
+
+private const val URL = "https://source.android.com"
+
+/**
+ * This tests uses a non-hermetic server. Instead of asserting, assume the next callback. This way,
+ * if the request were to fail, the test would just be skipped instead of failing.
+ */
+@RunWith(AndroidJUnit4::class)
+class BidirectionalStreamTest {
+ private val context: Context = ApplicationProvider.getApplicationContext()
+ private val callback = TestBidirectionalStreamCallback()
+ private val httpEngine = HttpEngine.Builder(context).build()
+ private var stream: BidirectionalStream? = null
+
+ @Before
+ fun setUp() {
+ skipIfNoInternetConnection(context)
+ }
+
+ @After
+ @Throws(Exception::class)
+ fun tearDown() {
+ // cancel active requests to enable engine shutdown.
+ stream?.let {
+ it.cancel()
+ callback.blockForDone()
+ }
+ httpEngine.shutdown()
+ }
+
+ private fun createBidirectionalStreamBuilder(url: String): BidirectionalStream.Builder {
+ return httpEngine.newBidirectionalStreamBuilder(url, callback.executor, callback)
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun testBidirectionalStream_GetStream_CompletesSuccessfully() {
+ stream = createBidirectionalStreamBuilder(URL).setHttpMethod("GET").build()
+ stream!!.start()
+ callback.assumeCallback(ResponseStep.ON_SUCCEEDED)
+ val info = callback.mResponseInfo
+ assumeOKStatusCode(info)
+ MatcherAssert.assertThat(
+ "Received byte count must be > 0", info.receivedByteCount, Matchers.greaterThan(0L))
+ assertEquals("h2", info.negotiatedProtocol)
+ }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/CallbackExceptionTest.kt b/Cronet/tests/cts/src/android/net/http/cts/CallbackExceptionTest.kt
new file mode 100644
index 0000000..749389e
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/CallbackExceptionTest.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 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.http.cts
+
+import android.content.Context
+import android.net.http.CallbackException
+import android.net.http.HttpEngine
+import android.net.http.cts.util.HttpCtsTestServer
+import android.net.http.cts.util.TestUrlRequestCallback
+import android.net.http.cts.util.TestUrlRequestCallback.FailureType
+import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertIs
+import kotlin.test.assertSame
+import kotlin.test.assertTrue
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class CallbackExceptionTest {
+
+ @Test
+ fun testCallbackException_returnsInputParameters() {
+ val message = "failed"
+ val cause = Throwable("exception")
+ val callbackException = object : CallbackException(message, cause) {}
+
+ assertEquals(message, callbackException.message)
+ assertSame(cause, callbackException.cause)
+ }
+
+ @Test
+ fun testCallbackException_thrownFromUrlRequest() {
+ val context: Context = ApplicationProvider.getApplicationContext()
+ val server = HttpCtsTestServer(context)
+ val httpEngine = HttpEngine.Builder(context).build()
+ val callback = TestUrlRequestCallback()
+ callback.setFailure(FailureType.THROW_SYNC, ResponseStep.ON_RESPONSE_STARTED)
+ val request = httpEngine
+ .newUrlRequestBuilder(server.successUrl, callback.executor, callback)
+ .build()
+
+ request.start()
+ callback.blockForDone()
+
+ assertTrue(request.isDone)
+ assertIs<CallbackException>(callback.mError)
+ server.shutdown()
+ httpEngine.shutdown()
+ }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt b/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt
new file mode 100644
index 0000000..219db61
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/ConnectionMigrationOptionsTest.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 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.http.cts
+
+import android.net.http.ConnectionMigrationOptions
+import android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_ENABLED
+import android.net.http.ConnectionMigrationOptions.MIGRATION_OPTION_UNSPECIFIED
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ConnectionMigrationOptionsTest {
+
+ @Test
+ fun testConnectionMigrationOptions_defaultValues() {
+ val options =
+ ConnectionMigrationOptions.Builder().build()
+
+ assertEquals(MIGRATION_OPTION_UNSPECIFIED, options.allowNonDefaultNetworkUsage)
+ assertEquals(MIGRATION_OPTION_UNSPECIFIED, options.defaultNetworkMigration)
+ assertEquals(MIGRATION_OPTION_UNSPECIFIED, options.pathDegradationMigration)
+ }
+
+ @Test
+ fun testConnectionMigrationOptions_enableDefaultNetworkMigration_returnSetValue() {
+ val options =
+ ConnectionMigrationOptions.Builder()
+ .setDefaultNetworkMigration(MIGRATION_OPTION_ENABLED)
+ .build()
+
+ assertEquals(MIGRATION_OPTION_ENABLED, options.defaultNetworkMigration)
+ }
+
+ @Test
+ fun testConnectionMigrationOptions_enablePathDegradationMigration_returnSetValue() {
+ val options =
+ ConnectionMigrationOptions.Builder()
+ .setPathDegradationMigration(MIGRATION_OPTION_ENABLED)
+ .build()
+
+ assertEquals(MIGRATION_OPTION_ENABLED, options.pathDegradationMigration)
+ }
+
+ @Test
+ fun testConnectionMigrationOptions_allowNonDefaultNetworkUsage_returnSetValue() {
+ val options =
+ ConnectionMigrationOptions.Builder()
+ .setAllowNonDefaultNetworkUsage(MIGRATION_OPTION_ENABLED).build()
+
+ assertEquals(MIGRATION_OPTION_ENABLED, options.allowNonDefaultNetworkUsage)
+ }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt b/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
new file mode 100644
index 0000000..6f4a979
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2023 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.http.cts
+
+import android.net.http.DnsOptions
+import android.net.http.DnsOptions.DNS_OPTION_ENABLED
+import android.net.http.DnsOptions.DNS_OPTION_UNSPECIFIED
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import java.time.Duration
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+import kotlin.test.assertNull
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class DnsOptionsTest {
+
+ @Test
+ fun testDnsOptions_defaultValues() {
+ val options = DnsOptions.Builder().build()
+
+ assertEquals(DNS_OPTION_UNSPECIFIED, options.persistHostCache)
+ assertNull(options.persistHostCachePeriod)
+ assertEquals(DNS_OPTION_UNSPECIFIED, options.staleDns)
+ assertNull(options.staleDnsOptions)
+ assertEquals(DNS_OPTION_UNSPECIFIED, options.useHttpStackDnsResolver)
+ assertEquals(DNS_OPTION_UNSPECIFIED,
+ options.preestablishConnectionsToStaleDnsResults)
+ }
+
+ @Test
+ fun testDnsOptions_persistHostCache_returnSetValue() {
+ val options = DnsOptions.Builder()
+ .setPersistHostCache(DNS_OPTION_ENABLED)
+ .build()
+
+ assertEquals(DNS_OPTION_ENABLED, options.persistHostCache)
+ }
+
+ @Test
+ fun testDnsOptions_persistHostCachePeriod_returnSetValue() {
+ val period = Duration.ofMillis(12345)
+ val options = DnsOptions.Builder().setPersistHostCachePeriod(period).build()
+
+ assertEquals(period, options.persistHostCachePeriod)
+ }
+
+ @Test
+ fun testDnsOptions_enableStaleDns_returnSetValue() {
+ val options = DnsOptions.Builder()
+ .setStaleDns(DNS_OPTION_ENABLED)
+ .build()
+
+ assertEquals(DNS_OPTION_ENABLED, options.staleDns)
+ }
+
+ @Test
+ fun testDnsOptions_useHttpStackDnsResolver_returnsSetValue() {
+ val options = DnsOptions.Builder()
+ .setUseHttpStackDnsResolver(DNS_OPTION_ENABLED)
+ .build()
+
+ assertEquals(DNS_OPTION_ENABLED, options.useHttpStackDnsResolver)
+ }
+
+ @Test
+ fun testDnsOptions_preestablishConnectionsToStaleDnsResults_returnsSetValue() {
+ val options = DnsOptions.Builder()
+ .setPreestablishConnectionsToStaleDnsResults(DNS_OPTION_ENABLED)
+ .build()
+
+ assertEquals(DNS_OPTION_ENABLED,
+ options.preestablishConnectionsToStaleDnsResults)
+ }
+
+ @Test
+ fun testDnsOptions_setStaleDnsOptions_returnsSetValues() {
+ val staleOptions = DnsOptions.StaleDnsOptions.Builder()
+ .setAllowCrossNetworkUsage(DNS_OPTION_ENABLED)
+ .setFreshLookupTimeout(Duration.ofMillis(1234))
+ .build()
+ val options = DnsOptions.Builder()
+ .setStaleDns(DNS_OPTION_ENABLED)
+ .setStaleDnsOptions(staleOptions)
+ .build()
+
+ assertEquals(DNS_OPTION_ENABLED, options.staleDns)
+ assertEquals(staleOptions, options.staleDnsOptions)
+ }
+
+ @Test
+ fun testStaleDnsOptions_defaultValues() {
+ val options = DnsOptions.StaleDnsOptions.Builder().build()
+
+ assertEquals(DNS_OPTION_UNSPECIFIED, options.allowCrossNetworkUsage)
+ assertNull(options.freshLookupTimeout)
+ assertNull(options.maxExpiredDelay)
+ assertEquals(DNS_OPTION_UNSPECIFIED, options.useStaleOnNameNotResolved)
+ }
+
+ @Test
+ fun testStaleDnsOptions_allowCrossNetworkUsage_returnsSetValue() {
+ val options = DnsOptions.StaleDnsOptions.Builder()
+ .setAllowCrossNetworkUsage(DNS_OPTION_ENABLED).build()
+
+ assertEquals(DNS_OPTION_ENABLED, options.allowCrossNetworkUsage)
+ }
+
+ @Test
+ fun testStaleDnsOptions_freshLookupTimeout_returnsSetValue() {
+ val duration = Duration.ofMillis(12345)
+ val options = DnsOptions.StaleDnsOptions.Builder().setFreshLookupTimeout(duration).build()
+
+ assertNotNull(options.freshLookupTimeout)
+ assertEquals(duration, options.freshLookupTimeout!!)
+ }
+
+ @Test
+ fun testStaleDnsOptions_useStaleOnNameNotResolved_returnsSetValue() {
+ val options = DnsOptions.StaleDnsOptions.Builder()
+ .setUseStaleOnNameNotResolved(DNS_OPTION_ENABLED)
+ .build()
+
+ assertEquals(DNS_OPTION_ENABLED, options.useStaleOnNameNotResolved)
+ }
+
+ @Test
+ fun testStaleDnsOptions_maxExpiredDelayMillis_returnsSetValue() {
+ val duration = Duration.ofMillis(12345)
+ val options = DnsOptions.StaleDnsOptions.Builder().setMaxExpiredDelay(duration).build()
+
+ assertNotNull(options.maxExpiredDelay)
+ assertEquals(duration, options.maxExpiredDelay!!)
+ }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java b/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java
index 6a8467c..ed86854 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/HttpEngineTest.java
@@ -17,27 +17,43 @@
package android.net.http.cts;
import static android.net.http.cts.util.TestUtilsKt.assertOKStatusCode;
+import static android.net.http.cts.util.TestUtilsKt.assumeOKStatusCode;
import static android.net.http.cts.util.TestUtilsKt.skipIfNoInternetConnection;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
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 android.content.Context;
+import android.net.Network;
+import android.net.http.ConnectionMigrationOptions;
+import android.net.http.DnsOptions;
import android.net.http.HttpEngine;
+import android.net.http.QuicOptions;
import android.net.http.UrlRequest;
import android.net.http.UrlResponseInfo;
+import android.net.http.cts.util.HttpCtsTestServer;
import android.net.http.cts.util.TestUrlRequestCallback;
import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Set;
@RunWith(AndroidJUnit4.class)
public class HttpEngineTest {
@@ -46,21 +62,32 @@
private HttpEngine.Builder mEngineBuilder;
private TestUrlRequestCallback mCallback;
+ private HttpCtsTestServer mTestServer;
+ private UrlRequest mRequest;
private HttpEngine mEngine;
+ private Context mContext;
@Before
public void setUp() throws Exception {
- Context context = InstrumentationRegistry.getInstrumentation().getContext();
- skipIfNoInternetConnection(context);
- mEngineBuilder = new HttpEngine.Builder(context);
+ mContext = ApplicationProvider.getApplicationContext();
+ skipIfNoInternetConnection(mContext);
+ mEngineBuilder = new HttpEngine.Builder(mContext);
mCallback = new TestUrlRequestCallback();
+ mTestServer = new HttpCtsTestServer(mContext);
}
@After
public void tearDown() throws Exception {
+ if (mRequest != null) {
+ mRequest.cancel();
+ mCallback.blockForDone();
+ }
if (mEngine != null) {
mEngine.shutdown();
}
+ if (mTestServer != null) {
+ mTestServer.shutdown();
+ }
}
private boolean isQuic(String negotiatedProtocol) {
@@ -71,42 +98,147 @@
public void testHttpEngine_Default() throws Exception {
mEngine = mEngineBuilder.build();
UrlRequest.Builder builder =
- mEngine.newUrlRequestBuilder(URL, mCallback, mCallback.getExecutor());
- builder.build().start();
+ mEngine.newUrlRequestBuilder(URL, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
- mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ // This tests uses a non-hermetic server. Instead of asserting, assume the next callback.
+ // This way, if the request were to fail, the test would just be skipped instead of failing.
+ mCallback.assumeCallback(ResponseStep.ON_SUCCEEDED);
UrlResponseInfo info = mCallback.mResponseInfo;
assertOKStatusCode(info);
assertEquals("h2", info.getNegotiatedProtocol());
}
@Test
+ public void testHttpEngine_EnableHttpCache() {
+ String url = mTestServer.getCacheableTestDownloadUrl(
+ /* downloadId */ "cacheable-download",
+ /* numBytes */ 10);
+ mEngine =
+ mEngineBuilder
+ .setStoragePath(mContext.getApplicationInfo().dataDir)
+ .setEnableHttpCache(
+ HttpEngine.Builder.HTTP_CACHE_DISK, /* maxSize */ 100 * 1024)
+ .build();
+
+ UrlRequest.Builder builder =
+ mEngine.newUrlRequestBuilder(url, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ UrlResponseInfo info = mCallback.mResponseInfo;
+ assumeOKStatusCode(info);
+ assertFalse(info.wasCached());
+
+ mCallback = new TestUrlRequestCallback();
+ builder = mEngine.newUrlRequestBuilder(url, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ info = mCallback.mResponseInfo;
+ assertOKStatusCode(info);
+ assertTrue(info.wasCached());
+ }
+
+ @Test
public void testHttpEngine_DisableHttp2() throws Exception {
mEngine = mEngineBuilder.setEnableHttp2(false).build();
UrlRequest.Builder builder =
- mEngine.newUrlRequestBuilder(URL, mCallback, mCallback.getExecutor());
- builder.build().start();
+ mEngine.newUrlRequestBuilder(URL, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
- mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ // This tests uses a non-hermetic server. Instead of asserting, assume the next callback.
+ // This way, if the request were to fail, the test would just be skipped instead of failing.
+ mCallback.assumeCallback(ResponseStep.ON_SUCCEEDED);
UrlResponseInfo info = mCallback.mResponseInfo;
assertOKStatusCode(info);
assertEquals("http/1.1", info.getNegotiatedProtocol());
}
@Test
+ public void testHttpEngine_EnablePublicKeyPinningBypassForLocalTrustAnchors() {
+ String url = mTestServer.getSuccessUrl();
+ // For known hosts, requests should succeed whether we're bypassing the local trust anchor
+ // or not.
+ mEngine = mEngineBuilder.setEnablePublicKeyPinningBypassForLocalTrustAnchors(false).build();
+ UrlRequest.Builder builder =
+ mEngine.newUrlRequestBuilder(url, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+
+ mEngine.shutdown();
+ mEngine = mEngineBuilder.setEnablePublicKeyPinningBypassForLocalTrustAnchors(true).build();
+ mCallback = new TestUrlRequestCallback();
+ builder = mEngine.newUrlRequestBuilder(url, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+
+ // TODO(b/270918920): We should also test with a certificate not present in the device's
+ // trusted store.
+ // This requires either:
+ // * Mocking the underlying CertificateVerifier.
+ // * Or, having the server return a root certificate not present in the device's trusted
+ // store.
+ // The former doesn't make sense for a CTS test as it would depend on the underlying
+ // implementation. The latter is something we should support once we write a proper test
+ // server.
+ }
+
+ private byte[] generateSha256() {
+ byte[] sha256 = new byte[32];
+ Arrays.fill(sha256, (byte) 58);
+ return sha256;
+ }
+
+ private Instant instantInFuture(int secondsIntoFuture) {
+ Calendar cal = Calendar.getInstance();
+ cal.add(Calendar.SECOND, secondsIntoFuture);
+ return cal.getTime().toInstant();
+ }
+
+ @Test
+ public void testHttpEngine_AddPublicKeyPins() {
+ // CtsTestServer, when set in SslMode.NO_CLIENT_AUTH (required to trigger
+ // certificate verification, needed by this test), uses a certificate that
+ // doesn't match the hostname. For this reason, CtsTestServer cannot be used
+ // by this test.
+ Instant expirationInstant = instantInFuture(/* secondsIntoFuture */ 100);
+ boolean includeSubdomains = true;
+ Set<byte[]> pinsSha256 = Set.of(generateSha256());
+ mEngine = mEngineBuilder.addPublicKeyPins(
+ HOST, pinsSha256, includeSubdomains, expirationInstant).build();
+
+ UrlRequest.Builder builder =
+ mEngine.newUrlRequestBuilder(URL, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+ mCallback.expectCallback(ResponseStep.ON_FAILED);
+ assertNotNull("Expected an error", mCallback.mError);
+ }
+
+ @Test
public void testHttpEngine_EnableQuic() throws Exception {
mEngine = mEngineBuilder.setEnableQuic(true).addQuicHint(HOST, 443, 443).build();
// The hint doesn't guarantee that QUIC will win the race, just that it will race TCP.
// We send multiple requests to reduce the flakiness of the test.
boolean quicWasUsed = false;
for (int i = 0; i < 5; i++) {
+ mCallback = new TestUrlRequestCallback();
UrlRequest.Builder builder =
- mEngine.newUrlRequestBuilder(URL, mCallback, mCallback.getExecutor());
- builder.build().start();
+ mEngine.newUrlRequestBuilder(URL, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
- mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ // This tests uses a non-hermetic server. Instead of asserting, assume the next
+ // callback. This way, if the request were to fail, the test would just be skipped
+ // instead of failing.
+ mCallback.assumeCallback(ResponseStep.ON_SUCCEEDED);
UrlResponseInfo info = mCallback.mResponseInfo;
- assertOKStatusCode(info);
+ assumeOKStatusCode(info);
quicWasUsed = isQuic(info.getNegotiatedProtocol());
if (quicWasUsed) {
break;
@@ -118,5 +250,178 @@
@Test
public void testHttpEngine_GetDefaultUserAgent() throws Exception {
assertThat(mEngineBuilder.getDefaultUserAgent(), containsString("AndroidHttpClient"));
+ assertThat(mEngineBuilder.getDefaultUserAgent()).contains(HttpEngine.getVersionString());
+ }
+
+ @Test
+ public void testHttpEngine_requestUsesDefaultUserAgent() throws Exception {
+ mEngine = mEngineBuilder.build();
+ HttpCtsTestServer server =
+ new HttpCtsTestServer(ApplicationProvider.getApplicationContext());
+
+ String url = server.getUserAgentUrl();
+ UrlRequest request =
+ mEngine.newUrlRequestBuilder(url, mCallback.getExecutor(), mCallback).build();
+ request.start();
+
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ UrlResponseInfo info = mCallback.mResponseInfo;
+ assertOKStatusCode(info);
+ String receivedUserAgent = extractUserAgent(mCallback.mResponseAsString);
+
+ assertThat(receivedUserAgent).isEqualTo(mEngineBuilder.getDefaultUserAgent());
+ }
+
+ @Test
+ public void testHttpEngine_requestUsesCustomUserAgent() throws Exception {
+ String userAgent = "CtsTests User Agent";
+ HttpCtsTestServer server =
+ new HttpCtsTestServer(ApplicationProvider.getApplicationContext());
+ mEngine =
+ new HttpEngine.Builder(ApplicationProvider.getApplicationContext())
+ .setUserAgent(userAgent)
+ .build();
+
+ String url = server.getUserAgentUrl();
+ UrlRequest request =
+ mEngine.newUrlRequestBuilder(url, mCallback.getExecutor(), mCallback).build();
+ request.start();
+
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ UrlResponseInfo info = mCallback.mResponseInfo;
+ assertOKStatusCode(info);
+ String receivedUserAgent = extractUserAgent(mCallback.mResponseAsString);
+
+ assertThat(receivedUserAgent).isEqualTo(userAgent);
+ }
+
+ private static String extractUserAgent(String userAgentResponseBody) {
+ // If someone wants to be evil and have the title HTML tag a part of the user agent,
+ // they'll have to fix this method :)
+ return userAgentResponseBody.replaceFirst(".*<title>", "").replaceFirst("</title>.*", "");
+ }
+
+ @Test
+ public void testHttpEngine_bindToNetwork() throws Exception {
+ // Create a fake Android.net.Network. Since that network doesn't exist, binding to
+ // that should end up in a failed request.
+ Network mockNetwork = Mockito.mock(Network.class);
+ Mockito.when(mockNetwork.getNetworkHandle()).thenReturn(123L);
+ String url = mTestServer.getSuccessUrl();
+
+ mEngine = mEngineBuilder.build();
+ mEngine.bindToNetwork(mockNetwork);
+ UrlRequest.Builder builder =
+ mEngine.newUrlRequestBuilder(url, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+
+ mCallback.expectCallback(ResponseStep.ON_FAILED);
+ }
+
+ @Test
+ public void testHttpEngine_unbindFromNetwork() throws Exception {
+ // Create a fake Android.net.Network. Since that network doesn't exist, binding to
+ // that should end up in a failed request.
+ Network mockNetwork = Mockito.mock(Network.class);
+ Mockito.when(mockNetwork.getNetworkHandle()).thenReturn(123L);
+ String url = mTestServer.getSuccessUrl();
+
+ mEngine = mEngineBuilder.build();
+ // Bind to the fake network but then unbind. This should result in a successful
+ // request.
+ mEngine.bindToNetwork(mockNetwork);
+ mEngine.bindToNetwork(null);
+ UrlRequest.Builder builder =
+ mEngine.newUrlRequestBuilder(url, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ UrlResponseInfo info = mCallback.mResponseInfo;
+ assertOKStatusCode(info);
+ }
+
+ @Test
+ public void testHttpEngine_setConnectionMigrationOptions_requestSucceeds() {
+ ConnectionMigrationOptions options = new ConnectionMigrationOptions.Builder().build();
+ mEngine = mEngineBuilder.setConnectionMigrationOptions(options).build();
+ UrlRequest.Builder builder =
+ mEngine.newUrlRequestBuilder(
+ mTestServer.getSuccessUrl(), mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ UrlResponseInfo info = mCallback.mResponseInfo;
+ assertOKStatusCode(info);
+ }
+
+ @Test
+ public void testHttpEngine_setDnsOptions_requestSucceeds() {
+ DnsOptions options = new DnsOptions.Builder().build();
+ mEngine = mEngineBuilder.setDnsOptions(options).build();
+ UrlRequest.Builder builder =
+ mEngine.newUrlRequestBuilder(
+ mTestServer.getSuccessUrl(), mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ UrlResponseInfo info = mCallback.mResponseInfo;
+ assertOKStatusCode(info);
+ }
+
+ @Test
+ public void getVersionString_notEmpty() {
+ assertThat(HttpEngine.getVersionString()).isNotEmpty();
+ }
+
+ @Test
+ public void testHttpEngine_SetQuicOptions_RequestSucceedsWithQuic() throws Exception {
+ QuicOptions options = new QuicOptions.Builder().build();
+ mEngine = mEngineBuilder
+ .setEnableQuic(true)
+ .addQuicHint(HOST, 443, 443)
+ .setQuicOptions(options)
+ .build();
+
+ // The hint doesn't guarantee that QUIC will win the race, just that it will race TCP.
+ // We send multiple requests to reduce the flakiness of the test.
+ boolean quicWasUsed = false;
+ for (int i = 0; i < 5; i++) {
+ mCallback = new TestUrlRequestCallback();
+ UrlRequest.Builder builder =
+ mEngine.newUrlRequestBuilder(URL, mCallback.getExecutor(), mCallback);
+ mRequest = builder.build();
+ mRequest.start();
+ mCallback.blockForDone();
+
+ quicWasUsed = isQuic(mCallback.mResponseInfo.getNegotiatedProtocol());
+ if (quicWasUsed) {
+ break;
+ }
+ }
+
+ assertTrue(quicWasUsed);
+ // This tests uses a non-hermetic server. Instead of asserting, assume the next callback.
+ // This way, if the request were to fail, the test would just be skipped instead of failing.
+ assumeOKStatusCode(mCallback.mResponseInfo);
+ }
+
+ @Test
+ public void testHttpEngine_enableBrotli_brotliAdvertised() {
+ mEngine = mEngineBuilder.setEnableBrotli(true).build();
+ mRequest =
+ mEngine.newUrlRequestBuilder(
+ mTestServer.getEchoHeadersUrl(), mCallback.getExecutor(), mCallback)
+ .build();
+ mRequest.start();
+
+ mCallback.assumeCallback(ResponseStep.ON_SUCCEEDED);
+ UrlResponseInfo info = mCallback.mResponseInfo;
+ assertThat(info.getHeaders().getAsMap().get("x-request-header-Accept-Encoding").toString())
+ .contains("br");
+ assertOKStatusCode(info);
}
}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/NetworkExceptionTest.kt b/Cronet/tests/cts/src/android/net/http/cts/NetworkExceptionTest.kt
new file mode 100644
index 0000000..dd4cf0d
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/NetworkExceptionTest.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 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.http.cts
+
+import android.net.http.HttpEngine
+import android.net.http.NetworkException
+import android.net.http.cts.util.TestUrlRequestCallback
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlin.test.assertEquals
+import kotlin.test.assertIs
+import kotlin.test.assertSame
+import kotlin.test.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class NetworkExceptionTest {
+
+ @Test
+ fun testNetworkException_returnsInputParameters() {
+ val message = "failed"
+ val cause = Throwable("thrown")
+ val networkException =
+ object : NetworkException(message, cause) {
+ override fun getErrorCode() = 0
+ override fun isImmediatelyRetryable() = false
+ }
+
+ assertEquals(message, networkException.message)
+ assertSame(cause, networkException.cause)
+ }
+
+ @Test
+ fun testNetworkException_thrownFromUrlRequest() {
+ val httpEngine = HttpEngine.Builder(ApplicationProvider.getApplicationContext()).build()
+ val callback = TestUrlRequestCallback()
+ val request =
+ httpEngine.newUrlRequestBuilder("http://localhost", callback.executor, callback).build()
+
+ request.start()
+ callback.blockForDone()
+
+ assertTrue(request.isDone)
+ assertIs<NetworkException>(callback.mError)
+ httpEngine.shutdown()
+ }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/QuicExceptionTest.kt b/Cronet/tests/cts/src/android/net/http/cts/QuicExceptionTest.kt
new file mode 100644
index 0000000..4b7aa14
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/QuicExceptionTest.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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.http.cts
+
+import android.net.http.QuicException
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class QuicExceptionTest {
+
+ @Test
+ fun testQuicException_returnsInputParameters() {
+ val message = "failed"
+ val cause = Throwable("thrown")
+ val quicException =
+ object : QuicException(message, cause) {
+ override fun getErrorCode() = 0
+ override fun isImmediatelyRetryable() = false
+ }
+
+ assertEquals(message, quicException.message)
+ assertEquals(cause, quicException.cause)
+ }
+
+ // TODO: add test for QuicException triggered from HttpEngine
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/QuicOptionsTest.kt b/Cronet/tests/cts/src/android/net/http/cts/QuicOptionsTest.kt
new file mode 100644
index 0000000..0b02aa7
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/QuicOptionsTest.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2023 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.http.cts
+
+import android.net.http.QuicOptions
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import java.time.Duration
+import kotlin.test.assertFailsWith
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class QuicOptionsTest {
+ @Test
+ fun testQuicOptions_defaultValues() {
+ val quicOptions = QuicOptions.Builder().build()
+ assertThat(quicOptions.allowedQuicHosts).isEmpty()
+ assertThat(quicOptions.handshakeUserAgent).isNull()
+ assertThat(quicOptions.idleConnectionTimeout).isNull()
+ assertFalse(quicOptions.hasInMemoryServerConfigsCacheSize())
+ assertFailsWith(IllegalStateException::class) {
+ quicOptions.inMemoryServerConfigsCacheSize
+ }
+ }
+
+ @Test
+ fun testQuicOptions_quicHostAllowlist_returnsAddedValues() {
+ val quicOptions = QuicOptions.Builder()
+ .addAllowedQuicHost("foo")
+ .addAllowedQuicHost("bar")
+ .addAllowedQuicHost("foo")
+ .addAllowedQuicHost("baz")
+ .build()
+ assertThat(quicOptions.allowedQuicHosts)
+ .containsExactly("foo", "bar", "baz")
+ .inOrder()
+ }
+
+ @Test
+ fun testQuicOptions_idleConnectionTimeout_returnsSetValue() {
+ val timeout = Duration.ofMinutes(10)
+ val quicOptions = QuicOptions.Builder()
+ .setIdleConnectionTimeout(timeout)
+ .build()
+ assertThat(quicOptions.idleConnectionTimeout)
+ .isEqualTo(timeout)
+ }
+
+ @Test
+ fun testQuicOptions_inMemoryServerConfigsCacheSize_returnsSetValue() {
+ val quicOptions = QuicOptions.Builder()
+ .setInMemoryServerConfigsCacheSize(42)
+ .build()
+ assertTrue(quicOptions.hasInMemoryServerConfigsCacheSize())
+ assertThat(quicOptions.inMemoryServerConfigsCacheSize)
+ .isEqualTo(42)
+ }
+
+ @Test
+ fun testQuicOptions_handshakeUserAgent_returnsSetValue() {
+ val userAgent = "test"
+ val quicOptions = QuicOptions.Builder()
+ .setHandshakeUserAgent(userAgent)
+ .build()
+ assertThat(quicOptions.handshakeUserAgent)
+ .isEqualTo(userAgent)
+ }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java b/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
index d7d3679..422f4d5 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/UrlRequestTest.java
@@ -19,11 +19,21 @@
import static android.net.http.cts.util.TestUtilsKt.assertOKStatusCode;
import static android.net.http.cts.util.TestUtilsKt.skipIfNoInternetConnection;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import android.content.Context;
+import android.net.http.HeaderBlock;
import android.net.http.HttpEngine;
+import android.net.http.HttpException;
+import android.net.http.InlineExecutionProhibitedException;
+import android.net.http.UploadDataProvider;
import android.net.http.UrlRequest;
import android.net.http.UrlRequest.Status;
import android.net.http.UrlResponseInfo;
@@ -31,24 +41,46 @@
import android.net.http.cts.util.TestStatusListener;
import android.net.http.cts.util.TestUrlRequestCallback;
import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep;
+import android.net.http.cts.util.UploadDataProviders;
+import android.webkit.cts.CtsTestServer;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.google.common.base.Strings;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.net.URLEncoder;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
@RunWith(AndroidJUnit4.class)
public class UrlRequestTest {
+ private static final Executor DIRECT_EXECUTOR = Runnable::run;
+
private TestUrlRequestCallback mCallback;
private HttpCtsTestServer mTestServer;
private HttpEngine mHttpEngine;
@Before
public void setUp() throws Exception {
- Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ Context context = ApplicationProvider.getApplicationContext();
skipIfNoInternetConnection(context);
HttpEngine.Builder builder = new HttpEngine.Builder(context);
mHttpEngine = builder.build();
@@ -66,14 +98,14 @@
}
}
- private UrlRequest buildUrlRequest(String url) {
- return mHttpEngine.newUrlRequestBuilder(url, mCallback, mCallback.getExecutor()).build();
+ private UrlRequest.Builder createUrlRequestBuilder(String url) {
+ return mHttpEngine.newUrlRequestBuilder(url, mCallback.getExecutor(), mCallback);
}
@Test
public void testUrlRequestGet_CompletesSuccessfully() throws Exception {
String url = mTestServer.getSuccessUrl();
- UrlRequest request = buildUrlRequest(url);
+ UrlRequest request = createUrlRequestBuilder(url).build();
request.start();
mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
@@ -84,11 +116,297 @@
@Test
public void testUrlRequestStatus_InvalidBeforeRequestStarts() throws Exception {
- UrlRequest request = buildUrlRequest(mTestServer.getSuccessUrl());
+ UrlRequest request = createUrlRequestBuilder(mTestServer.getSuccessUrl()).build();
// Calling before request is started should give Status.INVALID,
// since the native adapter is not created.
TestStatusListener statusListener = new TestStatusListener();
request.getStatus(statusListener);
statusListener.expectStatus(Status.INVALID);
}
+
+ @Test
+ public void testUrlRequestCancel_CancelCalled() throws Exception {
+ UrlRequest request = createUrlRequestBuilder(mTestServer.getSuccessUrl()).build();
+ mCallback.setAutoAdvance(false);
+
+ request.start();
+ mCallback.waitForNextStep();
+ assertSame(mCallback.mResponseStep, ResponseStep.ON_RESPONSE_STARTED);
+
+ request.cancel();
+ mCallback.expectCallback(ResponseStep.ON_CANCELED);
+ }
+
+ @Test
+ public void testUrlRequestPost_EchoRequestBody() {
+ String testData = "test";
+ UrlRequest.Builder builder = createUrlRequestBuilder(mTestServer.getEchoBodyUrl());
+
+ UploadDataProvider dataProvider = UploadDataProviders.create(testData);
+ builder.setUploadDataProvider(dataProvider, mCallback.getExecutor());
+ builder.addHeader("Content-Type", "text/html");
+ builder.build().start();
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+
+ assertOKStatusCode(mCallback.mResponseInfo);
+ assertEquals(testData, mCallback.mResponseAsString);
+ }
+
+ @Test
+ public void testUrlRequestFail_FailedCalled() {
+ createUrlRequestBuilder("http://0.0.0.0:0/").build().start();
+ mCallback.expectCallback(ResponseStep.ON_FAILED);
+ }
+
+ @Test
+ public void testUrlRequest_directExecutor_allowed() throws InterruptedException {
+ TestUrlRequestCallback callback = new TestUrlRequestCallback();
+ callback.setAllowDirectExecutor(true);
+ UrlRequest.Builder builder = mHttpEngine.newUrlRequestBuilder(
+ mTestServer.getEchoBodyUrl(), DIRECT_EXECUTOR, callback);
+ UploadDataProvider dataProvider = UploadDataProviders.create("test");
+ builder.setUploadDataProvider(dataProvider, DIRECT_EXECUTOR);
+ builder.addHeader("Content-Type", "text/plain;charset=UTF-8");
+ builder.setDirectExecutorAllowed(true);
+ builder.build().start();
+ callback.blockForDone();
+
+ if (callback.mOnErrorCalled) {
+ throw new AssertionError("Expected no exception", callback.mError);
+ }
+
+ assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
+ assertEquals("test", callback.mResponseAsString);
+ }
+
+ @Test
+ public void testUrlRequest_directExecutor_disallowed_uploadDataProvider() throws Exception {
+ TestUrlRequestCallback callback = new TestUrlRequestCallback();
+ // This applies just locally to the test callback, not to SUT
+ callback.setAllowDirectExecutor(true);
+
+ UrlRequest.Builder builder = mHttpEngine.newUrlRequestBuilder(
+ mTestServer.getEchoBodyUrl(), Executors.newSingleThreadExecutor(), callback);
+ UploadDataProvider dataProvider = UploadDataProviders.create("test");
+
+ builder.setUploadDataProvider(dataProvider, DIRECT_EXECUTOR)
+ .addHeader("Content-Type", "text/plain;charset=UTF-8")
+ .build()
+ .start();
+ callback.blockForDone();
+
+ assertTrue(callback.mOnErrorCalled);
+ assertTrue(callback.mError.getCause() instanceof InlineExecutionProhibitedException);
+ }
+
+ @Test
+ public void testUrlRequest_directExecutor_disallowed_responseCallback() throws Exception {
+ TestUrlRequestCallback callback = new TestUrlRequestCallback();
+ // This applies just locally to the test callback, not to SUT
+ callback.setAllowDirectExecutor(true);
+
+ UrlRequest.Builder builder = mHttpEngine.newUrlRequestBuilder(
+ mTestServer.getEchoBodyUrl(), DIRECT_EXECUTOR, callback);
+ UploadDataProvider dataProvider = UploadDataProviders.create("test");
+
+ builder.setUploadDataProvider(dataProvider, Executors.newSingleThreadExecutor())
+ .addHeader("Content-Type", "text/plain;charset=UTF-8")
+ .build()
+ .start();
+ callback.blockForDone();
+
+ assertTrue(callback.mOnErrorCalled);
+ assertTrue(callback.mError.getCause() instanceof InlineExecutionProhibitedException);
+ }
+
+ @Test
+ public void testUrlRequest_nonDirectByteBuffer() throws Exception {
+ BlockingQueue<HttpException> onFailedException = new ArrayBlockingQueue<>(1);
+
+ UrlRequest request =
+ mHttpEngine
+ .newUrlRequestBuilder(
+ mTestServer.getSuccessUrl(),
+ Executors.newSingleThreadExecutor(),
+ new StubUrlRequestCallback() {
+ @Override
+ public void onResponseStarted(
+ UrlRequest request, UrlResponseInfo info) {
+ // note: allocate, not allocateDirect
+ request.read(ByteBuffer.allocate(1024));
+ }
+
+ @Override
+ public void onFailed(
+ UrlRequest request,
+ UrlResponseInfo info,
+ HttpException error) {
+ onFailedException.add(error);
+ }
+ })
+ .build();
+ request.start();
+
+ HttpException e = onFailedException.poll(5, TimeUnit.SECONDS);
+ assertNotNull(e);
+ assertTrue(e.getCause() instanceof IllegalArgumentException);
+ assertTrue(e.getCause().getMessage().contains("direct"));
+ }
+
+ @Test
+ public void testUrlRequest_fullByteBuffer() throws Exception {
+ BlockingQueue<HttpException> onFailedException = new ArrayBlockingQueue<>(1);
+
+ UrlRequest request =
+ mHttpEngine
+ .newUrlRequestBuilder(
+ mTestServer.getSuccessUrl(),
+ Executors.newSingleThreadExecutor(),
+ new StubUrlRequestCallback() {
+ @Override
+ public void onResponseStarted(
+ UrlRequest request, UrlResponseInfo info) {
+ ByteBuffer bb = ByteBuffer.allocateDirect(1024);
+ bb.position(bb.limit());
+ request.read(bb);
+ }
+
+ @Override
+ public void onFailed(
+ UrlRequest request,
+ UrlResponseInfo info,
+ HttpException error) {
+ onFailedException.add(error);
+ }
+ })
+ .build();
+ request.start();
+
+ HttpException e = onFailedException.poll(5, TimeUnit.SECONDS);
+ assertNotNull(e);
+ assertTrue(e.getCause() instanceof IllegalArgumentException);
+ assertTrue(e.getCause().getMessage().contains("full"));
+ }
+
+ @Test
+ public void testUrlRequest_redirects() throws Exception {
+ int expectedNumRedirects = 5;
+ String url =
+ mTestServer.getRedirectingAssetUrl("html/hello_world.html", expectedNumRedirects);
+
+ UrlRequest request = createUrlRequestBuilder(url).build();
+ request.start();
+
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+ UrlResponseInfo info = mCallback.mResponseInfo;
+ assertOKStatusCode(info);
+ assertThat(mCallback.mResponseAsString).contains("hello world");
+ assertThat(info.getUrlChain()).hasSize(expectedNumRedirects + 1);
+ assertThat(info.getUrlChain().get(0)).isEqualTo(url);
+ assertThat(info.getUrlChain().get(expectedNumRedirects)).isEqualTo(info.getUrl());
+ }
+
+ @Test
+ public void testUrlRequestPost_withRedirect() throws Exception {
+ String body = Strings.repeat(
+ "Hello, this is a really interesting body, so write this 100 times.", 100);
+
+ String redirectUrlParameter =
+ URLEncoder.encode(mTestServer.getEchoBodyUrl(), "UTF-8");
+ createUrlRequestBuilder(
+ String.format(
+ "%s/alt_redirect?dest=%s&statusCode=307",
+ mTestServer.getBaseUri(),
+ redirectUrlParameter))
+ .setHttpMethod("POST")
+ .addHeader("Content-Type", "text/plain")
+ .setUploadDataProvider(
+ UploadDataProviders.create(body.getBytes(StandardCharsets.UTF_8)),
+ mCallback.getExecutor())
+ .build()
+ .start();
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+
+ assertOKStatusCode(mCallback.mResponseInfo);
+ assertThat(mCallback.mResponseAsString).isEqualTo(body);
+ }
+
+ @Test
+ public void testUrlRequest_customHeaders() throws Exception {
+ UrlRequest.Builder builder = createUrlRequestBuilder(mTestServer.getEchoHeadersUrl());
+
+ List<Map.Entry<String, String>> expectedHeaders = Arrays.asList(
+ Map.entry("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="),
+ Map.entry("Max-Forwards", "10"),
+ Map.entry("X-Client-Data", "random custom header content"));
+
+ for (Map.Entry<String, String> header : expectedHeaders) {
+ builder.addHeader(header.getKey(), header.getValue());
+ }
+
+ builder.build().start();
+ mCallback.expectCallback(ResponseStep.ON_SUCCEEDED);
+
+ assertOKStatusCode(mCallback.mResponseInfo);
+
+ List<Map.Entry<String, String>> echoedHeaders =
+ extractEchoedHeaders(mCallback.mResponseInfo.getHeaders());
+
+ // The implementation might decide to add more headers like accepted encodings it handles
+ // internally so the server is likely to see more headers than explicitly set
+ // by the developer.
+ assertThat(echoedHeaders)
+ .containsAtLeastElementsIn(expectedHeaders);
+ }
+
+ private static List<Map.Entry<String, String>> extractEchoedHeaders(HeaderBlock headers) {
+ return headers.getAsList()
+ .stream()
+ .flatMap(input -> {
+ if (input.getKey().startsWith(CtsTestServer.ECHOED_RESPONSE_HEADER_PREFIX)) {
+ String strippedKey =
+ input.getKey().substring(
+ CtsTestServer.ECHOED_RESPONSE_HEADER_PREFIX.length());
+ return Stream.of(Map.entry(strippedKey, input.getValue()));
+ } else {
+ return Stream.empty();
+ }
+ })
+ .collect(Collectors.toList());
+ }
+
+ private static class StubUrlRequestCallback implements UrlRequest.Callback {
+
+ @Override
+ public void onRedirectReceived(
+ UrlRequest request, UrlResponseInfo info, String newLocationUrl) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void onReadCompleted(
+ UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void onFailed(UrlRequest request, UrlResponseInfo info, HttpException error) {
+ throw new UnsupportedOperationException(error);
+ }
+
+ @Override
+ public void onCanceled(@NonNull UrlRequest request, @Nullable UrlResponseInfo info) {
+ throw new UnsupportedOperationException();
+ }
+ }
}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/UrlResponseInfoTest.kt b/Cronet/tests/cts/src/android/net/http/cts/UrlResponseInfoTest.kt
new file mode 100644
index 0000000..38da9c5
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/UrlResponseInfoTest.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 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.http.cts
+
+import android.content.Context
+import android.net.http.HttpEngine
+import android.net.http.cts.util.HttpCtsTestServer
+import android.net.http.cts.util.TestUrlRequestCallback
+import android.net.http.cts.util.TestUrlRequestCallback.ResponseStep
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class UrlResponseInfoTest {
+
+ @Test
+ fun testUrlResponseInfo_apisReturnCorrectInfo() {
+ // start the engine and send a request
+ val context: Context = ApplicationProvider.getApplicationContext()
+ val server = HttpCtsTestServer(context)
+ val httpEngine = HttpEngine.Builder(context).build()
+ val callback = TestUrlRequestCallback()
+ val url = server.successUrl
+ val request = httpEngine.newUrlRequestBuilder(url, callback.executor, callback).build()
+
+ request.start()
+ callback.expectCallback(ResponseStep.ON_SUCCEEDED)
+
+ val info = callback.mResponseInfo
+ assertFalse(info.headers.asList.isEmpty())
+ assertEquals(200, info.httpStatusCode)
+ assertTrue(info.receivedByteCount > 0)
+ assertEquals(url, info.url)
+ assertEquals(listOf(url), info.urlChain)
+ assertFalse(info.wasCached())
+
+ // TODO Current test server does not set these values. Uncomment when we use one that does.
+ // assertEquals("OK", info.httpStatusText)
+ // assertEquals("http/1.1", info.negotiatedProtocol)
+
+ // cronet defaults to port 0 when no proxy is specified.
+ // This is not a behaviour we want to enforce since null is reasonable too.
+ // assertEquals(":0", info.proxyServer)
+
+ server.shutdown()
+ httpEngine.shutdown()
+ }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/HttpCtsTestServer.kt b/Cronet/tests/cts/src/android/net/http/cts/util/HttpCtsTestServer.kt
index 87d5108..5196544 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/util/HttpCtsTestServer.kt
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/HttpCtsTestServer.kt
@@ -18,9 +18,40 @@
import android.content.Context
import android.webkit.cts.CtsTestServer
+import java.net.URI
+import org.apache.http.HttpEntityEnclosingRequest
+import org.apache.http.HttpRequest
+import org.apache.http.HttpResponse
+import org.apache.http.HttpStatus
+import org.apache.http.HttpVersion
+import org.apache.http.message.BasicHttpResponse
+
+private const val ECHO_BODY_PATH = "/echo_body"
/** Extends CtsTestServer to handle POST requests and other test specific requests */
class HttpCtsTestServer(context: Context) : CtsTestServer(context) {
+ val echoBodyUrl: String = baseUri + ECHO_BODY_PATH
val successUrl: String = getAssetUrl("html/hello_world.html")
+
+ override fun onPost(req: HttpRequest): HttpResponse? {
+ val path = URI.create(req.requestLine.uri).path
+ var response: HttpResponse? = null
+
+ if (path.startsWith(ECHO_BODY_PATH)) {
+ if (req !is HttpEntityEnclosingRequest) {
+ return BasicHttpResponse(
+ HttpVersion.HTTP_1_0,
+ HttpStatus.SC_INTERNAL_SERVER_ERROR,
+ "Expected req to be of type HttpEntityEnclosingRequest but got ${req.javaClass}"
+ )
+ }
+
+ response = BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, null)
+ response.entity = req.entity
+ response.addHeader("Content-Length", req.entity.contentLength.toString())
+ }
+
+ return response
+ }
}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestBidirectionalStreamCallback.java b/Cronet/tests/cts/src/android/net/http/cts/util/TestBidirectionalStreamCallback.java
new file mode 100644
index 0000000..1e7333c
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestBidirectionalStreamCallback.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2023 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.http.cts.util;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeThat;
+import static org.junit.Assume.assumeTrue;
+
+import android.net.http.BidirectionalStream;
+import android.net.http.HeaderBlock;
+import android.net.http.HttpException;
+import android.net.http.UrlResponseInfo;
+import android.os.ConditionVariable;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Callback that tracks information from different callbacks and has a method to block thread until
+ * the stream completes on another thread. Allows to cancel, block stream or throw an exception from
+ * an arbitrary step.
+ */
+public class TestBidirectionalStreamCallback implements BidirectionalStream.Callback {
+ private static final int TIMEOUT_MS = 12_000;
+ public UrlResponseInfo mResponseInfo;
+ public HttpException mError;
+
+ public ResponseStep mResponseStep = ResponseStep.NOTHING;
+
+ public boolean mOnErrorCalled;
+ public boolean mOnCanceledCalled;
+
+ public int mHttpResponseDataLength;
+ public String mResponseAsString = "";
+
+ public HeaderBlock mTrailers;
+
+ private static final int READ_BUFFER_SIZE = 32 * 1024;
+
+ // When false, the consumer is responsible for all calls into the stream
+ // that advance it.
+ private boolean mAutoAdvance = true;
+
+ // Conditionally fail on certain steps.
+ private FailureType mFailureType = FailureType.NONE;
+ private ResponseStep mFailureStep = ResponseStep.NOTHING;
+
+ // Signals when the stream is done either successfully or not.
+ private final ConditionVariable mDone = new ConditionVariable();
+
+ // Signaled on each step when mAutoAdvance is false.
+ private final ConditionVariable mReadStepBlock = new ConditionVariable();
+ private final ConditionVariable mWriteStepBlock = new ConditionVariable();
+
+ // Executor Service for Cronet callbacks.
+ private final ExecutorService mExecutorService =
+ Executors.newSingleThreadExecutor(new ExecutorThreadFactory());
+ private Thread mExecutorThread;
+
+ // position() of ByteBuffer prior to read() call.
+ private int mBufferPositionBeforeRead;
+
+ // Data to write.
+ private final ArrayList<WriteBuffer> mWriteBuffers = new ArrayList<WriteBuffer>();
+
+ // Buffers that we yet to receive the corresponding onWriteCompleted callback.
+ private final ArrayList<WriteBuffer> mWriteBuffersToBeAcked = new ArrayList<WriteBuffer>();
+
+ // Whether to use a direct executor.
+ private final boolean mUseDirectExecutor;
+ private final DirectExecutor mDirectExecutor;
+
+ private class ExecutorThreadFactory implements ThreadFactory {
+ @Override
+ public Thread newThread(Runnable r) {
+ mExecutorThread = new Thread(r);
+ return mExecutorThread;
+ }
+ }
+
+ private static class WriteBuffer {
+ final ByteBuffer mBuffer;
+ final boolean mFlush;
+
+ WriteBuffer(ByteBuffer buffer, boolean flush) {
+ mBuffer = buffer;
+ mFlush = flush;
+ }
+ }
+
+ private static class DirectExecutor implements Executor {
+ @Override
+ public void execute(Runnable task) {
+ task.run();
+ }
+ }
+
+ public enum ResponseStep {
+ NOTHING,
+ ON_STREAM_READY,
+ ON_RESPONSE_STARTED,
+ ON_READ_COMPLETED,
+ ON_WRITE_COMPLETED,
+ ON_TRAILERS,
+ ON_CANCELED,
+ ON_FAILED,
+ ON_SUCCEEDED,
+ }
+
+ public enum FailureType {
+ NONE,
+ CANCEL_SYNC,
+ CANCEL_ASYNC,
+ // Same as above, but continues to advance the stream after posting
+ // the cancellation task.
+ CANCEL_ASYNC_WITHOUT_PAUSE,
+ THROW_SYNC
+ }
+
+ private boolean isTerminalCallback(ResponseStep step) {
+ switch (step) {
+ case ON_SUCCEEDED:
+ case ON_CANCELED:
+ case ON_FAILED:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public TestBidirectionalStreamCallback() {
+ mUseDirectExecutor = false;
+ mDirectExecutor = null;
+ }
+
+ public TestBidirectionalStreamCallback(boolean useDirectExecutor) {
+ mUseDirectExecutor = useDirectExecutor;
+ mDirectExecutor = new DirectExecutor();
+ }
+
+ public void setAutoAdvance(boolean autoAdvance) {
+ mAutoAdvance = autoAdvance;
+ }
+
+ public void setFailure(FailureType failureType, ResponseStep failureStep) {
+ mFailureStep = failureStep;
+ mFailureType = failureType;
+ }
+
+ public boolean blockForDone() {
+ return mDone.block(TIMEOUT_MS);
+ }
+
+ /**
+ * Waits for a terminal callback to complete execution before failing if the callback is not the
+ * expected one
+ *
+ * @param expectedStep the expected callback step
+ */
+ public void expectCallback(ResponseStep expectedStep) {
+ if (isTerminalCallback(expectedStep)) {
+ assertTrue(String.format(
+ "Request timed out. Expected %s callback. Current callback is %s",
+ expectedStep, mResponseStep),
+ blockForDone());
+ }
+ assertSame(expectedStep, mResponseStep);
+ }
+
+ /**
+ * Waits for a terminal callback to complete execution before skipping the test if the callback
+ * is not the expected one
+ *
+ * @param expectedStep the expected callback step
+ */
+ public void assumeCallback(ResponseStep expectedStep) {
+ if (isTerminalCallback(expectedStep)) {
+ assumeTrue(
+ String.format(
+ "Request timed out. Expected %s callback. Current callback is %s",
+ expectedStep, mResponseStep),
+ blockForDone());
+ }
+ assumeThat(expectedStep, equalTo(mResponseStep));
+ }
+
+ public void waitForNextReadStep() {
+ mReadStepBlock.block();
+ mReadStepBlock.close();
+ }
+
+ public void waitForNextWriteStep() {
+ mWriteStepBlock.block();
+ mWriteStepBlock.close();
+ }
+
+ public Executor getExecutor() {
+ if (mUseDirectExecutor) {
+ return mDirectExecutor;
+ }
+ return mExecutorService;
+ }
+
+ public void shutdownExecutor() {
+ if (mUseDirectExecutor) {
+ throw new UnsupportedOperationException("DirectExecutor doesn't support shutdown");
+ }
+ mExecutorService.shutdown();
+ }
+
+ public void addWriteData(byte[] data) {
+ addWriteData(data, true);
+ }
+
+ public void addWriteData(byte[] data, boolean flush) {
+ ByteBuffer writeBuffer = ByteBuffer.allocateDirect(data.length);
+ writeBuffer.put(data);
+ writeBuffer.flip();
+ mWriteBuffers.add(new WriteBuffer(writeBuffer, flush));
+ mWriteBuffersToBeAcked.add(new WriteBuffer(writeBuffer, flush));
+ }
+
+ @Override
+ public void onStreamReady(BidirectionalStream stream) {
+ checkOnValidThread();
+ assertFalse(stream.isDone());
+ assertEquals(ResponseStep.NOTHING, mResponseStep);
+ assertNull(mError);
+ mResponseStep = ResponseStep.ON_STREAM_READY;
+ if (maybeThrowCancelOrPause(stream, mWriteStepBlock)) {
+ return;
+ }
+ startNextWrite(stream);
+ }
+
+ @Override
+ public void onResponseHeadersReceived(BidirectionalStream stream, UrlResponseInfo info) {
+ checkOnValidThread();
+ assertFalse(stream.isDone());
+ assertTrue(
+ mResponseStep == ResponseStep.NOTHING
+ || mResponseStep == ResponseStep.ON_STREAM_READY
+ || mResponseStep == ResponseStep.ON_WRITE_COMPLETED);
+ assertNull(mError);
+
+ mResponseStep = ResponseStep.ON_RESPONSE_STARTED;
+ mResponseInfo = info;
+ if (maybeThrowCancelOrPause(stream, mReadStepBlock)) {
+ return;
+ }
+ startNextRead(stream);
+ }
+
+ @Override
+ public void onReadCompleted(
+ BidirectionalStream stream,
+ UrlResponseInfo info,
+ ByteBuffer byteBuffer,
+ boolean endOfStream) {
+ checkOnValidThread();
+ assertFalse(stream.isDone());
+ assertTrue(
+ mResponseStep == ResponseStep.ON_RESPONSE_STARTED
+ || mResponseStep == ResponseStep.ON_READ_COMPLETED
+ || mResponseStep == ResponseStep.ON_WRITE_COMPLETED
+ || mResponseStep == ResponseStep.ON_TRAILERS);
+ assertNull(mError);
+
+ mResponseStep = ResponseStep.ON_READ_COMPLETED;
+ mResponseInfo = info;
+
+ final int bytesRead = byteBuffer.position() - mBufferPositionBeforeRead;
+ mHttpResponseDataLength += bytesRead;
+ final byte[] lastDataReceivedAsBytes = new byte[bytesRead];
+ // Rewind byteBuffer.position() to pre-read() position.
+ byteBuffer.position(mBufferPositionBeforeRead);
+ // This restores byteBuffer.position() to its value on entrance to
+ // this function.
+ byteBuffer.get(lastDataReceivedAsBytes);
+
+ mResponseAsString += new String(lastDataReceivedAsBytes);
+
+ if (maybeThrowCancelOrPause(stream, mReadStepBlock)) {
+ return;
+ }
+ // Do not read if EOF has been reached.
+ if (!endOfStream) {
+ startNextRead(stream);
+ }
+ }
+
+ @Override
+ public void onWriteCompleted(
+ BidirectionalStream stream,
+ UrlResponseInfo info,
+ ByteBuffer buffer,
+ boolean endOfStream) {
+ checkOnValidThread();
+ assertFalse(stream.isDone());
+ assertNull(mError);
+ mResponseStep = ResponseStep.ON_WRITE_COMPLETED;
+ mResponseInfo = info;
+ if (!mWriteBuffersToBeAcked.isEmpty()) {
+ assertEquals(buffer, mWriteBuffersToBeAcked.get(0).mBuffer);
+ mWriteBuffersToBeAcked.remove(0);
+ }
+ if (maybeThrowCancelOrPause(stream, mWriteStepBlock)) {
+ return;
+ }
+ startNextWrite(stream);
+ }
+
+ @Override
+ public void onResponseTrailersReceived(
+ BidirectionalStream stream,
+ UrlResponseInfo info,
+ HeaderBlock trailers) {
+ checkOnValidThread();
+ assertFalse(stream.isDone());
+ assertNull(mError);
+ mResponseStep = ResponseStep.ON_TRAILERS;
+ mResponseInfo = info;
+ mTrailers = trailers;
+ if (maybeThrowCancelOrPause(stream, mReadStepBlock)) {
+ return;
+ }
+ }
+
+ @Override
+ public void onSucceeded(BidirectionalStream stream, UrlResponseInfo info) {
+ checkOnValidThread();
+ assertTrue(stream.isDone());
+ assertTrue(
+ mResponseStep == ResponseStep.ON_RESPONSE_STARTED
+ || mResponseStep == ResponseStep.ON_READ_COMPLETED
+ || mResponseStep == ResponseStep.ON_WRITE_COMPLETED
+ || mResponseStep == ResponseStep.ON_TRAILERS);
+ assertFalse(mOnErrorCalled);
+ assertFalse(mOnCanceledCalled);
+ assertNull(mError);
+ assertEquals(0, mWriteBuffers.size());
+ assertEquals(0, mWriteBuffersToBeAcked.size());
+
+ mResponseStep = ResponseStep.ON_SUCCEEDED;
+ mResponseInfo = info;
+ openDone();
+ maybeThrowCancelOrPause(stream, mReadStepBlock);
+ }
+
+ @Override
+ public void onFailed(BidirectionalStream stream, UrlResponseInfo info, HttpException error) {
+ checkOnValidThread();
+ assertTrue(stream.isDone());
+ // Shouldn't happen after success.
+ assertTrue(mResponseStep != ResponseStep.ON_SUCCEEDED);
+ // Should happen at most once for a single stream.
+ assertFalse(mOnErrorCalled);
+ assertFalse(mOnCanceledCalled);
+ assertNull(mError);
+ mResponseStep = ResponseStep.ON_FAILED;
+ mResponseInfo = info;
+
+ mOnErrorCalled = true;
+ mError = error;
+ openDone();
+ maybeThrowCancelOrPause(stream, mReadStepBlock);
+ }
+
+ @Override
+ public void onCanceled(BidirectionalStream stream, UrlResponseInfo info) {
+ checkOnValidThread();
+ assertTrue(stream.isDone());
+ // Should happen at most once for a single stream.
+ assertFalse(mOnCanceledCalled);
+ assertFalse(mOnErrorCalled);
+ assertNull(mError);
+ mResponseStep = ResponseStep.ON_CANCELED;
+ mResponseInfo = info;
+
+ mOnCanceledCalled = true;
+ openDone();
+ maybeThrowCancelOrPause(stream, mReadStepBlock);
+ }
+
+ public void startNextRead(BidirectionalStream stream) {
+ startNextRead(stream, ByteBuffer.allocateDirect(READ_BUFFER_SIZE));
+ }
+
+ public void startNextRead(BidirectionalStream stream, ByteBuffer buffer) {
+ mBufferPositionBeforeRead = buffer.position();
+ stream.read(buffer);
+ }
+
+ public void startNextWrite(BidirectionalStream stream) {
+ if (!mWriteBuffers.isEmpty()) {
+ Iterator<WriteBuffer> iterator = mWriteBuffers.iterator();
+ while (iterator.hasNext()) {
+ WriteBuffer b = iterator.next();
+ stream.write(b.mBuffer, !iterator.hasNext());
+ iterator.remove();
+ if (b.mFlush) {
+ stream.flush();
+ break;
+ }
+ }
+ }
+ }
+
+ public boolean isDone() {
+ // It's not mentioned by the Android docs, but block(0) seems to block
+ // indefinitely, so have to block for one millisecond to get state
+ // without blocking.
+ return mDone.block(1);
+ }
+
+ /** Returns the number of pending Writes. */
+ public int numPendingWrites() {
+ return mWriteBuffers.size();
+ }
+
+ protected void openDone() {
+ mDone.open();
+ }
+
+ /** Returns {@code false} if the callback should continue to advance the stream. */
+ private boolean maybeThrowCancelOrPause(
+ final BidirectionalStream stream, ConditionVariable stepBlock) {
+ if (mResponseStep != mFailureStep || mFailureType == FailureType.NONE) {
+ if (!mAutoAdvance) {
+ stepBlock.open();
+ return true;
+ }
+ return false;
+ }
+
+ if (mFailureType == FailureType.THROW_SYNC) {
+ throw new IllegalStateException("Callback Exception.");
+ }
+ Runnable task =
+ new Runnable() {
+ @Override
+ public void run() {
+ stream.cancel();
+ }
+ };
+ if (mFailureType == FailureType.CANCEL_ASYNC
+ || mFailureType == FailureType.CANCEL_ASYNC_WITHOUT_PAUSE) {
+ getExecutor().execute(task);
+ } else {
+ task.run();
+ }
+ return mFailureType != FailureType.CANCEL_ASYNC_WITHOUT_PAUSE;
+ }
+
+ /** Checks whether callback methods are invoked on the correct thread. */
+ private void checkOnValidThread() {
+ if (!mUseDirectExecutor) {
+ assertEquals(mExecutorThread, Thread.currentThread());
+ }
+ }
+}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestStatusListener.kt b/Cronet/tests/cts/src/android/net/http/cts/util/TestStatusListener.kt
index e526c7d..3a4486f 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/util/TestStatusListener.kt
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestStatusListener.kt
@@ -24,7 +24,7 @@
private const val TIMEOUT_MS = 12000L
/** Test status listener for requests */
-class TestStatusListener : StatusListener() {
+class TestStatusListener : StatusListener {
private val statusFuture = CompletableFuture<Int>()
override fun onStatus(status: Int) {
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestUploadDataProvider.java b/Cronet/tests/cts/src/android/net/http/cts/util/TestUploadDataProvider.java
deleted file mode 100644
index d047828..0000000
--- a/Cronet/tests/cts/src/android/net/http/cts/util/TestUploadDataProvider.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2022 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.http.cts.util;
-
-import android.net.http.UploadDataProvider;
-import android.net.http.UploadDataSink;
-import android.os.ConditionVariable;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.ClosedChannelException;
-import java.util.ArrayList;
-import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/** An UploadDataProvider implementation used in tests. */
-public class TestUploadDataProvider extends UploadDataProvider {
- // Indicates whether all success callbacks are synchronous or asynchronous.
- // Doesn't apply to errors.
- public enum SuccessCallbackMode {
- SYNC,
- ASYNC
- }
-
- // Indicates whether failures should throw exceptions, invoke callbacks
- // synchronously, or invoke callback asynchronously.
- public enum FailMode {
- NONE,
- THROWN,
- CALLBACK_SYNC,
- CALLBACK_ASYNC
- }
-
- private final ArrayList<byte[]> mReads = new ArrayList<byte[]>();
- private final SuccessCallbackMode mSuccessCallbackMode;
- private final Executor mExecutor;
-
- private boolean mChunked;
-
- // Index of read to fail on.
- private int mReadFailIndex = -1;
- // Indicates how to fail on a read.
- private FailMode mReadFailMode = FailMode.NONE;
-
- private FailMode mRewindFailMode = FailMode.NONE;
-
- private FailMode mLengthFailMode = FailMode.NONE;
-
- private int mNumReadCalls;
- private int mNumRewindCalls;
-
- private int mNextRead;
- private boolean mStarted;
- private boolean mReadPending;
- private boolean mRewindPending;
- // Used to ensure there are no read/rewind requests after a failure.
- private boolean mFailed;
-
- private final AtomicBoolean mClosed = new AtomicBoolean(false);
- private final ConditionVariable mAwaitingClose = new ConditionVariable(false);
-
- public TestUploadDataProvider(
- SuccessCallbackMode successCallbackMode, final Executor executor) {
- mSuccessCallbackMode = successCallbackMode;
- mExecutor = executor;
- }
-
- // Adds the result to be returned by a successful read request. The
- // returned bytes must all fit within the read buffer provided by Cronet.
- // After a rewind, if there is one, all reads will be repeated.
- public void addRead(byte[] read) {
- if (mStarted) {
- throw new IllegalStateException("Adding bytes after read");
- }
- mReads.add(read);
- }
-
- public void setReadFailure(int readFailIndex, FailMode readFailMode) {
- mReadFailIndex = readFailIndex;
- mReadFailMode = readFailMode;
- }
-
- public void setLengthFailure() {
- mLengthFailMode = FailMode.THROWN;
- }
-
- public void setRewindFailure(FailMode rewindFailMode) {
- mRewindFailMode = rewindFailMode;
- }
-
- public void setChunked(boolean chunked) {
- mChunked = chunked;
- }
-
- public int getNumReadCalls() {
- return mNumReadCalls;
- }
-
- public int getNumRewindCalls() {
- return mNumRewindCalls;
- }
-
- /** Returns the cumulative length of all data added by calls to addRead. */
- @Override
- public long getLength() throws IOException {
- if (mClosed.get()) {
- throw new ClosedChannelException();
- }
- if (mLengthFailMode == FailMode.THROWN) {
- throw new IllegalStateException("Sync length failure");
- }
- return getUploadedLength();
- }
-
- public long getUploadedLength() {
- if (mChunked) {
- return -1;
- }
- long length = 0;
- for (byte[] read : mReads) {
- length += read.length;
- }
- return length;
- }
-
- @Override
- public void read(final UploadDataSink uploadDataSink, final ByteBuffer byteBuffer)
- throws IOException {
- int currentReadCall = mNumReadCalls;
- ++mNumReadCalls;
- if (mClosed.get()) {
- throw new ClosedChannelException();
- }
- assertIdle();
-
- if (maybeFailRead(currentReadCall, uploadDataSink)) {
- mFailed = true;
- return;
- }
-
- mReadPending = true;
- mStarted = true;
-
- final boolean finalChunk = (mChunked && mNextRead == mReads.size() - 1);
- if (mNextRead < mReads.size()) {
- if ((byteBuffer.limit() - byteBuffer.position()) < mReads.get(mNextRead).length) {
- throw new IllegalStateException("Read buffer smaller than expected.");
- }
- byteBuffer.put(mReads.get(mNextRead));
- ++mNextRead;
- } else {
- throw new IllegalStateException("Too many reads: " + mNextRead);
- }
-
- Runnable completeRunnable =
- new Runnable() {
- @Override
- public void run() {
- mReadPending = false;
- uploadDataSink.onReadSucceeded(finalChunk);
- }
- };
- if (mSuccessCallbackMode == SuccessCallbackMode.SYNC) {
- completeRunnable.run();
- } else {
- mExecutor.execute(completeRunnable);
- }
- }
-
- @Override
- public void rewind(final UploadDataSink uploadDataSink) throws IOException {
- ++mNumRewindCalls;
- if (mClosed.get()) {
- throw new ClosedChannelException();
- }
- assertIdle();
-
- if (maybeFailRewind(uploadDataSink)) {
- mFailed = true;
- return;
- }
-
- if (mNextRead == 0) {
- // Should never try and rewind when rewinding does nothing.
- throw new IllegalStateException("Unexpected rewind when already at beginning");
- }
-
- mRewindPending = true;
- mNextRead = 0;
-
- Runnable completeRunnable =
- new Runnable() {
- @Override
- public void run() {
- mRewindPending = false;
- uploadDataSink.onRewindSucceeded();
- }
- };
- if (mSuccessCallbackMode == SuccessCallbackMode.SYNC) {
- completeRunnable.run();
- } else {
- mExecutor.execute(completeRunnable);
- }
- }
-
- private void assertIdle() {
- if (mReadPending) {
- throw new IllegalStateException("Unexpected operation during read");
- }
- if (mRewindPending) {
- throw new IllegalStateException("Unexpected operation during rewind");
- }
- if (mFailed) {
- throw new IllegalStateException("Unexpected operation after failure");
- }
- }
-
- private boolean maybeFailRead(int readIndex, final UploadDataSink uploadDataSink) {
- if (readIndex != mReadFailIndex) return false;
-
- switch (mReadFailMode) {
- case THROWN:
- throw new IllegalStateException("Thrown read failure");
- case CALLBACK_SYNC:
- uploadDataSink.onReadError(new IllegalStateException("Sync read failure"));
- return true;
- case CALLBACK_ASYNC:
- Runnable errorRunnable =
- new Runnable() {
- @Override
- public void run() {
- uploadDataSink.onReadError(
- new IllegalStateException("Async read failure"));
- }
- };
- mExecutor.execute(errorRunnable);
- return true;
- default:
- return false;
- }
- }
-
- private boolean maybeFailRewind(final UploadDataSink uploadDataSink) {
- switch (mRewindFailMode) {
- case THROWN:
- throw new IllegalStateException("Thrown rewind failure");
- case CALLBACK_SYNC:
- uploadDataSink.onRewindError(new IllegalStateException("Sync rewind failure"));
- return true;
- case CALLBACK_ASYNC:
- Runnable errorRunnable =
- new Runnable() {
- @Override
- public void run() {
- uploadDataSink.onRewindError(
- new IllegalStateException("Async rewind failure"));
- }
- };
- mExecutor.execute(errorRunnable);
- return true;
- default:
- return false;
- }
- }
-
- @Override
- public void close() throws IOException {
- if (!mClosed.compareAndSet(false, true)) {
- throw new AssertionError("Closed twice");
- }
- mAwaitingClose.open();
- }
-
- public void assertClosed() {
- mAwaitingClose.block(5000);
- if (!mClosed.get()) {
- throw new AssertionError("Was not closed");
- }
- }
-}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java b/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java
index 0b9e90f..28443b7 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestUrlRequestCallback.java
@@ -16,13 +16,19 @@
package android.net.http.cts.util;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.core.AnyOf.anyOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeThat;
+import static org.junit.Assume.assumeTrue;
import android.net.http.CallbackException;
import android.net.http.HttpException;
@@ -44,7 +50,7 @@
* method to block thread until the request completes on another thread.
* Allows us to cancel, block request or throw an exception from an arbitrary step.
*/
-public class TestUrlRequestCallback extends UrlRequest.Callback {
+public class TestUrlRequestCallback implements UrlRequest.Callback {
private static final int TIMEOUT_MS = 12_000;
public ArrayList<UrlResponseInfo> mRedirectResponseInfoList = new ArrayList<>();
public ArrayList<String> mRedirectUrlList = new ArrayList<>();
@@ -232,6 +238,19 @@
}
/**
+ * Waits for a terminal callback to complete execution before skipping the test if the
+ * callback is not the expected one
+ *
+ * @param expectedStep the expected callback step
+ */
+ public void assumeCallback(ResponseStep expectedStep) {
+ if (isTerminalCallback(expectedStep)) {
+ assumeTrue("Did not receive terminal callback before timeout", blockForDone());
+ }
+ assumeThat(expectedStep, equalTo(mResponseStep));
+ }
+
+ /**
* Blocks the calling thread until one of the final states has been called.
* This is called before the callback has finished executed.
*/
@@ -272,8 +291,9 @@
UrlRequest request, UrlResponseInfo info, String newLocationUrl) {
checkExecutorThread();
assertFalse(request.isDone());
- assertTrue(mResponseStep == ResponseStep.NOTHING
- || mResponseStep == ResponseStep.ON_RECEIVED_REDIRECT);
+ assertThat(mResponseStep, anyOf(
+ equalTo(ResponseStep.NOTHING),
+ equalTo(ResponseStep.ON_RECEIVED_REDIRECT)));
assertNull(mError);
mResponseStep = ResponseStep.ON_RECEIVED_REDIRECT;
@@ -290,8 +310,9 @@
public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {
checkExecutorThread();
assertFalse(request.isDone());
- assertTrue(mResponseStep == ResponseStep.NOTHING
- || mResponseStep == ResponseStep.ON_RECEIVED_REDIRECT);
+ assertThat(mResponseStep, anyOf(
+ equalTo(ResponseStep.NOTHING),
+ equalTo(ResponseStep.ON_RECEIVED_REDIRECT)));
assertNull(mError);
mResponseStep = ResponseStep.ON_RESPONSE_STARTED;
@@ -306,8 +327,9 @@
public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
checkExecutorThread();
assertFalse(request.isDone());
- assertTrue(mResponseStep == ResponseStep.ON_RESPONSE_STARTED
- || mResponseStep == ResponseStep.ON_READ_COMPLETED);
+ assertThat(mResponseStep, anyOf(
+ equalTo(ResponseStep.ON_RESPONSE_STARTED),
+ equalTo(ResponseStep.ON_READ_COMPLETED)));
assertNull(mError);
mResponseStep = ResponseStep.ON_READ_COMPLETED;
@@ -333,8 +355,9 @@
public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
checkExecutorThread();
assertTrue(request.isDone());
- assertTrue(mResponseStep == ResponseStep.ON_RESPONSE_STARTED
- || mResponseStep == ResponseStep.ON_READ_COMPLETED);
+ assertThat(mResponseStep, anyOf(
+ equalTo(ResponseStep.ON_RESPONSE_STARTED),
+ equalTo(ResponseStep.ON_READ_COMPLETED)));
assertFalse(mOnErrorCalled);
assertFalse(mOnCanceledCalled);
assertNull(mError);
@@ -357,7 +380,7 @@
checkExecutorThread();
assertTrue(request.isDone());
// Shouldn't happen after success.
- assertTrue(mResponseStep != ResponseStep.ON_SUCCEEDED);
+ assertNotEquals(ResponseStep.ON_SUCCEEDED, mResponseStep);
// Should happen at most once for a single request.
assertFalse(mOnErrorCalled);
assertFalse(mOnCanceledCalled);
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/TestUtils.kt b/Cronet/tests/cts/src/android/net/http/cts/util/TestUtils.kt
index d30c059..7fc005a 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/util/TestUtils.kt
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/TestUtils.kt
@@ -19,15 +19,22 @@
import android.content.Context
import android.net.ConnectivityManager
import android.net.http.UrlResponseInfo
+import org.hamcrest.Matchers.equalTo
import org.junit.Assert.assertEquals
import org.junit.Assume.assumeNotNull
+import org.junit.Assume.assumeThat
fun skipIfNoInternetConnection(context: Context) {
val connectivityManager = context.getSystemService(ConnectivityManager::class.java)
assumeNotNull(
- "This test requires a working Internet connection", connectivityManager.getActiveNetwork())
+ "This test requires a working Internet connection", connectivityManager!!.activeNetwork
+ )
}
fun assertOKStatusCode(info: UrlResponseInfo) {
- assertEquals("Status code must be 200 OK", 200, info.getHttpStatusCode())
+ assertEquals("Status code must be 200 OK", 200, info.httpStatusCode)
+}
+
+fun assumeOKStatusCode(info: UrlResponseInfo) {
+ assumeThat("Status code must be 200 OK", info.httpStatusCode, equalTo(200))
}
diff --git a/Cronet/tests/cts/src/android/net/http/cts/util/UploadDataProviders.java b/Cronet/tests/cts/src/android/net/http/cts/util/UploadDataProviders.java
new file mode 100644
index 0000000..3b90fa0
--- /dev/null
+++ b/Cronet/tests/cts/src/android/net/http/cts/util/UploadDataProviders.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2023 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.http.cts.util;
+
+import android.net.http.UploadDataProvider;
+import android.net.http.UploadDataSink;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Provides implementations of {@link UploadDataProvider} for common use cases. Corresponds to
+ * {@code android.net.http.apihelpers.UploadDataProviders} which is not an exposed API.
+ */
+public final class UploadDataProviders {
+ /**
+ * Uploads an entire file.
+ *
+ * @param file The file to upload
+ * @return A new UploadDataProvider for the given file
+ */
+ public static UploadDataProvider create(final File file) {
+ return new FileUploadProvider(() -> new FileInputStream(file).getChannel());
+ }
+
+ /**
+ * Uploads an entire file, closing the descriptor when it is no longer needed.
+ *
+ * @param fd The file descriptor to upload
+ * @throws IllegalArgumentException if {@code fd} is not a file.
+ * @return A new UploadDataProvider for the given file descriptor
+ */
+ public static UploadDataProvider create(final ParcelFileDescriptor fd) {
+ return new FileUploadProvider(() -> {
+ if (fd.getStatSize() != -1) {
+ return new ParcelFileDescriptor.AutoCloseInputStream(fd).getChannel();
+ } else {
+ fd.close();
+ throw new IllegalArgumentException("Not a file: " + fd);
+ }
+ });
+ }
+
+ /**
+ * Uploads a ByteBuffer, from the current {@code buffer.position()} to {@code buffer.limit()}
+ *
+ * @param buffer The data to upload
+ * @return A new UploadDataProvider for the given buffer
+ */
+ public static UploadDataProvider create(ByteBuffer buffer) {
+ return new ByteBufferUploadProvider(buffer.slice());
+ }
+
+ /**
+ * Uploads {@code length} bytes from {@code data}, starting from {@code offset}
+ *
+ * @param data Array containing data to upload
+ * @param offset Offset within data to start with
+ * @param length Number of bytes to upload
+ * @return A new UploadDataProvider for the given data
+ */
+ public static UploadDataProvider create(byte[] data, int offset, int length) {
+ return new ByteBufferUploadProvider(ByteBuffer.wrap(data, offset, length).slice());
+ }
+
+ /**
+ * Uploads the contents of {@code data}
+ *
+ * @param data Array containing data to upload
+ * @return A new UploadDataProvider for the given data
+ */
+ public static UploadDataProvider create(byte[] data) {
+ return create(data, 0, data.length);
+ }
+
+ /**
+ * Uploads the UTF-8 representation of {@code data}
+ *
+ * @param data String containing data to upload
+ * @return A new UploadDataProvider for the given data
+ */
+ public static UploadDataProvider create(String data) {
+ return create(data.getBytes(StandardCharsets.UTF_8));
+ }
+
+ private interface FileChannelProvider {
+ FileChannel getChannel() throws IOException;
+ }
+
+ private static final class FileUploadProvider extends UploadDataProvider {
+ private volatile FileChannel mChannel;
+ private final FileChannelProvider mProvider;
+ /** Guards initialization of {@code mChannel} */
+ private final Object mLock = new Object();
+
+ private FileUploadProvider(FileChannelProvider provider) {
+ this.mProvider = provider;
+ }
+
+ @Override
+ public long getLength() throws IOException {
+ return getChannel().size();
+ }
+
+ @Override
+ public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) throws IOException {
+ if (!byteBuffer.hasRemaining()) {
+ throw new IllegalStateException("Cronet passed a buffer with no bytes remaining");
+ }
+ FileChannel channel = getChannel();
+ int bytesRead = 0;
+ while (bytesRead == 0) {
+ int read = channel.read(byteBuffer);
+ if (read == -1) {
+ break;
+ } else {
+ bytesRead += read;
+ }
+ }
+ uploadDataSink.onReadSucceeded(false);
+ }
+
+ @Override
+ public void rewind(UploadDataSink uploadDataSink) throws IOException {
+ getChannel().position(0);
+ uploadDataSink.onRewindSucceeded();
+ }
+
+ /**
+ * Lazily initializes the channel so that a blocking operation isn't performed
+ * on a non-executor thread.
+ */
+ private FileChannel getChannel() throws IOException {
+ if (mChannel == null) {
+ synchronized (mLock) {
+ if (mChannel == null) {
+ mChannel = mProvider.getChannel();
+ }
+ }
+ }
+ return mChannel;
+ }
+
+ @Override
+ public void close() throws IOException {
+ FileChannel channel = mChannel;
+ if (channel != null) {
+ channel.close();
+ }
+ }
+ }
+
+ private static final class ByteBufferUploadProvider extends UploadDataProvider {
+ private final ByteBuffer mUploadBuffer;
+
+ private ByteBufferUploadProvider(ByteBuffer uploadBuffer) {
+ this.mUploadBuffer = uploadBuffer;
+ }
+
+ @Override
+ public long getLength() {
+ return mUploadBuffer.limit();
+ }
+
+ @Override
+ public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) {
+ if (!byteBuffer.hasRemaining()) {
+ throw new IllegalStateException("Cronet passed a buffer with no bytes remaining");
+ }
+ if (byteBuffer.remaining() >= mUploadBuffer.remaining()) {
+ byteBuffer.put(mUploadBuffer);
+ } else {
+ int oldLimit = mUploadBuffer.limit();
+ mUploadBuffer.limit(mUploadBuffer.position() + byteBuffer.remaining());
+ byteBuffer.put(mUploadBuffer);
+ mUploadBuffer.limit(oldLimit);
+ }
+ uploadDataSink.onReadSucceeded(false);
+ }
+
+ @Override
+ public void rewind(UploadDataSink uploadDataSink) {
+ mUploadBuffer.position(0);
+ uploadDataSink.onRewindSucceeded();
+ }
+ }
+
+ // Prevent instantiation
+ private UploadDataProviders() {}
+}
diff --git a/Cronet/tests/mts/Android.bp b/Cronet/tests/mts/Android.bp
new file mode 100644
index 0000000..ecf4b7f
--- /dev/null
+++ b/Cronet/tests/mts/Android.bp
@@ -0,0 +1,75 @@
+// Copyright (C) 2023 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_genrule {
+ name: "net-http-test-jarjar-rules",
+ defaults: ["CronetTestJavaDefaults"],
+ tool_files: [
+ ":NetHttpTestsLibPreJarJar{.jar}",
+ "jarjar_excludes.txt",
+ ],
+ tools: [
+ "jarjar-rules-generator",
+ ],
+ out: ["net_http_test_jarjar_rules.txt"],
+ cmd: "$(location jarjar-rules-generator) " +
+ "$(location :NetHttpTestsLibPreJarJar{.jar}) " +
+ "--prefix android.net.connectivity " +
+ "--excludes $(location jarjar_excludes.txt) " +
+ "--output $(out)",
+}
+
+android_library {
+ name: "NetHttpTestsLibPreJarJar",
+ defaults: ["CronetTestJavaDefaults"],
+ srcs: [":cronet_aml_javatests_sources"],
+ sdk_version: "module_current",
+ min_sdk_version: "30",
+ static_libs: [
+ "cronet_testserver_utils",
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "junit",
+ ],
+ libs: [
+ "android.test.base",
+ "framework-connectivity-pre-jarjar",
+ // android.net.TrafficStats apis
+ "framework-connectivity-t",
+ ],
+ lint: { test: true }
+}
+
+android_test {
+ name: "NetHttpTests",
+ defaults: [
+ "CronetTestJavaDefaults",
+ "mts-target-sdk-version-current",
+ ],
+ static_libs: ["NetHttpTestsLibPreJarJar"],
+ jarjar_rules: ":net-http-test-jarjar-rules",
+ jni_libs: [
+ "cronet_aml_components_cronet_android_cronet_tests__testing"
+ ],
+ test_suites: [
+ "general-tests",
+ "mts-tethering",
+ ],
+}
+
diff --git a/Cronet/tests/mts/AndroidManifest.xml b/Cronet/tests/mts/AndroidManifest.xml
new file mode 100644
index 0000000..f597134
--- /dev/null
+++ b/Cronet/tests/mts/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.net.http.mts">
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.INTERNET"/>
+
+ <application android:networkSecurityConfig="@xml/network_security_config">
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.net.http.mts"
+ android:label="MTS tests of android.net.http">
+ </instrumentation>
+
+</manifest>
\ No newline at end of file
diff --git a/Cronet/tests/mts/AndroidTest.xml b/Cronet/tests/mts/AndroidTest.xml
new file mode 100644
index 0000000..0d780a1
--- /dev/null
+++ b/Cronet/tests/mts/AndroidTest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+<configuration description="Runs NetHttp Mainline Tests.">
+ <!-- Only run tests if the device under test is SDK version 30 or above. -->
+ <!-- TODO Switch back to Sdk30 when b/270049141 is fixed -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="NetHttpTests.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="NetHttpTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.net.http.mts" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+
+ <!-- Only run NetHttpTests in MTS if the Tethering Mainline module is installed. -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.tethering" />
+ </object>
+</configuration>
\ No newline at end of file
diff --git a/Cronet/tests/mts/jarjar_excludes.txt b/Cronet/tests/mts/jarjar_excludes.txt
new file mode 100644
index 0000000..cf3a017
--- /dev/null
+++ b/Cronet/tests/mts/jarjar_excludes.txt
@@ -0,0 +1,13 @@
+# It's prohibited to jarjar androidx packages
+androidx\..+
+# Do not jarjar the api classes
+android\.net\..+
+# cronet_tests.so is not jarjared and uses base classes. We can remove this when there's a
+# separate java base target to depend on.
+org\.chromium\.base\..+
+# Do not jarjar the tests and its utils as they also do JNI with cronet_tests.so
+org\.chromium\.net\..*Test.*(\$.+)?
+org\.chromium\.net\.NativeTestServer(\$.+)?
+org\.chromium\.net\.MockUrlRequestJobFactory(\$.+)?
+org\.chromium\.net\.QuicTestServer(\$.+)?
+org\.chromium\.net\.MockCertVerifier(\$.+)?
\ No newline at end of file
diff --git a/Cronet/tests/mts/res/xml/network_security_config.xml b/Cronet/tests/mts/res/xml/network_security_config.xml
new file mode 100644
index 0000000..d44c36f
--- /dev/null
+++ b/Cronet/tests/mts/res/xml/network_security_config.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+
+<network-security-config>
+ <domain-config cleartextTrafficPermitted="true">
+ <!-- Used as the base URL by native test server (net::EmbeddedTestServer) -->
+ <domain includeSubdomains="true">127.0.0.1</domain>
+ <!-- Used by CronetHttpURLConnectionTest#testIOExceptionInterruptRethrown -->
+ <domain includeSubdomains="true">localhost</domain>
+ <!-- Used by CronetHttpURLConnectionTest#testBadIP -->
+ <domain includeSubdomains="true">0.0.0.0</domain>
+ <!-- Used by CronetHttpURLConnectionTest#testSetUseCachesFalse -->
+ <domain includeSubdomains="true">host-cache-test-host</domain>
+ <!-- Used by CronetHttpURLConnectionTest#testBadHostname -->
+ <domain includeSubdomains="true">this-weird-host-name-does-not-exist</domain>
+ <!-- Used by CronetUrlRequestContextTest#testHostResolverRules -->
+ <domain includeSubdomains="true">some-weird-hostname</domain>
+ </domain-config>
+</network-security-config>
\ No newline at end of file
diff --git a/Cronet/tools/import/copy.bara.sky b/Cronet/tools/import/copy.bara.sky
new file mode 100644
index 0000000..5372a4d
--- /dev/null
+++ b/Cronet/tools/import/copy.bara.sky
@@ -0,0 +1,119 @@
+# Copyright 2023 Google Inc. All rights reserved.
+#
+# 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_excludes = [
+ # Exclude all Android build files
+ "**/Android.bp",
+ "**/Android.mk",
+
+ # Exclude existing *OWNERS files
+ "**/*OWNERS",
+ "**/.git/**",
+ "**/.gitignore",
+]
+
+cronet_origin_files = glob(
+ include = [
+ "base/**",
+ "build/**",
+ "build/buildflag.h",
+ "chrome/VERSION",
+ "components/cronet/**",
+ "components/metrics/**",
+ "components/nacl/**",
+ "components/prefs/**",
+ "crypto/**",
+ "ipc/**",
+ "net/**",
+ # Note: Only used for tests.
+ "testing/**",
+ "url/**",
+ "LICENSE",
+ ],
+ exclude = common_excludes + [
+ # Per aosp/2367109
+ "build/android/CheckInstallApk-debug.apk",
+ "build/android/unused_resources/**",
+ "build/linux/**",
+
+ # Per aosp/2374766
+ "components/cronet/ios/**",
+ "components/cronet/native/**",
+
+ # Per aosp/2399270
+ "testing/buildbot/**",
+
+ # Exclude all third-party directories. Those are specified explicitly
+ # below, so no dependency can accidentally creep in.
+ "**/third_party/**",
+ ],
+) + glob(
+ # Explicitly include third-party dependencies.
+ # Note: some third-party dependencies include a third_party folder within
+ # them. So far, this has not become a problem.
+ include = [
+ "base/third_party/cityhash/**",
+ "base/third_party/cityhash_v103/**",
+ "base/third_party/double_conversion/**",
+ "base/third_party/dynamic_annotations/**",
+ "base/third_party/icu/**",
+ "base/third_party/nspr/**",
+ "base/third_party/superfasthash/**",
+ "base/third_party/valgrind/**",
+ "buildtools/third_party/libc++/**",
+ "buildtools/third_party/libc++abi/**",
+ # Note: Only used for tests.
+ "net/third_party/nist-pkits/**",
+ "net/third_party/quiche/**",
+ "net/third_party/uri_template/**",
+ "third_party/abseil-cpp/**",
+ "third_party/android_ndk/sources/android/cpufeatures/**",
+ "third_party/ashmem/**",
+ "third_party/boringssl/**",
+ "third_party/brotli/**",
+ # Note: Only used for tests.
+ "third_party/ced/**",
+ # Note: Only used for tests.
+ "third_party/googletest/**",
+ "third_party/icu/**",
+ "third_party/libevent/**",
+ # Note: Only used for tests.
+ "third_party/libxml/**",
+ # Note: Only used for tests.
+ "third_party/lss/**",
+ "third_party/metrics_proto/**",
+ "third_party/modp_b64/**",
+ "third_party/protobuf/**",
+ # Note: Only used for tests.
+ "third_party/quic_trace/**",
+ # Note: Cronet currently uses Android's zlib
+ # "third_party/zlib/**",
+ "url/third_party/mozilla/**",
+ ],
+ exclude = common_excludes,
+)
+
+core.workflow(
+ name = "import_cronet",
+ authoring = authoring.overwrite("Cronet Mainline Eng <cronet-mainline-eng+copybara@google.com>"),
+ # Origin folder is specified via source_ref argument, see import_cronet.sh
+ origin = folder.origin(),
+ origin_files = cronet_origin_files,
+ destination = git.destination(
+ # The destination URL is set by the invoking script.
+ url = "overwritten/by/script",
+ push = "upstream-import",
+ ),
+ mode = "SQUASH",
+)
diff --git a/Cronet/tools/import/import_cronet.sh b/Cronet/tools/import/import_cronet.sh
new file mode 100755
index 0000000..0f04af7
--- /dev/null
+++ b/Cronet/tools/import/import_cronet.sh
@@ -0,0 +1,146 @@
+#!/bin/bash
+
+# Copyright 2023 Google Inc. All rights reserved.
+#
+# 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.
+
+# Script to invoke copybara locally to import Cronet into Android.
+# Inputs:
+# Environment:
+# ANDROID_BUILD_TOP: path the root of the current Android directory.
+# Arguments:
+# -l rev: The last revision that was imported.
+# Optional Arguments:
+# -n rev: The new revision to import.
+# -f: Force copybara to ignore a failure to find the last imported revision.
+
+set -e -x
+
+OPTSTRING=fl:n:
+
+usage() {
+ cat <<EOF
+Usage: import_cronet.sh -n new-rev [-l last-rev] [-f]
+EOF
+ exit 1
+}
+
+COPYBARA_FOLDER_ORIGIN="/tmp/copybara-origin"
+
+#######################################
+# Create local upstream-import branch in external/cronet.
+# Globals:
+# ANDROID_BUILD_TOP
+# Arguments:
+# none
+#######################################
+setup_upstream_import_branch() {
+ local git_dir="${ANDROID_BUILD_TOP}/external/cronet"
+
+ (cd "${git_dir}" && git fetch aosp upstream-import:upstream-import)
+}
+
+#######################################
+# Setup folder.origin for copybara inside /tmp
+# Globals:
+# COPYBARA_FOLDER_ORIGIN
+# Arguments:
+# new_rev, string
+#######################################
+setup_folder_origin() (
+ local _new_rev=$1
+ mkdir -p "${COPYBARA_FOLDER_ORIGIN}"
+ cd "${COPYBARA_FOLDER_ORIGIN}"
+
+ if [ -d src ]; then
+ (cd src && git fetch --tags && git checkout "${_new_rev}")
+ else
+ # For this to work _new_rev must be a branch or a tag.
+ git clone --depth=1 --branch "${_new_rev}" https://chromium.googlesource.com/chromium/src.git
+ fi
+
+
+ cat <<EOF >.gclient
+solutions = [
+ {
+ "name": "src",
+ "url": "https://chromium.googlesource.com/chromium/src.git",
+ "managed": False,
+ "custom_deps": {},
+ "custom_vars": {},
+ },
+]
+target_os = ["android"]
+EOF
+ cd src
+ # Set appropriate gclient flags to speed up syncing.
+ gclient sync \
+ --no-history \
+ --shallow \
+ --delete_unversioned_trees
+)
+
+#######################################
+# Runs the copybara import of Chromium
+# Globals:
+# ANDROID_BUILD_TOP
+# COPYBARA_FOLDER_ORIGIN
+# Arguments:
+# last_rev, string or empty
+# force, string or empty
+#######################################
+do_run_copybara() {
+ local _last_rev=$1
+ local _force=$2
+
+ local -a flags
+ flags+=(--git-destination-url="file://${ANDROID_BUILD_TOP}/external/cronet")
+ flags+=(--repo-timeout 3m)
+
+ # buildtools/third_party/libc++ contains an invalid symlink
+ flags+=(--folder-origin-ignore-invalid-symlinks)
+ flags+=(--git-no-verify)
+
+ if [ ! -z "${_force}" ]; then
+ flags+=(--force)
+ fi
+
+ if [ ! -z "${_last_rev}" ]; then
+ flags+=(--last-rev "${_last_rev}")
+ fi
+
+ /google/bin/releases/copybara/public/copybara/copybara \
+ "${flags[@]}" \
+ "${ANDROID_BUILD_TOP}/packages/modules/Connectivity/Cronet/tools/import/copy.bara.sky" \
+ import_cronet "${COPYBARA_FOLDER_ORIGIN}/src"
+}
+
+while getopts $OPTSTRING opt; do
+ case "${opt}" in
+ f) force=true ;;
+ l) last_rev="${OPTARG}" ;;
+ n) new_rev="${OPTARG}" ;;
+ ?) usage ;;
+ *) echo "'${opt}' '${OPTARG}'"
+ esac
+done
+
+if [ -z "${new_rev}" ]; then
+ echo "-n argument required"
+ usage
+fi
+
+setup_upstream_import_branch
+setup_folder_origin "${new_rev}"
+do_run_copybara "${last_rev}" "${force}"
+
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a1e81c8..d2f6d6a 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -58,15 +58,23 @@
]
},
{
+ "name": "CtsNetTestCasesMaxTargetSdk33",
+ "options": [
+ {
+ "exclude-annotation": "com.android.testutils.SkipPresubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "bpf_existence_test"
},
{
"name": "connectivity_native_test"
},
{
- "name": "CtsNetHttpTestCases"
- },
- {
"name": "libclat_test"
},
{
@@ -86,6 +94,16 @@
},
{
"name": "FrameworksNetIntegrationTests"
+ },
+ // Runs both NetHttpTests and CtsNetHttpTestCases
+ {
+ "name": "NetHttpCoverageTests",
+ "options": [
+ {
+ // These sometimes take longer than 1 min which is the presubmit timeout
+ "exclude-annotation": "androidx.test.filters.LargeTest"
+ }
+ ]
}
],
"postsubmit": [
@@ -138,6 +156,17 @@
}
]
},
+ {
+ "name": "CtsNetTestCasesMaxTargetSdk33[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
+ "options": [
+ {
+ "exclude-annotation": "com.android.testutils.SkipPresubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.RequiresDevice"
+ }
+ ]
+ },
// Test with APK modules only, in cases where APEX is not supported, or the other modules
// were simply not updated
{
@@ -186,6 +215,15 @@
},
{
"name": "libnetworkstats_test[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]"
+ },
+ {
+ "name": "NetHttpCoverageTests[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]",
+ "options": [
+ {
+ // These sometimes take longer than 1 min which is the presubmit timeout
+ "exclude-annotation": "androidx.test.filters.LargeTest"
+ }
+ ]
}
],
"mainline-postsubmit": [
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index d2f6d15..83ca2b7 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -61,9 +61,13 @@
"modules-utils-build",
"modules-utils-statemachine",
"networkstack-client",
+ // AIDL tetheroffload implementation
+ "android.hardware.tetheroffload-V1-java",
+ // HIDL tetheroffload implementation
"android.hardware.tetheroffload.config-V1.0-java",
"android.hardware.tetheroffload.control-V1.0-java",
"android.hardware.tetheroffload.control-V1.1-java",
+ "android.hidl.manager-V1.2-java",
"net-utils-framework-common",
"net-utils-device-common",
"net-utils-device-common-bpf",
@@ -246,6 +250,9 @@
// e.g. *classpath_fragments.
"com.android.tethering",
],
+ native_shared_libs: [
+ "libnetd_updatable",
+ ],
}
java_library_static {
diff --git a/Tethering/AndroidManifest.xml b/Tethering/AndroidManifest.xml
index 23467e7..6a363b0 100644
--- a/Tethering/AndroidManifest.xml
+++ b/Tethering/AndroidManifest.xml
@@ -45,7 +45,6 @@
<!-- Sending non-protected broadcast from system uid is not allowed. -->
<protected-broadcast android:name="com.android.server.connectivity.tethering.DISABLE_TETHERING" />
- <protected-broadcast android:name="com.android.server.connectivity.KeepaliveTracker.TCP_POLLING_ALARM" />
<application
android:process="com.android.networkstack.process"
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index b26911c..d84fef3 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -38,6 +38,13 @@
name: "ConnectivityNextEnableDefaults",
enabled: true,
}
+java_defaults {
+ name: "NetworkStackApiShimSettingsForCurrentBranch",
+ // API shims to include in the networking modules built from the branch. Branches that disable
+ // the "next" targets must use stable shims (latest stable API level) instead of current shims
+ // (X_current API level).
+ static_libs: ["NetworkStackApiCurrentShims"],
+}
apex_defaults {
name: "ConnectivityApexDefaults",
// Tethering app to include in the AOSP apex. Branches that disable the "next" targets may use
@@ -66,11 +73,19 @@
apex_defaults {
name: "CronetInTetheringApexDefaultsEnabled",
- jni_libs: ["cronet_aml_components_cronet_android_cronet"],
+ jni_libs: [
+ "cronet_aml_components_cronet_android_cronet",
+ "//external/cronet/third_party/boringssl:libcrypto",
+ "//external/cronet/third_party/boringssl:libssl",
+ ],
arch: {
riscv64: {
// TODO: remove this when there is a riscv64 libcronet
- exclude_jni_libs: ["cronet_aml_components_cronet_android_cronet"],
+ exclude_jni_libs: [
+ "cronet_aml_components_cronet_android_cronet",
+ "//external/cronet/third_party/boringssl:libcrypto",
+ "//external/cronet/third_party/boringssl:libssl",
+ ],
},
},
}
@@ -144,7 +159,6 @@
compat_configs: [
"connectivity-platform-compat-config",
- "connectivity-t-platform-compat-config",
],
}
@@ -228,7 +242,6 @@
"android.net.apf",
"android.net.connectivity",
"android.net.http.apihelpers",
- "android.net.http.internal",
"android.net.netstats.provider",
"android.net.nsd",
"android.net.wear",
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index 4c677d0..6b62da9 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -30,7 +30,6 @@
java_sdk_library {
name: "framework-tethering",
defaults: [
- "CronetJavaDefaults",
"framework-tethering-defaults",
],
impl_library_visibility: [
@@ -65,6 +64,7 @@
hostdex: true, // for hiddenapi check
permitted_packages: ["android.net"],
+ lint: { strict_updatability_linting: true },
}
java_defaults {
@@ -81,20 +81,11 @@
impl_only_static_libs: [
"cronet_aml_java",
],
- // STOPSHIP(b/265674359): fix all Cronet lint warnings and re-enable lint
- // directly in framework-tethering
- lint: {
- enabled: false,
- },
- api_lint: {
- enabled: false,
- },
- api_dir: "cronet_enabled/api",
}
java_defaults {
name: "CronetJavaDefaultsDisabled",
- lint: { strict_updatability_linting: true },
+ api_dir: "cronet_disabled/api",
}
java_defaults {
@@ -118,7 +109,6 @@
name: "framework-tethering-pre-jarjar",
defaults: [
"framework-tethering-defaults",
- "CronetJavaPrejarjarDefaults",
],
}
@@ -135,7 +125,7 @@
out: ["framework_tethering_jarjar_rules.txt"],
cmd: "$(location jarjar-rules-generator) " +
"$(location :framework-tethering-pre-jarjar{.jar}) " +
- "--apistubs $(location :framework-tethering.stubs.module_lib{.jar}) " +
+ "--apistubs $(location :framework-tethering.stubs.module_lib{.jar}) " +
"--prefix android.net.http.internal " +
"--excludes $(location jarjar-excludes.txt) " +
"--output $(out)",
@@ -159,6 +149,7 @@
filegroup {
name: "framework-tethering-srcs",
+ defaults: ["framework-sources-module-defaults"],
srcs: [
"src/**/*.aidl",
"src/**/*.java",
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/current.txt b/Tethering/common/TetheringLib/cronet_enabled/api/current.txt
deleted file mode 100644
index c0157b7..0000000
--- a/Tethering/common/TetheringLib/cronet_enabled/api/current.txt
+++ /dev/null
@@ -1,194 +0,0 @@
-// Signature format: 2.0
-package android.net.http {
-
- public abstract class CallbackException extends android.net.http.HttpException {
- ctor protected CallbackException(String, Throwable);
- }
-
- public class ConnectionMigrationOptions {
- method @Nullable public Boolean getEnableDefaultNetworkMigration();
- method @Nullable public Boolean getEnablePathDegradationMigration();
- }
-
- public static class ConnectionMigrationOptions.Builder {
- ctor public ConnectionMigrationOptions.Builder();
- method public android.net.http.ConnectionMigrationOptions build();
- method public android.net.http.ConnectionMigrationOptions.Builder setEnableDefaultNetworkMigration(boolean);
- method public android.net.http.ConnectionMigrationOptions.Builder setEnablePathDegradationMigration(boolean);
- }
-
- public final class DnsOptions {
- method @Nullable public Boolean getPersistHostCache();
- method @Nullable public java.time.Duration getPersistHostCachePeriod();
- }
-
- public static final class DnsOptions.Builder {
- ctor public DnsOptions.Builder();
- method public android.net.http.DnsOptions build();
- method public android.net.http.DnsOptions.Builder setPersistHostCache(boolean);
- method public android.net.http.DnsOptions.Builder setPersistHostCachePeriod(java.time.Duration);
- }
-
- public abstract class HttpEngine {
- method public abstract java.net.URLStreamHandlerFactory createURLStreamHandlerFactory();
- method public abstract String getVersionString();
- method public abstract android.net.http.UrlRequest.Builder newUrlRequestBuilder(String, android.net.http.UrlRequest.Callback, java.util.concurrent.Executor);
- method public abstract java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException;
- method public abstract void shutdown();
- }
-
- public static class HttpEngine.Builder {
- ctor public HttpEngine.Builder(android.content.Context);
- method public android.net.http.HttpEngine.Builder addPublicKeyPins(String, java.util.Set<byte[]>, boolean, java.time.Instant);
- method public android.net.http.HttpEngine.Builder addQuicHint(String, int, int);
- method public android.net.http.HttpEngine build();
- method public String getDefaultUserAgent();
- method public android.net.http.HttpEngine.Builder setConnectionMigrationOptions(android.net.http.ConnectionMigrationOptions);
- method public android.net.http.HttpEngine.Builder setDnsOptions(android.net.http.DnsOptions);
- method public android.net.http.HttpEngine.Builder setEnableBrotli(boolean);
- method public android.net.http.HttpEngine.Builder setEnableHttp2(boolean);
- method public android.net.http.HttpEngine.Builder setEnableHttpCache(int, long);
- method public android.net.http.HttpEngine.Builder setEnablePublicKeyPinningBypassForLocalTrustAnchors(boolean);
- method public android.net.http.HttpEngine.Builder setEnableQuic(boolean);
- method public android.net.http.HttpEngine.Builder setQuicOptions(android.net.http.QuicOptions);
- method public android.net.http.HttpEngine.Builder setStoragePath(String);
- method public android.net.http.HttpEngine.Builder setUserAgent(String);
- field public static final int HTTP_CACHE_DISABLED = 0; // 0x0
- field public static final int HTTP_CACHE_DISK = 3; // 0x3
- field public static final int HTTP_CACHE_DISK_NO_HTTP = 2; // 0x2
- field public static final int HTTP_CACHE_IN_MEMORY = 1; // 0x1
- }
-
- public class HttpException extends java.io.IOException {
- ctor public HttpException(String, Throwable);
- }
-
- public final class InlineExecutionProhibitedException extends java.util.concurrent.RejectedExecutionException {
- ctor public InlineExecutionProhibitedException();
- }
-
- public abstract class NetworkException extends android.net.http.HttpException {
- ctor public NetworkException(String, Throwable);
- method public abstract int getErrorCode();
- method public abstract boolean isImmediatelyRetryable();
- field public static final int ERROR_ADDRESS_UNREACHABLE = 9; // 0x9
- field public static final int ERROR_CONNECTION_CLOSED = 5; // 0x5
- field public static final int ERROR_CONNECTION_REFUSED = 7; // 0x7
- field public static final int ERROR_CONNECTION_RESET = 8; // 0x8
- field public static final int ERROR_CONNECTION_TIMED_OUT = 6; // 0x6
- field public static final int ERROR_HOSTNAME_NOT_RESOLVED = 1; // 0x1
- field public static final int ERROR_INTERNET_DISCONNECTED = 2; // 0x2
- field public static final int ERROR_NETWORK_CHANGED = 3; // 0x3
- field public static final int ERROR_OTHER = 11; // 0xb
- field public static final int ERROR_QUIC_PROTOCOL_FAILED = 10; // 0xa
- field public static final int ERROR_TIMED_OUT = 4; // 0x4
- }
-
- public abstract class QuicException extends android.net.http.NetworkException {
- ctor protected QuicException(String, Throwable);
- }
-
- public class QuicOptions {
- method @Nullable public String getHandshakeUserAgent();
- method @Nullable public Integer getInMemoryServerConfigsCacheSize();
- method public java.util.Set<java.lang.String> getQuicHostAllowlist();
- }
-
- public static class QuicOptions.Builder {
- ctor public QuicOptions.Builder();
- method public android.net.http.QuicOptions.Builder addAllowedQuicHost(String);
- method public android.net.http.QuicOptions build();
- method public android.net.http.QuicOptions.Builder setHandshakeUserAgent(String);
- method public android.net.http.QuicOptions.Builder setInMemoryServerConfigsCacheSize(int);
- }
-
- public abstract class UploadDataProvider implements java.io.Closeable {
- ctor public UploadDataProvider();
- method public void close() throws java.io.IOException;
- method public abstract long getLength() throws java.io.IOException;
- method public abstract void read(android.net.http.UploadDataSink, java.nio.ByteBuffer) throws java.io.IOException;
- method public abstract void rewind(android.net.http.UploadDataSink) throws java.io.IOException;
- }
-
- public abstract class UploadDataSink {
- ctor public UploadDataSink();
- method public abstract void onReadError(Exception);
- method public abstract void onReadSucceeded(boolean);
- method public abstract void onRewindError(Exception);
- method public abstract void onRewindSucceeded();
- }
-
- public abstract class UrlRequest {
- method public abstract void cancel();
- method public abstract void followRedirect();
- method public abstract void getStatus(android.net.http.UrlRequest.StatusListener);
- method public abstract boolean isDone();
- method public abstract void read(java.nio.ByteBuffer);
- method public abstract void start();
- }
-
- public abstract static class UrlRequest.Builder {
- method public abstract android.net.http.UrlRequest.Builder addHeader(String, String);
- method public abstract android.net.http.UrlRequest.Builder allowDirectExecutor();
- method public abstract android.net.http.UrlRequest build();
- method public abstract android.net.http.UrlRequest.Builder disableCache();
- method public abstract android.net.http.UrlRequest.Builder setHttpMethod(String);
- method public abstract android.net.http.UrlRequest.Builder setPriority(int);
- method public abstract android.net.http.UrlRequest.Builder setUploadDataProvider(android.net.http.UploadDataProvider, java.util.concurrent.Executor);
- field public static final int REQUEST_PRIORITY_HIGHEST = 4; // 0x4
- field public static final int REQUEST_PRIORITY_IDLE = 0; // 0x0
- field public static final int REQUEST_PRIORITY_LOW = 2; // 0x2
- field public static final int REQUEST_PRIORITY_LOWEST = 1; // 0x1
- field public static final int REQUEST_PRIORITY_MEDIUM = 3; // 0x3
- }
-
- public abstract static class UrlRequest.Callback {
- ctor public UrlRequest.Callback();
- method public void onCanceled(android.net.http.UrlRequest, android.net.http.UrlResponseInfo);
- method public abstract void onFailed(android.net.http.UrlRequest, android.net.http.UrlResponseInfo, android.net.http.HttpException);
- method public abstract void onReadCompleted(android.net.http.UrlRequest, android.net.http.UrlResponseInfo, java.nio.ByteBuffer) throws java.lang.Exception;
- method public abstract void onRedirectReceived(android.net.http.UrlRequest, android.net.http.UrlResponseInfo, String) throws java.lang.Exception;
- method public abstract void onResponseStarted(android.net.http.UrlRequest, android.net.http.UrlResponseInfo) throws java.lang.Exception;
- method public abstract void onSucceeded(android.net.http.UrlRequest, android.net.http.UrlResponseInfo);
- }
-
- public static class UrlRequest.Status {
- field public static final int CONNECTING = 10; // 0xa
- field public static final int DOWNLOADING_PAC_FILE = 5; // 0x5
- field public static final int ESTABLISHING_PROXY_TUNNEL = 8; // 0x8
- field public static final int IDLE = 0; // 0x0
- field public static final int INVALID = -1; // 0xffffffff
- field public static final int READING_RESPONSE = 14; // 0xe
- field public static final int RESOLVING_HOST = 9; // 0x9
- field public static final int RESOLVING_HOST_IN_PAC_FILE = 7; // 0x7
- field public static final int RESOLVING_PROXY_FOR_URL = 6; // 0x6
- field public static final int SENDING_REQUEST = 12; // 0xc
- field public static final int SSL_HANDSHAKE = 11; // 0xb
- field public static final int WAITING_FOR_AVAILABLE_SOCKET = 2; // 0x2
- field public static final int WAITING_FOR_CACHE = 4; // 0x4
- field public static final int WAITING_FOR_DELEGATE = 3; // 0x3
- field public static final int WAITING_FOR_RESPONSE = 13; // 0xd
- field public static final int WAITING_FOR_STALLED_SOCKET_POOL = 1; // 0x1
- }
-
- public abstract static class UrlRequest.StatusListener {
- ctor public UrlRequest.StatusListener();
- method public abstract void onStatus(int);
- }
-
- public abstract class UrlResponseInfo {
- ctor public UrlResponseInfo();
- method public abstract java.util.Map<java.lang.String,java.util.List<java.lang.String>> getAllHeaders();
- method public abstract java.util.List<java.util.Map.Entry<java.lang.String,java.lang.String>> getAllHeadersAsList();
- method public abstract int getHttpStatusCode();
- method public abstract String getHttpStatusText();
- method public abstract String getNegotiatedProtocol();
- method public abstract String getProxyServer();
- method public abstract long getReceivedByteCount();
- method public abstract String getUrl();
- method public abstract java.util.List<java.lang.String> getUrlChain();
- method public abstract boolean wasCached();
- }
-
-}
-
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/module-lib-current.txt b/Tethering/common/TetheringLib/cronet_enabled/api/module-lib-current.txt
deleted file mode 100644
index 460c216..0000000
--- a/Tethering/common/TetheringLib/cronet_enabled/api/module-lib-current.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-// Signature format: 2.0
-package android.net {
-
- public final class TetheringConstants {
- field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
- field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
- field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
- field public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
- field public static final String EXTRA_SET_ALARM = "extraSetAlarm";
- }
-
- public class TetheringManager {
- ctor public TetheringManager(@NonNull android.content.Context, @NonNull java.util.function.Supplier<android.os.IBinder>);
- method public int getLastTetherError(@NonNull String);
- method @NonNull public String[] getTetherableBluetoothRegexs();
- method @NonNull public String[] getTetherableIfaces();
- method @NonNull public String[] getTetherableUsbRegexs();
- method @NonNull public String[] getTetherableWifiRegexs();
- method @NonNull public String[] getTetheredIfaces();
- method @NonNull public String[] getTetheringErroredIfaces();
- method public boolean isTetheringSupported();
- method public boolean isTetheringSupported(@NonNull String);
- method public void requestLatestTetheringEntitlementResult(int, @NonNull android.os.ResultReceiver, boolean);
- method @Deprecated public int setUsbTethering(boolean);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
- method @Deprecated public int tether(@NonNull String);
- method @Deprecated public int untether(@NonNull String);
- }
-
- public static interface TetheringManager.TetheredInterfaceCallback {
- method public void onAvailable(@NonNull String);
- method public void onUnavailable();
- }
-
- public static interface TetheringManager.TetheredInterfaceRequest {
- method public void release();
- }
-
- public static interface TetheringManager.TetheringEventCallback {
- method @Deprecated public default void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
- }
-
- @Deprecated public static class TetheringManager.TetheringInterfaceRegexps {
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
- }
-
-}
-
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/removed.txt b/Tethering/common/TetheringLib/cronet_enabled/api/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/Tethering/common/TetheringLib/cronet_enabled/api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/system-current.txt b/Tethering/common/TetheringLib/cronet_enabled/api/system-current.txt
deleted file mode 100644
index 844ff64..0000000
--- a/Tethering/common/TetheringLib/cronet_enabled/api/system-current.txt
+++ /dev/null
@@ -1,117 +0,0 @@
-// Signature format: 2.0
-package android.net {
-
- public final class TetheredClient implements android.os.Parcelable {
- ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
- method public int describeContents();
- method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
- method @NonNull public android.net.MacAddress getMacAddress();
- method public int getTetheringType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
- }
-
- public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.net.LinkAddress getAddress();
- method @Nullable public String getHostname();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
- }
-
- public final class TetheringInterface implements android.os.Parcelable {
- ctor public TetheringInterface(int, @NonNull String);
- method public int describeContents();
- method @NonNull public String getInterface();
- method public int getType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheringInterface> CREATOR;
- }
-
- public class TetheringManager {
- method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
- field @Deprecated public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
- field public static final int CONNECTIVITY_SCOPE_GLOBAL = 1; // 0x1
- field public static final int CONNECTIVITY_SCOPE_LOCAL = 2; // 0x2
- field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
- field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
- field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
- field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
- field public static final int TETHERING_BLUETOOTH = 2; // 0x2
- field public static final int TETHERING_ETHERNET = 5; // 0x5
- field public static final int TETHERING_INVALID = -1; // 0xffffffff
- field public static final int TETHERING_NCM = 4; // 0x4
- field public static final int TETHERING_USB = 1; // 0x1
- field public static final int TETHERING_WIFI = 0; // 0x0
- field public static final int TETHERING_WIFI_P2P = 3; // 0x3
- field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
- field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9
- field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8
- field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
- field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
- field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5
- field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
- field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
- field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
- field public static final int TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb
- field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
- field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
- field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
- field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
- field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10
- field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
- field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
- field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2
- field public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1; // 0x1
- field public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0; // 0x0
- }
-
- public static interface TetheringManager.OnTetheringEntitlementResultListener {
- method public void onTetheringEntitlementResult(int);
- }
-
- public static interface TetheringManager.StartTetheringCallback {
- method public default void onTetheringFailed(int);
- method public default void onTetheringStarted();
- }
-
- public static interface TetheringManager.TetheringEventCallback {
- method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
- method public default void onError(@NonNull String, int);
- method public default void onError(@NonNull android.net.TetheringInterface, int);
- method public default void onLocalOnlyInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public default void onLocalOnlyInterfacesChanged(@NonNull java.util.Set<android.net.TetheringInterface>);
- method public default void onOffloadStatusChanged(int);
- method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public default void onTetherableInterfacesChanged(@NonNull java.util.Set<android.net.TetheringInterface>);
- method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public default void onTetheredInterfacesChanged(@NonNull java.util.Set<android.net.TetheringInterface>);
- method public default void onTetheringSupported(boolean);
- method public default void onUpstreamChanged(@Nullable android.net.Network);
- }
-
- public static class TetheringManager.TetheringRequest {
- method @Nullable public android.net.LinkAddress getClientStaticIpv4Address();
- method public int getConnectivityScope();
- method @Nullable public android.net.LinkAddress getLocalIpv4Address();
- method public boolean getShouldShowEntitlementUi();
- method public int getTetheringType();
- method public boolean isExemptFromEntitlementCheck();
- }
-
- public static class TetheringManager.TetheringRequest.Builder {
- ctor public TetheringManager.TetheringRequest.Builder(int);
- method @NonNull public android.net.TetheringManager.TetheringRequest build();
- method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setConnectivityScope(int);
- method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress);
- }
-
-}
-
diff --git a/Tethering/jni/com_android_networkstack_tethering_util_TetheringUtils.cpp b/Tethering/jni/com_android_networkstack_tethering_util_TetheringUtils.cpp
index 6699c0d..14e4b9a 100644
--- a/Tethering/jni/com_android_networkstack_tethering_util_TetheringUtils.cpp
+++ b/Tethering/jni/com_android_networkstack_tethering_util_TetheringUtils.cpp
@@ -18,21 +18,19 @@
#include <error.h>
#include <jni.h>
#include <linux/filter.h>
+#include <linux/ipv6.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedUtfChars.h>
#include <netjniutils/netjniutils.h>
#include <net/if.h>
#include <netinet/ether.h>
-#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <sys/socket.h>
#include <stdio.h>
-namespace android {
+#include <bpf/BpfClassic.h>
-static const uint32_t kIPv6NextHeaderOffset = offsetof(ip6_hdr, ip6_nxt);
-static const uint32_t kIPv6PayloadStart = sizeof(ip6_hdr);
-static const uint32_t kICMPv6TypeOffset = kIPv6PayloadStart + offsetof(icmp6_hdr, icmp6_type);
+namespace android {
static void throwSocketException(JNIEnv *env, const char* msg, int error) {
jniThrowExceptionFmt(env, "java/net/SocketException", "%s: %s", msg, strerror(error));
@@ -42,18 +40,14 @@
uint32_t type) {
sock_filter filter_code[] = {
// Check header is ICMPv6.
- BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kIPv6NextHeaderOffset),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
+ BPF_LOAD_IPV6_U8(nexthdr),
+ BPF2_REJECT_IF_NOT_EQUAL(IPPROTO_ICMPV6),
// Check ICMPv6 type.
- BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kICMPv6TypeOffset),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, type, 0, 1),
+ BPF_LOAD_NET_RELATIVE_U8(sizeof(ipv6hdr) + offsetof(icmp6_hdr, icmp6_type)),
+ BPF2_REJECT_IF_NOT_EQUAL(type),
- // Accept.
- BPF_STMT(BPF_RET | BPF_K, 0xffff),
-
- // Reject.
- BPF_STMT(BPF_RET | BPF_K, 0)
+ BPF_ACCEPT,
};
const sock_fprog filter = {
@@ -67,17 +61,17 @@
}
}
-static void com_android_networkstack_tethering_util_setupNaSocket(JNIEnv *env, jobject clazz,
+static void com_android_networkstack_tethering_util_setupNaSocket(JNIEnv *env, jclass clazz,
jobject javaFd) {
com_android_networkstack_tethering_util_setupIcmpFilter(env, javaFd, ND_NEIGHBOR_ADVERT);
}
-static void com_android_networkstack_tethering_util_setupNsSocket(JNIEnv *env, jobject clazz,
+static void com_android_networkstack_tethering_util_setupNsSocket(JNIEnv *env, jclass clazz,
jobject javaFd) {
com_android_networkstack_tethering_util_setupIcmpFilter(env, javaFd, ND_NEIGHBOR_SOLICIT);
}
-static void com_android_networkstack_tethering_util_setupRaSocket(JNIEnv *env, jobject clazz,
+static void com_android_networkstack_tethering_util_setupRaSocket(JNIEnv *env, jclass clazz,
jobject javaFd, jint ifIndex) {
static const int kLinkLocalHopLimit = 255;
diff --git a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
index c452e55..775c36f 100644
--- a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
+++ b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
@@ -88,13 +88,13 @@
private static final int MIN_RTR_ADV_INTERVAL_SEC = 300;
private static final int MAX_RTR_ADV_INTERVAL_SEC = 600;
// In general, router, prefix, and DNS lifetimes are all advised to be
- // greater than or equal to 3 * MAX_RTR_ADV_INTERVAL. Here, we double
+ // greater than or equal to 3 * MAX_RTR_ADV_INTERVAL. Here, we quadruple
// that to allow for multicast packet loss.
//
// This MAX_RTR_ADV_INTERVAL_SEC and DEFAULT_LIFETIME are also consistent
// with the https://tools.ietf.org/html/rfc7772#section-4 discussion of
// "approximately 7 RAs per hour".
- private static final int DEFAULT_LIFETIME = 6 * MAX_RTR_ADV_INTERVAL_SEC;
+ private static final int DEFAULT_LIFETIME = 12 * MAX_RTR_ADV_INTERVAL_SEC;
// From https://tools.ietf.org/html/rfc4861#section-10 .
private static final int MIN_DELAY_BETWEEN_RAS_SEC = 3;
// Both initial and final RAs, but also for changes in RA contents.
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 44d3ffc..976f5df 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -37,6 +37,7 @@
import android.app.usage.NetworkStatsManager;
import android.net.INetd;
+import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.NetworkStats;
import android.net.NetworkStats.Entry;
@@ -878,6 +879,27 @@
return true;
}
+ private int getMtu(@NonNull final String ifaceName, @NonNull final LinkProperties lp) {
+ int mtu = INVALID_MTU;
+
+ if (ifaceName.equals(lp.getInterfaceName())) {
+ mtu = lp.getMtu();
+ }
+
+ // Get mtu via kernel if mtu is not found in LinkProperties.
+ if (mtu == INVALID_MTU) {
+ mtu = mDeps.getNetworkInterfaceMtu(ifaceName);
+ }
+
+ // Use default mtu if can't find any.
+ if (mtu == INVALID_MTU) mtu = NetworkStackConstants.ETHER_MTU;
+
+ // Clamp to minimum ipv4 mtu
+ if (mtu < IPV4_MIN_MTU) mtu = IPV4_MIN_MTU;
+
+ return mtu;
+ }
+
/**
* Call when UpstreamNetworkState may be changed.
* If upstream has ipv4 for tethering, update this new UpstreamNetworkState
@@ -900,16 +922,7 @@
final String ifaceName = ns.linkProperties.getInterfaceName();
final InterfaceParams params = mDeps.getInterfaceParams(ifaceName);
final boolean isVcn = isVcnInterface(ifaceName);
- mtu = ns.linkProperties.getMtu();
- if (mtu == INVALID_MTU) {
- // Get mtu via kernel if mtu is not found in LinkProperties.
- mtu = mDeps.getNetworkInterfaceMtu(ifaceName);
- }
-
- // Use default mtu if can't find any.
- if (mtu == INVALID_MTU) mtu = NetworkStackConstants.ETHER_MTU;
- // Clamp to minimum ipv4 mtu
- if (mtu < IPV4_MIN_MTU) mtu = IPV4_MIN_MTU;
+ mtu = getMtu(ifaceName, ns.linkProperties);
if (!isVcn && params != null && !params.hasMacAddress /* raw ip upstream only */) {
upstreamIndex = params.index;
@@ -2243,5 +2256,13 @@
return mTetherClients;
}
+ // Return map of upstream interface IPv4 address to interface index.
+ // This is used for testing only.
+ @NonNull
+ @VisibleForTesting
+ final HashMap<Inet4Address, Integer> getIpv4UpstreamIndicesForTesting() {
+ return mIpv4UpstreamIndices;
+ }
+
private static native String[] getBpfCounterNames();
}
diff --git a/Tethering/src/com/android/networkstack/tethering/IOffloadHal.java b/Tethering/src/com/android/networkstack/tethering/IOffloadHal.java
new file mode 100644
index 0000000..e66e7ae
--- /dev/null
+++ b/Tethering/src/com/android/networkstack/tethering/IOffloadHal.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 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.networkstack.tethering;
+
+import android.annotation.NonNull;
+import android.os.NativeHandle;
+
+import com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats;
+import com.android.networkstack.tethering.OffloadHardwareInterface.OffloadHalCallback;
+
+import java.util.ArrayList;
+
+/** Abstraction of Tetheroffload HAL interface */
+interface IOffloadHal {
+ /*
+ * Initialize the Tetheroffload HAL. Offload management process need to know conntrack rules to
+ * support NAT, but it may not have permission to create netlink netfilter sockets. Create two
+ * netlink netfilter sockets and share them with offload management process.
+ */
+ boolean initOffload(@NonNull NativeHandle handle1, @NonNull NativeHandle handle2,
+ @NonNull OffloadHalCallback callback);
+
+ /** Stop the Tetheroffload HAL. */
+ boolean stopOffload();
+
+ /** Get HAL interface version number. */
+ int getVersion();
+
+ /** Get Tx/Rx usage from last query. */
+ ForwardedStats getForwardedStats(@NonNull String upstream);
+
+ /** Set local prefixes to offload management process. */
+ boolean setLocalPrefixes(@NonNull ArrayList<String> localPrefixes);
+
+ /** Set data limit value to offload management process. */
+ boolean setDataLimit(@NonNull String iface, long limit);
+
+ /** Set data warning and limit value to offload management process. */
+ boolean setDataWarningAndLimit(@NonNull String iface, long warning, long limit);
+
+ /** Set upstream parameters to offload management process. */
+ boolean setUpstreamParameters(@NonNull String iface, @NonNull String v4addr,
+ @NonNull String v4gateway, @NonNull ArrayList<String> v6gws);
+
+ /** Add downstream prefix to offload management process. */
+ boolean addDownstream(@NonNull String ifname, @NonNull String prefix);
+
+ /** Remove downstream prefix from offload management process. */
+ boolean removeDownstream(@NonNull String ifname, @NonNull String prefix);
+}
diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadController.java b/Tethering/src/com/android/networkstack/tethering/OffloadController.java
index d2f177d..b4c0d6a 100644
--- a/Tethering/src/com/android/networkstack/tethering/OffloadController.java
+++ b/Tethering/src/com/android/networkstack/tethering/OffloadController.java
@@ -26,8 +26,8 @@
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_0;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_1;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_0;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_1;
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE;
import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
@@ -98,9 +98,8 @@
private final OffloadTetheringStatsProvider mStatsProvider;
private final SharedLog mLog;
private final HashMap<String, LinkProperties> mDownstreams;
- private boolean mConfigInitialized;
@OffloadHardwareInterface.OffloadHalVersion
- private int mControlHalVersion;
+ private int mOffloadHalVersion;
private LinkProperties mUpstreamLinkProperties;
// The complete set of offload-exempt prefixes passed in via Tethering from
// all upstream and downstream sources.
@@ -205,20 +204,11 @@
return false;
}
- if (!mConfigInitialized) {
- mConfigInitialized = mHwInterface.initOffloadConfig();
- if (!mConfigInitialized) {
- mLog.i("tethering offload config not supported");
- stop();
- return false;
- }
- }
-
- mControlHalVersion = mHwInterface.initOffloadControl(
+ mOffloadHalVersion = mHwInterface.initOffload(
// OffloadHardwareInterface guarantees that these callback
// methods are called on the handler passed to it, which is the
// same as mHandler, as coordinated by the setup in Tethering.
- new OffloadHardwareInterface.ControlCallback() {
+ new OffloadHardwareInterface.OffloadHalCallback() {
@Override
public void onStarted() {
if (!started()) return;
@@ -305,11 +295,11 @@
final boolean isStarted = started();
if (!isStarted) {
- mLog.i("tethering offload control not supported");
+ mLog.i("tethering offload not supported");
stop();
} else {
mLog.log("tethering offload started, version: "
- + OffloadHardwareInterface.halVerToString(mControlHalVersion));
+ + OffloadHardwareInterface.halVerToString(mOffloadHalVersion));
mNatUpdateCallbacksReceived = 0;
mNatUpdateNetlinkErrors = 0;
maybeSchedulePollingStats();
@@ -325,9 +315,8 @@
final boolean wasStarted = started();
updateStatsForCurrentUpstream();
mUpstreamLinkProperties = null;
- mHwInterface.stopOffloadControl();
- mControlHalVersion = OFFLOAD_HAL_VERSION_NONE;
- mConfigInitialized = false;
+ mHwInterface.stopOffload();
+ mOffloadHalVersion = OFFLOAD_HAL_VERSION_NONE;
if (mHandler.hasCallbacks(mScheduledPollingTask)) {
mHandler.removeCallbacks(mScheduledPollingTask);
}
@@ -335,7 +324,7 @@
}
private boolean started() {
- return mConfigInitialized && mControlHalVersion != OFFLOAD_HAL_VERSION_NONE;
+ return mOffloadHalVersion != OFFLOAD_HAL_VERSION_NONE;
}
@VisibleForTesting
@@ -528,7 +517,7 @@
}
private boolean useStatsPolling() {
- return mControlHalVersion == OFFLOAD_HAL_VERSION_1_0;
+ return mOffloadHalVersion == OFFLOAD_HAL_VERSION_HIDL_1_0;
}
private boolean maybeUpdateDataWarningAndLimit(String iface) {
@@ -540,7 +529,7 @@
final InterfaceQuota quota = mInterfaceQuotas.getOrDefault(iface, InterfaceQuota.MAX_VALUE);
final boolean ret;
- if (mControlHalVersion >= OFFLOAD_HAL_VERSION_1_1) {
+ if (mOffloadHalVersion >= OFFLOAD_HAL_VERSION_HIDL_1_1) {
ret = mHwInterface.setDataWarningAndLimit(iface, quota.warningBytes, quota.limitBytes);
} else {
ret = mHwInterface.setDataLimit(iface, quota.limitBytes);
@@ -611,7 +600,7 @@
for (RouteInfo ri : oldRoutes) {
if (shouldIgnoreDownstreamRoute(ri)) continue;
if (!newRoutes.contains(ri)) {
- mHwInterface.removeDownstreamPrefix(ifname, ri.getDestination().toString());
+ mHwInterface.removeDownstream(ifname, ri.getDestination().toString());
}
}
@@ -619,7 +608,7 @@
for (RouteInfo ri : newRoutes) {
if (shouldIgnoreDownstreamRoute(ri)) continue;
if (!oldRoutes.contains(ri)) {
- mHwInterface.addDownstreamPrefix(ifname, ri.getDestination().toString());
+ mHwInterface.addDownstream(ifname, ri.getDestination().toString());
}
}
}
@@ -639,7 +628,7 @@
for (RouteInfo route : lp.getRoutes()) {
if (shouldIgnoreDownstreamRoute(route)) continue;
- mHwInterface.removeDownstreamPrefix(ifname, route.getDestination().toString());
+ mHwInterface.removeDownstream(ifname, route.getDestination().toString());
}
}
@@ -768,11 +757,21 @@
final boolean isStarted = started();
pw.println("Offload HALs " + (isStarted ? "started" : "not started"));
pw.println("Offload Control HAL version: "
- + OffloadHardwareInterface.halVerToString(mControlHalVersion));
+ + OffloadHardwareInterface.halVerToString(mOffloadHalVersion));
LinkProperties lp = mUpstreamLinkProperties;
String upstream = (lp != null) ? lp.getInterfaceName() : null;
pw.println("Current upstream: " + upstream);
pw.println("Exempt prefixes: " + mLastLocalPrefixStrs);
+ pw.println("ForwardedStats:");
+ pw.increaseIndent();
+ if (mForwardedStats.isEmpty()) {
+ pw.println("<empty>");
+ } else {
+ for (final Map.Entry<String, ForwardedStats> kv : mForwardedStats.entrySet()) {
+ pw.println(kv.getKey() + ": " + kv.getValue());
+ }
+ }
+ pw.decreaseIndent();
pw.println("NAT timeout update callbacks received during the "
+ (isStarted ? "current" : "last")
+ " offload session: "
diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadHalAidlImpl.java b/Tethering/src/com/android/networkstack/tethering/OffloadHalAidlImpl.java
new file mode 100644
index 0000000..e7dc757
--- /dev/null
+++ b/Tethering/src/com/android/networkstack/tethering/OffloadHalAidlImpl.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2022 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.networkstack.tethering;
+
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_AIDL;
+
+import android.annotation.NonNull;
+import android.hardware.tetheroffload.ForwardedStats;
+import android.hardware.tetheroffload.IOffload;
+import android.hardware.tetheroffload.ITetheringOffloadCallback;
+import android.hardware.tetheroffload.NatTimeoutUpdate;
+import android.hardware.tetheroffload.NetworkProtocol;
+import android.hardware.tetheroffload.OffloadCallbackEvent;
+import android.os.Handler;
+import android.os.NativeHandle;
+import android.os.ParcelFileDescriptor;
+import android.os.ServiceManager;
+import android.system.OsConstants;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.net.module.util.SharedLog;
+import com.android.networkstack.tethering.OffloadHardwareInterface.OffloadHalCallback;
+
+import java.util.ArrayList;
+
+/**
+ * The implementation of IOffloadHal which based on Stable AIDL interface
+ */
+public class OffloadHalAidlImpl implements IOffloadHal {
+ private static final String TAG = OffloadHalAidlImpl.class.getSimpleName();
+ private static final String HAL_INSTANCE_NAME = IOffload.DESCRIPTOR + "/default";
+
+ private final Handler mHandler;
+ private final SharedLog mLog;
+ private final IOffload mIOffload;
+ @OffloadHardwareInterface.OffloadHalVersion
+ private final int mOffloadVersion;
+
+ private TetheringOffloadCallback mTetheringOffloadCallback;
+
+ public OffloadHalAidlImpl(int version, @NonNull IOffload offload, @NonNull Handler handler,
+ @NonNull SharedLog log) {
+ mOffloadVersion = version;
+ mIOffload = offload;
+ mHandler = handler;
+ mLog = log.forSubComponent(TAG);
+ }
+
+ /**
+ * Initialize the Tetheroffload HAL. Provides bound netlink file descriptors for use in the
+ * management process.
+ */
+ public boolean initOffload(@NonNull NativeHandle handle1, @NonNull NativeHandle handle2,
+ @NonNull OffloadHalCallback callback) {
+ final String methodStr = String.format("initOffload(%d, %d, %s)",
+ handle1.getFileDescriptor().getInt$(), handle2.getFileDescriptor().getInt$(),
+ (callback == null) ? "null"
+ : "0x" + Integer.toHexString(System.identityHashCode(callback)));
+ mTetheringOffloadCallback = new TetheringOffloadCallback(mHandler, callback, mLog);
+ try {
+ mIOffload.initOffload(
+ ParcelFileDescriptor.adoptFd(handle1.getFileDescriptor().getInt$()),
+ ParcelFileDescriptor.adoptFd(handle2.getFileDescriptor().getInt$()),
+ mTetheringOffloadCallback);
+ } catch (Exception e) {
+ logAndIgnoreException(e, methodStr);
+ return false;
+ }
+ mLog.i(methodStr);
+ return true;
+ }
+
+ /** Stop the Tetheroffload HAL. */
+ public boolean stopOffload() {
+ final String methodStr = "stopOffload()";
+ try {
+ mIOffload.stopOffload();
+ } catch (Exception e) {
+ logAndIgnoreException(e, methodStr);
+ return false;
+ }
+
+ mTetheringOffloadCallback = null;
+ mLog.i(methodStr);
+ return true;
+ }
+
+ /** Get HAL interface version number. */
+ public int getVersion() {
+ return mOffloadVersion;
+ }
+
+ /** Get Tx/Rx usage from last query. */
+ public OffloadHardwareInterface.ForwardedStats getForwardedStats(@NonNull String upstream) {
+ ForwardedStats stats = new ForwardedStats();
+ final String methodStr = String.format("getForwardedStats(%s)", upstream);
+ try {
+ stats = mIOffload.getForwardedStats(upstream);
+ } catch (Exception e) {
+ logAndIgnoreException(e, methodStr);
+ }
+ mLog.i(methodStr);
+ return new OffloadHardwareInterface.ForwardedStats(stats.rxBytes, stats.txBytes);
+ }
+
+ /** Set local prefixes to offload management process. */
+ public boolean setLocalPrefixes(@NonNull ArrayList<String> localPrefixes) {
+ final String methodStr = String.format("setLocalPrefixes([%s])",
+ String.join(",", localPrefixes));
+ try {
+ mIOffload.setLocalPrefixes(localPrefixes.toArray(new String[localPrefixes.size()]));
+ } catch (Exception e) {
+ logAndIgnoreException(e, methodStr);
+ return false;
+ }
+ mLog.i(methodStr);
+ return true;
+ }
+
+ /**
+ * Set data limit value to offload management process.
+ * Method setDataLimit is deprecated in AIDL, so call setDataWarningAndLimit instead,
+ * with warningBytes set to its MAX_VALUE.
+ */
+ public boolean setDataLimit(@NonNull String iface, long limit) {
+ final long warning = Long.MAX_VALUE;
+ final String methodStr = String.format("setDataLimit(%s, %d)", iface, limit);
+ try {
+ mIOffload.setDataWarningAndLimit(iface, warning, limit);
+ } catch (Exception e) {
+ logAndIgnoreException(e, methodStr);
+ return false;
+ }
+ mLog.i(methodStr);
+ return true;
+ }
+
+ /** Set data warning and limit value to offload management process. */
+ public boolean setDataWarningAndLimit(@NonNull String iface, long warning, long limit) {
+ final String methodStr =
+ String.format("setDataWarningAndLimit(%s, %d, %d)", iface, warning, limit);
+ try {
+ mIOffload.setDataWarningAndLimit(iface, warning, limit);
+ } catch (Exception e) {
+ logAndIgnoreException(e, methodStr);
+ return false;
+ }
+ mLog.i(methodStr);
+ return true;
+ }
+
+ /** Set upstream parameters to offload management process. */
+ public boolean setUpstreamParameters(@NonNull String iface, @NonNull String v4addr,
+ @NonNull String v4gateway, @NonNull ArrayList<String> v6gws) {
+ final String methodStr = String.format("setUpstreamParameters(%s, %s, %s, [%s])",
+ iface, v4addr, v4gateway, String.join(",", v6gws));
+ try {
+ mIOffload.setUpstreamParameters(iface, v4addr, v4gateway,
+ v6gws.toArray(new String[v6gws.size()]));
+ } catch (Exception e) {
+ logAndIgnoreException(e, methodStr);
+ return false;
+ }
+ mLog.i(methodStr);
+ return true;
+ }
+
+ /** Add downstream prefix to offload management process. */
+ public boolean addDownstream(@NonNull String ifname, @NonNull String prefix) {
+ final String methodStr = String.format("addDownstream(%s, %s)", ifname, prefix);
+ try {
+ mIOffload.addDownstream(ifname, prefix);
+ } catch (Exception e) {
+ logAndIgnoreException(e, methodStr);
+ return false;
+ }
+ mLog.i(methodStr);
+ return true;
+ }
+
+ /** Remove downstream prefix from offload management process. */
+ public boolean removeDownstream(@NonNull String ifname, @NonNull String prefix) {
+ final String methodStr = String.format("removeDownstream(%s, %s)", ifname, prefix);
+ try {
+ mIOffload.removeDownstream(ifname, prefix);
+ } catch (Exception e) {
+ logAndIgnoreException(e, methodStr);
+ return false;
+ }
+ mLog.i(methodStr);
+ return true;
+ }
+
+ /**
+ * Get {@link IOffloadHal} object from the AIDL service.
+ *
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ * @param log Log to be used by the repository.
+ */
+ public static IOffloadHal getIOffloadHal(Handler handler, SharedLog log) {
+ // Tetheroffload AIDL interface is only supported after U.
+ if (!SdkLevel.isAtLeastU() || !ServiceManager.isDeclared(HAL_INSTANCE_NAME)) return null;
+
+ IOffload offload = IOffload.Stub.asInterface(
+ ServiceManager.waitForDeclaredService(HAL_INSTANCE_NAME));
+ if (offload == null) return null;
+
+ return new OffloadHalAidlImpl(OFFLOAD_HAL_VERSION_AIDL, offload, handler, log);
+ }
+
+ private void logAndIgnoreException(Exception e, final String methodStr) {
+ mLog.e(methodStr + " failed with " + e.getClass().getSimpleName() + ": ", e);
+ }
+
+ private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
+ public final Handler handler;
+ public final OffloadHalCallback callback;
+ public final SharedLog log;
+
+ TetheringOffloadCallback(
+ Handler h, OffloadHalCallback cb, SharedLog sharedLog) {
+ handler = h;
+ callback = cb;
+ log = sharedLog;
+ }
+
+ private void handleOnEvent(int event) {
+ switch (event) {
+ case OffloadCallbackEvent.OFFLOAD_STARTED:
+ callback.onStarted();
+ break;
+ case OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR:
+ callback.onStoppedError();
+ break;
+ case OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED:
+ callback.onStoppedUnsupported();
+ break;
+ case OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE:
+ callback.onSupportAvailable();
+ break;
+ case OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED:
+ callback.onStoppedLimitReached();
+ break;
+ case OffloadCallbackEvent.OFFLOAD_WARNING_REACHED:
+ callback.onWarningReached();
+ break;
+ default:
+ log.e("Unsupported OffloadCallbackEvent: " + event);
+ }
+ }
+
+ @Override
+ public void onEvent(int event) {
+ handler.post(() -> {
+ handleOnEvent(event);
+ });
+ }
+
+ @Override
+ public void updateTimeout(NatTimeoutUpdate params) {
+ handler.post(() -> {
+ callback.onNatTimeoutUpdate(
+ networkProtocolToOsConstant(params.proto),
+ params.src.addr, params.src.port,
+ params.dst.addr, params.dst.port);
+ });
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return ITetheringOffloadCallback.HASH;
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return ITetheringOffloadCallback.VERSION;
+ }
+ }
+
+ private static int networkProtocolToOsConstant(int proto) {
+ switch (proto) {
+ case NetworkProtocol.TCP: return OsConstants.IPPROTO_TCP;
+ case NetworkProtocol.UDP: return OsConstants.IPPROTO_UDP;
+ default:
+ // The caller checks this value and will log an error. Just make
+ // sure it won't collide with valid OsConstants.IPPROTO_* values.
+ return -Math.abs(proto);
+ }
+ }
+}
diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadHalHidlImpl.java b/Tethering/src/com/android/networkstack/tethering/OffloadHalHidlImpl.java
new file mode 100644
index 0000000..e0a9878
--- /dev/null
+++ b/Tethering/src/com/android/networkstack/tethering/OffloadHalHidlImpl.java
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2022 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.networkstack.tethering;
+
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_0;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_1;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.halVerToString;
+import static com.android.networkstack.tethering.util.TetheringUtils.uint16;
+
+import android.annotation.NonNull;
+import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
+import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
+import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
+import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
+import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
+import android.hardware.tetheroffload.control.V1_1.ITetheringOffloadCallback;
+import android.os.Handler;
+import android.os.NativeHandle;
+import android.os.RemoteException;
+import android.system.OsConstants;
+import android.util.Log;
+
+import com.android.net.module.util.SharedLog;
+import com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats;
+import com.android.networkstack.tethering.OffloadHardwareInterface.OffloadHalCallback;
+
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+
+/**
+ * The implementation of IOffloadHal which based on HIDL interfaces
+ */
+public class OffloadHalHidlImpl implements IOffloadHal {
+ private static final String TAG = OffloadHalHidlImpl.class.getSimpleName();
+ private static final String YIELDS = " -> ";
+
+ private final Handler mHandler;
+ private final SharedLog mLog;
+ private final IOffloadConfig mIOffloadConfig;
+ private final IOffloadControl mIOffloadControl;
+ @OffloadHardwareInterface.OffloadHalVersion
+ private final int mOffloadControlVersion;
+
+ private OffloadHalCallback mOffloadHalCallback;
+ private TetheringOffloadCallback mTetheringOffloadCallback;
+
+ public OffloadHalHidlImpl(int version, @NonNull IOffloadConfig config,
+ @NonNull IOffloadControl control, @NonNull Handler handler, @NonNull SharedLog log) {
+ mOffloadControlVersion = version;
+ mIOffloadConfig = config;
+ mIOffloadControl = control;
+ mHandler = handler;
+ mLog = log.forSubComponent(TAG);
+ }
+
+ /**
+ * Initialize the Tetheroffload HAL. Provides bound netlink file descriptors for use in the
+ * management process.
+ */
+ public boolean initOffload(@NonNull NativeHandle handle1, @NonNull NativeHandle handle2,
+ @NonNull OffloadHalCallback callback) {
+ final String logmsg = String.format("initOffload(%d, %d, %s)",
+ handle1.getFileDescriptor().getInt$(), handle2.getFileDescriptor().getInt$(),
+ (callback == null) ? "null"
+ : "0x" + Integer.toHexString(System.identityHashCode(callback)));
+
+ mOffloadHalCallback = callback;
+ mTetheringOffloadCallback = new TetheringOffloadCallback(
+ mHandler, mOffloadHalCallback, mLog, mOffloadControlVersion);
+ final CbResults results = new CbResults();
+ try {
+ mIOffloadConfig.setHandles(handle1, handle2,
+ (boolean success, String errMsg) -> {
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
+ });
+ mIOffloadControl.initOffload(
+ mTetheringOffloadCallback,
+ (boolean success, String errMsg) -> {
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
+ });
+ } catch (RemoteException e) {
+ record(logmsg, e);
+ return false;
+ }
+
+ record(logmsg, results);
+ return results.mSuccess;
+ }
+
+ /** Stop the Tetheroffload HAL. */
+ public boolean stopOffload() {
+ try {
+ mIOffloadControl.stopOffload(
+ (boolean success, String errMsg) -> {
+ if (!success) mLog.e("stopOffload failed: " + errMsg);
+ });
+ } catch (RemoteException e) {
+ mLog.e("failed to stopOffload: " + e);
+ }
+ mOffloadHalCallback = null;
+ mTetheringOffloadCallback = null;
+ mLog.log("stopOffload()");
+ return true;
+ }
+
+ /** Get HAL interface version number. */
+ public int getVersion() {
+ return mOffloadControlVersion;
+ }
+
+ /** Get Tx/Rx usage from last query. */
+ public ForwardedStats getForwardedStats(@NonNull String upstream) {
+ final String logmsg = String.format("getForwardedStats(%s)", upstream);
+
+ final ForwardedStats stats = new ForwardedStats();
+ try {
+ mIOffloadControl.getForwardedStats(
+ upstream,
+ (long rxBytes, long txBytes) -> {
+ stats.rxBytes = (rxBytes > 0) ? rxBytes : 0;
+ stats.txBytes = (txBytes > 0) ? txBytes : 0;
+ });
+ } catch (RemoteException e) {
+ record(logmsg, e);
+ return stats;
+ }
+
+ return stats;
+ }
+
+ /** Set local prefixes to offload management process. */
+ public boolean setLocalPrefixes(@NonNull ArrayList<String> localPrefixes) {
+ final String logmsg = String.format("setLocalPrefixes([%s])",
+ String.join(",", localPrefixes));
+
+ final CbResults results = new CbResults();
+ try {
+ mIOffloadControl.setLocalPrefixes(localPrefixes,
+ (boolean success, String errMsg) -> {
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
+ });
+ } catch (RemoteException e) {
+ record(logmsg, e);
+ return false;
+ }
+
+ record(logmsg, results);
+ return results.mSuccess;
+ }
+
+ /** Set data limit value to offload management process. */
+ public boolean setDataLimit(@NonNull String iface, long limit) {
+
+ final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit);
+
+ final CbResults results = new CbResults();
+ try {
+ mIOffloadControl.setDataLimit(
+ iface, limit,
+ (boolean success, String errMsg) -> {
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
+ });
+ } catch (RemoteException e) {
+ record(logmsg, e);
+ return false;
+ }
+
+ record(logmsg, results);
+ return results.mSuccess;
+ }
+
+ /** Set data warning and limit value to offload management process. */
+ public boolean setDataWarningAndLimit(@NonNull String iface, long warning, long limit) {
+ if (mOffloadControlVersion < OFFLOAD_HAL_VERSION_HIDL_1_1) {
+ throw new UnsupportedOperationException(
+ "setDataWarningAndLimit is not supported below HAL V1.1");
+ }
+ final String logmsg =
+ String.format("setDataWarningAndLimit(%s, %d, %d)", iface, warning, limit);
+
+ final CbResults results = new CbResults();
+ try {
+ ((android.hardware.tetheroffload.control.V1_1.IOffloadControl) mIOffloadControl)
+ .setDataWarningAndLimit(
+ iface, warning, limit,
+ (boolean success, String errMsg) -> {
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
+ });
+ } catch (RemoteException e) {
+ record(logmsg, e);
+ return false;
+ }
+
+ record(logmsg, results);
+ return results.mSuccess;
+ }
+
+ /** Set upstream parameters to offload management process. */
+ public boolean setUpstreamParameters(@NonNull String iface, @NonNull String v4addr,
+ @NonNull String v4gateway, @NonNull ArrayList<String> v6gws) {
+ final String logmsg = String.format("setUpstreamParameters(%s, %s, %s, [%s])",
+ iface, v4addr, v4gateway, String.join(",", v6gws));
+
+ final CbResults results = new CbResults();
+ try {
+ mIOffloadControl.setUpstreamParameters(
+ iface, v4addr, v4gateway, v6gws,
+ (boolean success, String errMsg) -> {
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
+ });
+ } catch (RemoteException e) {
+ record(logmsg, e);
+ return false;
+ }
+
+ record(logmsg, results);
+ return results.mSuccess;
+ }
+
+ /** Add downstream prefix to offload management process. */
+ public boolean addDownstream(@NonNull String ifname, @NonNull String prefix) {
+ final String logmsg = String.format("addDownstream(%s, %s)", ifname, prefix);
+
+ final CbResults results = new CbResults();
+ try {
+ mIOffloadControl.addDownstream(ifname, prefix,
+ (boolean success, String errMsg) -> {
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
+ });
+ } catch (RemoteException e) {
+ record(logmsg, e);
+ return false;
+ }
+
+ record(logmsg, results);
+ return results.mSuccess;
+ }
+
+ /** Remove downstream prefix from offload management process. */
+ public boolean removeDownstream(@NonNull String ifname, @NonNull String prefix) {
+ final String logmsg = String.format("removeDownstream(%s, %s)", ifname, prefix);
+
+ final CbResults results = new CbResults();
+ try {
+ mIOffloadControl.removeDownstream(ifname, prefix,
+ (boolean success, String errMsg) -> {
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
+ });
+ } catch (RemoteException e) {
+ record(logmsg, e);
+ return false;
+ }
+
+ record(logmsg, results);
+ return results.mSuccess;
+ }
+
+ /**
+ * Get {@link IOffloadHal} object from the HIDL service.
+ *
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ * @param log Log to be used by the repository.
+ */
+ public static IOffloadHal getIOffloadHal(Handler handler, SharedLog log) {
+ IOffloadConfig config = null;
+ try {
+ config = IOffloadConfig.getService(true /*retry*/);
+ } catch (RemoteException e) {
+ log.e("getIOffloadConfig error " + e);
+ return null;
+ } catch (NoSuchElementException e) {
+ log.i("getIOffloadConfig Tether Offload HAL not present/implemented");
+ return null;
+ }
+
+ IOffloadControl control = null;
+ int version = OFFLOAD_HAL_VERSION_NONE;
+ try {
+ control = android.hardware.tetheroffload.control
+ .V1_1.IOffloadControl.getService(true /*retry*/);
+ version = OFFLOAD_HAL_VERSION_HIDL_1_1;
+ } catch (NoSuchElementException e) {
+ // Unsupported by device.
+ } catch (RemoteException e) {
+ log.e("Unable to get offload control " + OFFLOAD_HAL_VERSION_HIDL_1_1);
+ }
+ if (control == null) {
+ try {
+ control = IOffloadControl.getService(true /*retry*/);
+ version = OFFLOAD_HAL_VERSION_HIDL_1_0;
+ } catch (NoSuchElementException e) {
+ // Unsupported by device.
+ } catch (RemoteException e) {
+ log.e("Unable to get offload control " + OFFLOAD_HAL_VERSION_HIDL_1_0);
+ }
+ }
+
+ if (config == null || control == null) return null;
+
+ return new OffloadHalHidlImpl(version, config, control, handler, log);
+ }
+
+ private void record(String msg, Throwable t) {
+ mLog.e(msg + YIELDS + "exception: " + t);
+ }
+
+ private void record(String msg, CbResults results) {
+ final String logmsg = msg + YIELDS + results;
+ if (!results.mSuccess) {
+ mLog.e(logmsg);
+ } else {
+ mLog.log(logmsg);
+ }
+ }
+
+ private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
+ public final Handler handler;
+ public final OffloadHalCallback callback;
+ public final SharedLog log;
+ private final int mOffloadControlVersion;
+
+ TetheringOffloadCallback(
+ Handler h, OffloadHalCallback cb, SharedLog sharedLog, int offloadControlVersion) {
+ handler = h;
+ callback = cb;
+ log = sharedLog;
+ this.mOffloadControlVersion = offloadControlVersion;
+ }
+
+ private void handleOnEvent(int event) {
+ switch (event) {
+ case OffloadCallbackEvent.OFFLOAD_STARTED:
+ callback.onStarted();
+ break;
+ case OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR:
+ callback.onStoppedError();
+ break;
+ case OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED:
+ callback.onStoppedUnsupported();
+ break;
+ case OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE:
+ callback.onSupportAvailable();
+ break;
+ case OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED:
+ callback.onStoppedLimitReached();
+ break;
+ case android.hardware.tetheroffload.control
+ .V1_1.OffloadCallbackEvent.OFFLOAD_WARNING_REACHED:
+ callback.onWarningReached();
+ break;
+ default:
+ log.e("Unsupported OffloadCallbackEvent: " + event);
+ }
+ }
+
+ @Override
+ public void onEvent(int event) {
+ // The implementation should never call onEvent()) if the event is already reported
+ // through newer callback.
+ if (mOffloadControlVersion > OFFLOAD_HAL_VERSION_HIDL_1_0) {
+ Log.wtf(TAG, "onEvent(" + event + ") fired on HAL "
+ + halVerToString(mOffloadControlVersion));
+ }
+ handler.post(() -> {
+ handleOnEvent(event);
+ });
+ }
+
+ @Override
+ public void onEvent_1_1(int event) {
+ if (mOffloadControlVersion < OFFLOAD_HAL_VERSION_HIDL_1_1) {
+ Log.wtf(TAG, "onEvent_1_1(" + event + ") fired on HAL "
+ + halVerToString(mOffloadControlVersion));
+ return;
+ }
+ handler.post(() -> {
+ handleOnEvent(event);
+ });
+ }
+
+ @Override
+ public void updateTimeout(NatTimeoutUpdate params) {
+ handler.post(() -> {
+ callback.onNatTimeoutUpdate(
+ networkProtocolToOsConstant(params.proto),
+ params.src.addr, uint16(params.src.port),
+ params.dst.addr, uint16(params.dst.port));
+ });
+ }
+ }
+
+ private static int networkProtocolToOsConstant(int proto) {
+ switch (proto) {
+ case NetworkProtocol.TCP: return OsConstants.IPPROTO_TCP;
+ case NetworkProtocol.UDP: return OsConstants.IPPROTO_UDP;
+ default:
+ // The caller checks this value and will log an error. Just make
+ // sure it won't collide with valid OsConstants.IPPROTO_* values.
+ return -Math.abs(proto);
+ }
+ }
+
+ private static class CbResults {
+ boolean mSuccess;
+ String mErrMsg;
+
+ @Override
+ public String toString() {
+ if (mSuccess) {
+ return "ok";
+ } else {
+ return "fail: " + mErrMsg;
+ }
+ }
+ }
+}
diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
index 76ddfe5..de15c5b 100644
--- a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
+++ b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
@@ -18,25 +18,15 @@
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static com.android.networkstack.tethering.util.TetheringUtils.uint16;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
-import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
-import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
-import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
-import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
-import android.hardware.tetheroffload.control.V1_1.ITetheringOffloadCallback;
import android.net.util.SocketUtils;
import android.os.Handler;
import android.os.NativeHandle;
-import android.os.RemoteException;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
-import android.util.Log;
-import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.SharedLog;
@@ -54,8 +44,6 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
-import java.util.NoSuchElementException;
-
/**
* Capture tethering dependencies, for injection.
@@ -86,43 +74,43 @@
private final Handler mHandler;
private final SharedLog mLog;
private final Dependencies mDeps;
- private IOffloadControl mOffloadControl;
+ private IOffloadHal mIOffload;
// TODO: Use major-minor version control to prevent from defining new constants.
static final int OFFLOAD_HAL_VERSION_NONE = 0;
- static final int OFFLOAD_HAL_VERSION_1_0 = 1;
- static final int OFFLOAD_HAL_VERSION_1_1 = 2;
+ static final int OFFLOAD_HAL_VERSION_HIDL_1_0 = 1;
+ static final int OFFLOAD_HAL_VERSION_HIDL_1_1 = 2;
+ static final int OFFLOAD_HAL_VERSION_AIDL = 3;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "OFFLOAD_HAL_VERSION_", value = {
OFFLOAD_HAL_VERSION_NONE,
- OFFLOAD_HAL_VERSION_1_0,
- OFFLOAD_HAL_VERSION_1_1
+ OFFLOAD_HAL_VERSION_HIDL_1_0,
+ OFFLOAD_HAL_VERSION_HIDL_1_1,
+ OFFLOAD_HAL_VERSION_AIDL,
})
public @interface OffloadHalVersion {}
- @OffloadHalVersion
- private int mOffloadControlVersion = OFFLOAD_HAL_VERSION_NONE;
@NonNull
static String halVerToString(int version) {
switch(version) {
- case OFFLOAD_HAL_VERSION_1_0:
- return "1.0";
- case OFFLOAD_HAL_VERSION_1_1:
- return "1.1";
+ case OFFLOAD_HAL_VERSION_HIDL_1_0:
+ return "HIDL 1.0";
+ case OFFLOAD_HAL_VERSION_HIDL_1_1:
+ return "HIDL 1.1";
+ case OFFLOAD_HAL_VERSION_AIDL:
+ return "AIDL";
case OFFLOAD_HAL_VERSION_NONE:
return "None";
default:
throw new IllegalArgumentException("Unsupported version int " + version);
}
-
}
- private TetheringOffloadCallback mTetheringOffloadCallback;
- private ControlCallback mControlCallback;
+ private OffloadHalCallback mOffloadHalCallback;
/** The callback to notify status of offload management process. */
- public static class ControlCallback {
+ public static class OffloadHalCallback {
/** Offload started. */
public void onStarted() {}
/**
@@ -179,7 +167,7 @@
}
public OffloadHardwareInterface(Handler h, SharedLog log) {
- this(h, log, new Dependencies(log));
+ this(h, log, new Dependencies(h, log));
}
OffloadHardwareInterface(Handler h, SharedLog log, Dependencies deps) {
@@ -190,45 +178,21 @@
/** Capture OffloadHardwareInterface dependencies, for injection. */
static class Dependencies {
+ private final Handler mHandler;
private final SharedLog mLog;
- Dependencies(SharedLog log) {
+ Dependencies(Handler handler, SharedLog log) {
+ mHandler = handler;
mLog = log;
}
- public IOffloadConfig getOffloadConfig() {
- try {
- return IOffloadConfig.getService(true /*retry*/);
- } catch (RemoteException | NoSuchElementException e) {
- mLog.e("getIOffloadConfig error " + e);
- return null;
- }
- }
-
- @NonNull
- public Pair<IOffloadControl, Integer> getOffloadControl() {
- IOffloadControl hal = null;
- int version = OFFLOAD_HAL_VERSION_NONE;
- try {
- hal = android.hardware.tetheroffload.control
- .V1_1.IOffloadControl.getService(true /*retry*/);
- version = OFFLOAD_HAL_VERSION_1_1;
- } catch (NoSuchElementException e) {
- // Unsupported by device.
- } catch (RemoteException e) {
- mLog.e("Unable to get offload control " + OFFLOAD_HAL_VERSION_1_1);
- }
+ public IOffloadHal getOffload() {
+ // Prefer AIDL implementation if its service is declared.
+ IOffloadHal hal = OffloadHalAidlImpl.getIOffloadHal(mHandler, mLog);
if (hal == null) {
- try {
- hal = IOffloadControl.getService(true /*retry*/);
- version = OFFLOAD_HAL_VERSION_1_0;
- } catch (NoSuchElementException e) {
- // Unsupported by device.
- } catch (RemoteException e) {
- mLog.e("Unable to get offload control " + OFFLOAD_HAL_VERSION_1_0);
- }
+ hal = OffloadHalHidlImpl.getIOffloadHal(mHandler, mLog);
}
- return new Pair<IOffloadControl, Integer>(hal, version);
+ return hal;
}
public NativeHandle createConntrackSocket(final int groups) {
@@ -273,56 +237,6 @@
return DEFAULT_TETHER_OFFLOAD_DISABLED;
}
- /**
- * Offload management process need to know conntrack rules to support NAT, but it may not have
- * permission to create netlink netfilter sockets. Create two netlink netfilter sockets and
- * share them with offload management process.
- */
- public boolean initOffloadConfig() {
- final IOffloadConfig offloadConfig = mDeps.getOffloadConfig();
- if (offloadConfig == null) {
- mLog.e("Could not find IOffloadConfig service");
- return false;
- }
- // Per the IConfigOffload definition:
- //
- // h1 provides a file descriptor bound to the following netlink groups
- // (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
- //
- // h2 provides a file descriptor bound to the following netlink groups
- // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
- final NativeHandle h1 = mDeps.createConntrackSocket(
- NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
- if (h1 == null) return false;
-
- requestSocketDump(h1);
-
- final NativeHandle h2 = mDeps.createConntrackSocket(
- NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
- if (h2 == null) {
- closeFdInNativeHandle(h1);
- return false;
- }
-
- final CbResults results = new CbResults();
- try {
- offloadConfig.setHandles(h1, h2,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record("initOffloadConfig, setHandles fail", e);
- return false;
- }
- // Explicitly close FDs.
- closeFdInNativeHandle(h1);
- closeFdInNativeHandle(h2);
-
- record("initOffloadConfig, setHandles results:", results);
- return results.mSuccess;
- }
-
@VisibleForTesting
void sendIpv4NfGenMsg(@NonNull NativeHandle handle, short type, short flags) {
final int length = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
@@ -355,165 +269,107 @@
(short) (NLM_F_REQUEST | NLM_F_DUMP));
}
- private void closeFdInNativeHandle(final NativeHandle h) {
- try {
- h.close();
- } catch (IOException | IllegalStateException e) {
- // IllegalStateException means fd is already closed, do nothing here.
- // Also nothing we can do if IOException.
+ private void maybeCloseFdInNativeHandles(final NativeHandle... handles) {
+ for (NativeHandle h : handles) {
+ if (h == null) continue;
+ try {
+ h.close();
+ } catch (IOException | IllegalStateException e) {
+ // IllegalStateException means fd is already closed, do nothing here.
+ // Also nothing we can do if IOException.
+ }
}
}
+ private int initWithHandles(NativeHandle h1, NativeHandle h2) {
+ if (h1 == null || h2 == null) {
+ mLog.e("Failed to create socket.");
+ return OFFLOAD_HAL_VERSION_NONE;
+ }
+
+ requestSocketDump(h1);
+ if (!mIOffload.initOffload(h1, h2, mOffloadHalCallback)) {
+ mIOffload.stopOffload();
+ mLog.e("Failed to initialize offload.");
+ return OFFLOAD_HAL_VERSION_NONE;
+ }
+
+ return mIOffload.getVersion();
+ }
+
/**
* Initialize the tethering offload HAL.
*
* @return one of {@code OFFLOAD_HAL_VERSION_*} represents the HAL version, or
* {@link #OFFLOAD_HAL_VERSION_NONE} if failed.
*/
- public int initOffloadControl(ControlCallback controlCb) {
- mControlCallback = controlCb;
-
- if (mOffloadControl == null) {
- final Pair<IOffloadControl, Integer> halAndVersion = mDeps.getOffloadControl();
- mOffloadControl = halAndVersion.first;
- mOffloadControlVersion = halAndVersion.second;
- if (mOffloadControl == null) {
- mLog.e("tethering IOffloadControl.getService() returned null");
+ public int initOffload(OffloadHalCallback offloadCb) {
+ if (mIOffload == null) {
+ mIOffload = mDeps.getOffload();
+ if (mIOffload == null) {
+ mLog.i("No tethering offload HAL service found.");
return OFFLOAD_HAL_VERSION_NONE;
}
- mLog.i("tethering offload control version "
- + halVerToString(mOffloadControlVersion) + " is supported.");
+ mLog.i("Tethering offload version "
+ + halVerToString(mIOffload.getVersion()) + " is supported.");
}
- final String logmsg = String.format("initOffloadControl(%s)",
- (controlCb == null) ? "null"
- : "0x" + Integer.toHexString(System.identityHashCode(controlCb)));
+ // Per the IOffload definition:
+ //
+ // h1 provides a file descriptor bound to the following netlink groups
+ // (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
+ //
+ // h2 provides a file descriptor bound to the following netlink groups
+ // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
+ final NativeHandle h1 = mDeps.createConntrackSocket(
+ NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY);
+ final NativeHandle h2 = mDeps.createConntrackSocket(
+ NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
- mTetheringOffloadCallback = new TetheringOffloadCallback(
- mHandler, mControlCallback, mLog, mOffloadControlVersion);
- final CbResults results = new CbResults();
- try {
- mOffloadControl.initOffload(
- mTetheringOffloadCallback,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return OFFLOAD_HAL_VERSION_NONE;
+ mOffloadHalCallback = offloadCb;
+ final int version = initWithHandles(h1, h2);
+
+ // Explicitly close FDs for HIDL. AIDL will pass the original FDs to the service,
+ // they shouldn't be closed here.
+ if (version < OFFLOAD_HAL_VERSION_AIDL) {
+ maybeCloseFdInNativeHandles(h1, h2);
}
-
- record(logmsg, results);
- return results.mSuccess ? mOffloadControlVersion : OFFLOAD_HAL_VERSION_NONE;
+ return version;
}
- /** Stop IOffloadControl. */
- public void stopOffloadControl() {
- if (mOffloadControl != null) {
- try {
- mOffloadControl.stopOffload(
- (boolean success, String errMsg) -> {
- if (!success) mLog.e("stopOffload failed: " + errMsg);
- });
- } catch (RemoteException e) {
- mLog.e("failed to stopOffload: " + e);
+ /** Stop the tethering offload HAL. */
+ public void stopOffload() {
+ if (mIOffload != null) {
+ if (!mIOffload.stopOffload()) {
+ mLog.e("Failed to stop offload.");
}
}
- mOffloadControl = null;
- mTetheringOffloadCallback = null;
- mControlCallback = null;
- mLog.log("stopOffloadControl()");
+ mIOffload = null;
+ mOffloadHalCallback = null;
}
/** Get Tx/Rx usage from last query. */
public ForwardedStats getForwardedStats(String upstream) {
- final String logmsg = String.format("getForwardedStats(%s)", upstream);
-
- final ForwardedStats stats = new ForwardedStats();
- try {
- mOffloadControl.getForwardedStats(
- upstream,
- (long rxBytes, long txBytes) -> {
- stats.rxBytes = (rxBytes > 0) ? rxBytes : 0;
- stats.txBytes = (txBytes > 0) ? txBytes : 0;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return stats;
- }
-
- return stats;
+ return mIOffload.getForwardedStats(upstream);
}
/** Set local prefixes to offload management process. */
public boolean setLocalPrefixes(ArrayList<String> localPrefixes) {
- final String logmsg = String.format("setLocalPrefixes([%s])",
- String.join(",", localPrefixes));
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.setLocalPrefixes(localPrefixes,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
+ return mIOffload.setLocalPrefixes(localPrefixes);
}
/** Set data limit value to offload management process. */
public boolean setDataLimit(String iface, long limit) {
-
- final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit);
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.setDataLimit(
- iface, limit,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
+ return mIOffload.setDataLimit(iface, limit);
}
/** Set data warning and limit value to offload management process. */
public boolean setDataWarningAndLimit(String iface, long warning, long limit) {
- if (mOffloadControlVersion < OFFLOAD_HAL_VERSION_1_1) {
- throw new IllegalArgumentException(
+ if (mIOffload.getVersion() < OFFLOAD_HAL_VERSION_HIDL_1_1) {
+ throw new UnsupportedOperationException(
"setDataWarningAndLimit is not supported below HAL V1.1");
}
- final String logmsg =
- String.format("setDataWarningAndLimit(%s, %d, %d)", iface, warning, limit);
-
- final CbResults results = new CbResults();
- try {
- ((android.hardware.tetheroffload.control.V1_1.IOffloadControl) mOffloadControl)
- .setDataWarningAndLimit(
- iface, warning, limit,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
+ return mIOffload.setDataWarningAndLimit(iface, warning, limit);
}
/** Set upstream parameters to offload management process. */
@@ -523,178 +379,16 @@
v4addr = (v4addr != null) ? v4addr : NO_IPV4_ADDRESS;
v4gateway = (v4gateway != null) ? v4gateway : NO_IPV4_GATEWAY;
v6gws = (v6gws != null) ? v6gws : new ArrayList<>();
-
- final String logmsg = String.format("setUpstreamParameters(%s, %s, %s, [%s])",
- iface, v4addr, v4gateway, String.join(",", v6gws));
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.setUpstreamParameters(
- iface, v4addr, v4gateway, v6gws,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
+ return mIOffload.setUpstreamParameters(iface, v4addr, v4gateway, v6gws);
}
/** Add downstream prefix to offload management process. */
- public boolean addDownstreamPrefix(String ifname, String prefix) {
- final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix);
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.addDownstream(ifname, prefix,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
+ public boolean addDownstream(String ifname, String prefix) {
+ return mIOffload.addDownstream(ifname, prefix);
}
/** Remove downstream prefix from offload management process. */
- public boolean removeDownstreamPrefix(String ifname, String prefix) {
- final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix);
-
- final CbResults results = new CbResults();
- try {
- mOffloadControl.removeDownstream(ifname, prefix,
- (boolean success, String errMsg) -> {
- results.mSuccess = success;
- results.mErrMsg = errMsg;
- });
- } catch (RemoteException e) {
- record(logmsg, e);
- return false;
- }
-
- record(logmsg, results);
- return results.mSuccess;
- }
-
- private void record(String msg, Throwable t) {
- mLog.e(msg + YIELDS + "exception: " + t);
- }
-
- private void record(String msg, CbResults results) {
- final String logmsg = msg + YIELDS + results;
- if (!results.mSuccess) {
- mLog.e(logmsg);
- } else {
- mLog.log(logmsg);
- }
- }
-
- private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
- public final Handler handler;
- public final ControlCallback controlCb;
- public final SharedLog log;
- private final int mOffloadControlVersion;
-
- TetheringOffloadCallback(
- Handler h, ControlCallback cb, SharedLog sharedLog, int offloadControlVersion) {
- handler = h;
- controlCb = cb;
- log = sharedLog;
- this.mOffloadControlVersion = offloadControlVersion;
- }
-
- private void handleOnEvent(int event) {
- switch (event) {
- case OffloadCallbackEvent.OFFLOAD_STARTED:
- controlCb.onStarted();
- break;
- case OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR:
- controlCb.onStoppedError();
- break;
- case OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED:
- controlCb.onStoppedUnsupported();
- break;
- case OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE:
- controlCb.onSupportAvailable();
- break;
- case OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED:
- controlCb.onStoppedLimitReached();
- break;
- case android.hardware.tetheroffload.control
- .V1_1.OffloadCallbackEvent.OFFLOAD_WARNING_REACHED:
- controlCb.onWarningReached();
- break;
- default:
- log.e("Unsupported OffloadCallbackEvent: " + event);
- }
- }
-
- @Override
- public void onEvent(int event) {
- // The implementation should never call onEvent()) if the event is already reported
- // through newer callback.
- if (mOffloadControlVersion > OFFLOAD_HAL_VERSION_1_0) {
- Log.wtf(TAG, "onEvent(" + event + ") fired on HAL "
- + halVerToString(mOffloadControlVersion));
- }
- handler.post(() -> {
- handleOnEvent(event);
- });
- }
-
- @Override
- public void onEvent_1_1(int event) {
- if (mOffloadControlVersion < OFFLOAD_HAL_VERSION_1_1) {
- Log.wtf(TAG, "onEvent_1_1(" + event + ") fired on HAL "
- + halVerToString(mOffloadControlVersion));
- return;
- }
- handler.post(() -> {
- handleOnEvent(event);
- });
- }
-
- @Override
- public void updateTimeout(NatTimeoutUpdate params) {
- handler.post(() -> {
- controlCb.onNatTimeoutUpdate(
- networkProtocolToOsConstant(params.proto),
- params.src.addr, uint16(params.src.port),
- params.dst.addr, uint16(params.dst.port));
- });
- }
- }
-
- private static int networkProtocolToOsConstant(int proto) {
- switch (proto) {
- case NetworkProtocol.TCP: return OsConstants.IPPROTO_TCP;
- case NetworkProtocol.UDP: return OsConstants.IPPROTO_UDP;
- default:
- // The caller checks this value and will log an error. Just make
- // sure it won't collide with valid OsContants.IPPROTO_* values.
- return -Math.abs(proto);
- }
- }
-
- private static class CbResults {
- boolean mSuccess;
- String mErrMsg;
-
- @Override
- public String toString() {
- if (mSuccess) {
- return "ok";
- } else {
- return "fail: " + mErrMsg;
- }
- }
+ public boolean removeDownstream(String ifname, String prefix) {
+ return mIOffload.removeDownstream(ifname, prefix);
}
}
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index e48019c..4c5bf4e 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -88,7 +88,6 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.TetherStatesParcel;
import android.net.TetheredClient;
@@ -1856,9 +1855,13 @@
final Network newUpstream = (ns != null) ? ns.network : null;
if (mTetherUpstream != newUpstream) {
mTetherUpstream = newUpstream;
- mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream);
- reportUpstreamChanged(ns);
+ reportUpstreamChanged(mTetherUpstream);
+ // Need to notify capabilities change after upstream network changed because new
+ // network's capabilities should be checked every time.
+ mNotificationUpdater.onUpstreamCapabilitiesChanged(
+ (ns != null) ? ns.networkCapabilities : null);
}
+ mTetheringMetrics.maybeUpdateUpstreamType(ns);
}
protected void setUpstreamNetwork(UpstreamNetworkState ns) {
@@ -2085,8 +2088,10 @@
if (mTetherUpstream != null) {
mTetherUpstream = null;
reportUpstreamChanged(null);
+ mNotificationUpdater.onUpstreamCapabilitiesChanged(null);
}
mBpfCoordinator.stopPolling();
+ mTetheringMetrics.cleanup();
}
private boolean updateUpstreamWanted() {
@@ -2439,10 +2444,8 @@
}
}
- private void reportUpstreamChanged(UpstreamNetworkState ns) {
+ private void reportUpstreamChanged(final Network network) {
final int length = mTetheringEventCallbacks.beginBroadcast();
- final Network network = (ns != null) ? ns.network : null;
- final NetworkCapabilities capabilities = (ns != null) ? ns.networkCapabilities : null;
try {
for (int i = 0; i < length; i++) {
try {
@@ -2454,9 +2457,6 @@
} finally {
mTetheringEventCallbacks.finishBroadcast();
}
- // Need to notify capabilities change after upstream network changed because new network's
- // capabilities should be checked every time.
- mNotificationUpdater.onUpstreamCapabilitiesChanged(capabilities);
}
private void reportConfigurationChanged(TetheringConfigurationParcel config) {
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index 16c031b..ac2aa7b 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -133,8 +133,6 @@
private boolean mIsDefaultCellularUpstream;
// The current system default network (not really used yet).
private Network mDefaultInternetNetwork;
- // The current upstream network used for tethering.
- private Network mTetheringUpstreamNetwork;
private boolean mPreferTestNetworks;
public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) {
@@ -191,7 +189,6 @@
releaseCallback(mListenAllCallback);
mListenAllCallback = null;
- mTetheringUpstreamNetwork = null;
mNetworkMap.clear();
}
@@ -342,11 +339,6 @@
return findFirstDunNetwork(mNetworkMap.values());
}
- /** Tell UpstreamNetworkMonitor which network is the current upstream of tethering. */
- public void setCurrentUpstream(Network upstream) {
- mTetheringUpstreamNetwork = upstream;
- }
-
/** Return local prefixes. */
public Set<IpPrefix> getLocalPrefixes() {
return (Set<IpPrefix>) mLocalPrefixes.clone();
diff --git a/Tethering/src/com/android/networkstack/tethering/metrics/TetheringMetrics.java b/Tethering/src/com/android/networkstack/tethering/metrics/TetheringMetrics.java
index ffcea4e..de25ff5 100644
--- a/Tethering/src/com/android/networkstack/tethering/metrics/TetheringMetrics.java
+++ b/Tethering/src/com/android/networkstack/tethering/metrics/TetheringMetrics.java
@@ -16,6 +16,12 @@
package com.android.networkstack.tethering.metrics;
+import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_LOWPAN;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_ETHERNET;
import static android.net.TetheringManager.TETHERING_NCM;
@@ -39,6 +45,8 @@
import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
import static android.net.TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
+import android.annotation.Nullable;
+import android.net.NetworkCapabilities;
import android.stats.connectivity.DownstreamType;
import android.stats.connectivity.ErrorCode;
import android.stats.connectivity.UpstreamType;
@@ -49,6 +57,11 @@
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import com.android.networkstack.tethering.UpstreamNetworkState;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
/**
* Collection of utilities for tethering metrics.
*
@@ -66,21 +79,58 @@
private static final String SYSTEMUI_PKG_NAME = "com.android.systemui";
private static final String GMS_PKG_NAME = "com.google.android.gms";
private final SparseArray<NetworkTetheringReported.Builder> mBuilderMap = new SparseArray<>();
+ private final SparseArray<Long> mDownstreamStartTime = new SparseArray<Long>();
+ private final ArrayList<RecordUpstreamEvent> mUpstreamEventList = new ArrayList<>();
+ private UpstreamType mCurrentUpstream = null;
+ private Long mCurrentUpStreamStartTime = 0L;
- /** Update Tethering stats about caller's package name and downstream type. */
- public void createBuilder(final int downstreamType, final String callerPkg) {
- NetworkTetheringReported.Builder statsBuilder =
- NetworkTetheringReported.newBuilder();
- statsBuilder.setDownstreamType(downstreamTypeToEnum(downstreamType))
- .setUserType(userTypeToEnum(callerPkg))
- .setUpstreamType(UpstreamType.UT_UNKNOWN)
- .setErrorCode(ErrorCode.EC_NO_ERROR)
- .setUpstreamEvents(UpstreamEvents.newBuilder())
- .setDurationMillis(0);
- mBuilderMap.put(downstreamType, statsBuilder);
+
+ /**
+ * Return the current system time in milliseconds.
+ * @return the current system time in milliseconds.
+ */
+ public long timeNow() {
+ return System.currentTimeMillis();
}
- /** Update error code of given downstreamType. */
+ private static class RecordUpstreamEvent {
+ public final long mStartTime;
+ public final long mStopTime;
+ public final UpstreamType mUpstreamType;
+
+ RecordUpstreamEvent(final long startTime, final long stopTime,
+ final UpstreamType upstream) {
+ mStartTime = startTime;
+ mStopTime = stopTime;
+ mUpstreamType = upstream;
+ }
+ }
+
+ /**
+ * Creates a |NetworkTetheringReported.Builder| object to update the tethering stats for the
+ * specified downstream type and caller's package name. Initializes the upstream events, error
+ * code, and duration to default values. Sets the start time for the downstream type in the
+ * |mDownstreamStartTime| map.
+ * @param downstreamType The type of downstream connection (e.g. Wifi, USB, Bluetooth).
+ * @param callerPkg The package name of the caller.
+ */
+ public void createBuilder(final int downstreamType, final String callerPkg) {
+ NetworkTetheringReported.Builder statsBuilder = NetworkTetheringReported.newBuilder()
+ .setDownstreamType(downstreamTypeToEnum(downstreamType))
+ .setUserType(userTypeToEnum(callerPkg))
+ .setUpstreamType(UpstreamType.UT_UNKNOWN)
+ .setErrorCode(ErrorCode.EC_NO_ERROR)
+ .setUpstreamEvents(UpstreamEvents.newBuilder())
+ .setDurationMillis(0);
+ mBuilderMap.put(downstreamType, statsBuilder);
+ mDownstreamStartTime.put(downstreamType, timeNow());
+ }
+
+ /**
+ * Update the error code of the given downstream type in the Tethering stats.
+ * @param downstreamType The downstream type whose error code to update.
+ * @param errCode The error code to set.
+ */
public void updateErrorCode(final int downstreamType, final int errCode) {
NetworkTetheringReported.Builder statsBuilder = mBuilderMap.get(downstreamType);
if (statsBuilder == null) {
@@ -90,38 +140,145 @@
statsBuilder.setErrorCode(errorCodeToEnum(errCode));
}
- /** Remove Tethering stats.
- * If Tethering stats is ready to write then write it before removing.
+ /**
+ * Update the list of upstream types and their duration whenever the current upstream type
+ * changes.
+ * @param ns The UpstreamNetworkState object representing the current upstream network state.
+ */
+ public void maybeUpdateUpstreamType(@Nullable final UpstreamNetworkState ns) {
+ UpstreamType upstream = transportTypeToUpstreamTypeEnum(ns);
+ if (upstream.equals(mCurrentUpstream)) return;
+
+ final long newTime = timeNow();
+ if (mCurrentUpstream != null) {
+ mUpstreamEventList.add(new RecordUpstreamEvent(mCurrentUpStreamStartTime, newTime,
+ mCurrentUpstream));
+ }
+ mCurrentUpstream = upstream;
+ mCurrentUpStreamStartTime = newTime;
+ }
+
+ /**
+ * Updates the upstream events builder with a new upstream event.
+ * @param upstreamEventsBuilder the builder for the upstream events list
+ * @param start the start time of the upstream event
+ * @param stop the stop time of the upstream event
+ * @param upstream the type of upstream type (e.g. Wifi, Cellular, Bluetooth, ...)
+ */
+ private void addUpstreamEvent(final UpstreamEvents.Builder upstreamEventsBuilder,
+ final long start, final long stop, @Nullable final UpstreamType upstream) {
+ final UpstreamEvent.Builder upstreamEventBuilder = UpstreamEvent.newBuilder()
+ .setUpstreamType(upstream == null ? UpstreamType.UT_NO_NETWORK : upstream)
+ .setDurationMillis(stop - start);
+ upstreamEventsBuilder.addUpstreamEvent(upstreamEventBuilder);
+ }
+
+ /**
+ * Updates the |NetworkTetheringReported.Builder| with relevant upstream events associated with
+ * the downstream event identified by the given downstream start time.
+ *
+ * This method iterates through the list of upstream events and adds any relevant events to a
+ * |UpstreamEvents.Builder|. Upstream events are considered relevant if their stop time is
+ * greater than or equal to the given downstream start time. The method also adds the last
+ * upstream event that occurred up until the current time.
+ *
+ * The resulting |UpstreamEvents.Builder| is then added to the
+ * |NetworkTetheringReported.Builder|, along with the duration of the downstream event
+ * (i.e., stop time minus downstream start time).
+ *
+ * @param statsBuilder the builder for the NetworkTetheringReported message
+ * @param downstreamStartTime the start time of the downstream event to find relevant upstream
+ * events for
+ */
+ private void noteDownstreamStopped(final NetworkTetheringReported.Builder statsBuilder,
+ final long downstreamStartTime) {
+ UpstreamEvents.Builder upstreamEventsBuilder = UpstreamEvents.newBuilder();
+ for (RecordUpstreamEvent event : mUpstreamEventList) {
+ if (downstreamStartTime > event.mStopTime) continue;
+
+ final long startTime = Math.max(downstreamStartTime, event.mStartTime);
+ // Handle completed upstream events.
+ addUpstreamEvent(upstreamEventsBuilder, startTime, event.mStopTime,
+ event.mUpstreamType);
+ }
+ final long startTime = Math.max(downstreamStartTime, mCurrentUpStreamStartTime);
+ final long stopTime = timeNow();
+ // Handle the last upstream event.
+ addUpstreamEvent(upstreamEventsBuilder, startTime, stopTime, mCurrentUpstream);
+ statsBuilder.setUpstreamEvents(upstreamEventsBuilder);
+ statsBuilder.setDurationMillis(stopTime - downstreamStartTime);
+ }
+
+ /**
+ * Removes tethering statistics for the given downstream type. If there are any stats to write
+ * for the downstream event associated with the type, they are written before removing the
+ * statistics.
+ *
+ * If the given downstream type does not exist in the map, an error message is logged and the
+ * method returns without doing anything.
+ *
+ * @param downstreamType the type of downstream event to remove statistics for
*/
public void sendReport(final int downstreamType) {
- final NetworkTetheringReported.Builder statsBuilder =
- mBuilderMap.get(downstreamType);
+ final NetworkTetheringReported.Builder statsBuilder = mBuilderMap.get(downstreamType);
if (statsBuilder == null) {
Log.e(TAG, "Given downstreamType does not exist, this is a bug!");
return;
}
+
+ noteDownstreamStopped(statsBuilder, mDownstreamStartTime.get(downstreamType));
write(statsBuilder.build());
+
mBuilderMap.remove(downstreamType);
+ mDownstreamStartTime.remove(downstreamType);
}
- /** Collect Tethering stats and write metrics data to statsd pipeline. */
+ /**
+ * Collects tethering statistics and writes them to the statsd pipeline. This method takes in a
+ * NetworkTetheringReported object, extracts its fields and uses them to write statistics data
+ * to the statsd pipeline.
+ *
+ * @param reported a NetworkTetheringReported object containing statistics to write
+ */
@VisibleForTesting
public void write(@NonNull final NetworkTetheringReported reported) {
- TetheringStatsLog.write(TetheringStatsLog.NETWORK_TETHERING_REPORTED,
+ final byte[] upstreamEvents = reported.getUpstreamEvents().toByteArray();
+
+ TetheringStatsLog.write(
+ TetheringStatsLog.NETWORK_TETHERING_REPORTED,
reported.getErrorCode().getNumber(),
reported.getDownstreamType().getNumber(),
reported.getUpstreamType().getNumber(),
reported.getUserType().getNumber(),
- null, 0);
+ upstreamEvents,
+ reported.getDurationMillis());
if (DBG) {
- Log.d(TAG, "Write errorCode: " + reported.getErrorCode().getNumber()
- + ", downstreamType: " + reported.getDownstreamType().getNumber()
- + ", upstreamType: " + reported.getUpstreamType().getNumber()
- + ", userType: " + reported.getUserType().getNumber());
+ Log.d(
+ TAG,
+ "Write errorCode: "
+ + reported.getErrorCode().getNumber()
+ + ", downstreamType: "
+ + reported.getDownstreamType().getNumber()
+ + ", upstreamType: "
+ + reported.getUpstreamType().getNumber()
+ + ", userType: "
+ + reported.getUserType().getNumber()
+ + ", upstreamTypes: "
+ + Arrays.toString(upstreamEvents)
+ + ", durationMillis: "
+ + reported.getDurationMillis());
}
}
- /** Map {@link TetheringType} to {@link DownstreamType} */
+ /**
+ * Cleans up the variables related to upstream events when tethering is turned off.
+ */
+ public void cleanup() {
+ mUpstreamEventList.clear();
+ mCurrentUpstream = null;
+ mCurrentUpStreamStartTime = 0L;
+ }
+
private DownstreamType downstreamTypeToEnum(final int ifaceType) {
switch(ifaceType) {
case TETHERING_WIFI:
@@ -141,7 +298,6 @@
}
}
- /** Map {@link StartTetheringError} to {@link ErrorCode} */
private ErrorCode errorCodeToEnum(final int lastError) {
switch(lastError) {
case TETHER_ERROR_NO_ERROR:
@@ -181,7 +337,6 @@
}
}
- /** Map callerPkg to {@link UserType} */
private UserType userTypeToEnum(final String callerPkg) {
if (callerPkg.equals(SETTINGS_PKG_NAME)) {
return UserType.USER_SETTINGS;
@@ -193,4 +348,25 @@
return UserType.USER_UNKNOWN;
}
}
+
+ private UpstreamType transportTypeToUpstreamTypeEnum(final UpstreamNetworkState ns) {
+ final NetworkCapabilities nc = (ns != null) ? ns.networkCapabilities : null;
+ if (nc == null) return UpstreamType.UT_NO_NETWORK;
+
+ final int typeCount = nc.getTransportTypes().length;
+ // It's possible for a VCN network to be mapped to UT_UNKNOWN, as it may consist of both
+ // Wi-Fi and cellular transport.
+ // TODO: It's necessary to define a new upstream type for VCN, which can be identified by
+ // NET_CAPABILITY_NOT_VCN_MANAGED.
+ if (typeCount > 1) return UpstreamType.UT_UNKNOWN;
+
+ if (nc.hasTransport(TRANSPORT_CELLULAR)) return UpstreamType.UT_CELLULAR;
+ if (nc.hasTransport(TRANSPORT_WIFI)) return UpstreamType.UT_WIFI;
+ if (nc.hasTransport(TRANSPORT_BLUETOOTH)) return UpstreamType.UT_BLUETOOTH;
+ if (nc.hasTransport(TRANSPORT_ETHERNET)) return UpstreamType.UT_ETHERNET;
+ if (nc.hasTransport(TRANSPORT_WIFI_AWARE)) return UpstreamType.UT_WIFI_AWARE;
+ if (nc.hasTransport(TRANSPORT_LOWPAN)) return UpstreamType.UT_LOWPAN;
+
+ return UpstreamType.UT_UNKNOWN;
+ }
}
diff --git a/Tethering/tests/integration/Android.bp b/Tethering/tests/integration/Android.bp
index 11e3dc0..5e08aba 100644
--- a/Tethering/tests/integration/Android.bp
+++ b/Tethering/tests/integration/Android.bp
@@ -21,8 +21,7 @@
name: "TetheringIntegrationTestsDefaults",
defaults: ["framework-connectivity-test-defaults"],
srcs: [
- "src/**/*.java",
- "src/**/*.kt",
+ "base/**/*.java",
],
min_sdk_version: "30",
static_libs: [
@@ -47,6 +46,16 @@
],
}
+android_library {
+ name: "TetheringIntegrationTestsBaseLib",
+ target_sdk_version: "current",
+ platform_apis: true,
+ defaults: ["TetheringIntegrationTestsDefaults"],
+ visibility: [
+ "//packages/modules/Connectivity/Tethering/tests/mts",
+ ]
+}
+
// Library including tethering integration tests targeting the latest stable SDK.
// Use with NetworkStackJarJarRules.
android_library {
@@ -54,6 +63,9 @@
target_sdk_version: "33",
platform_apis: true,
defaults: ["TetheringIntegrationTestsDefaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
visibility: [
"//packages/modules/Connectivity/tests/cts/tethering",
"//packages/modules/Connectivity/tests:__subpackages__",
@@ -68,12 +80,16 @@
target_sdk_version: "current",
platform_apis: true,
defaults: ["TetheringIntegrationTestsDefaults"],
+ srcs: [
+ "src/**/*.java",
+ ],
visibility: [
"//packages/modules/Connectivity/tests/cts/tethering",
"//packages/modules/Connectivity/Tethering/tests/mts",
]
}
+// TODO: remove because TetheringIntegrationTests has been covered by ConnectivityCoverageTests.
android_test {
name: "TetheringIntegrationTests",
platform_apis: true,
@@ -81,6 +97,9 @@
test_suites: [
"device-tests",
],
+ srcs: [
+ "src/**/*.java",
+ ],
compile_multilib: "both",
jarjar_rules: ":NetworkStackJarJarRules",
}
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTestBase.java b/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java
similarity index 97%
rename from Tethering/tests/integration/src/android/net/EthernetTetheringTestBase.java
rename to Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java
index 7685981..007bf23 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTestBase.java
+++ b/Tethering/tests/integration/base/android/net/EthernetTetheringTestBase.java
@@ -72,6 +72,8 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.PacketBuilder;
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.structs.Ipv6Header;
import com.android.testutils.HandlerUtils;
import com.android.testutils.TapPacketReader;
import com.android.testutils.TestNetworkTracker;
@@ -213,6 +215,13 @@
}
}
+ protected void stopEthernetTethering(final MyTetheringEventCallback callback) {
+ runAsShell(TETHER_PRIVILEGED, () -> {
+ mTm.stopTethering(TETHERING_ETHERNET);
+ maybeUnregisterTetheringEventCallback(callback);
+ });
+ }
+
protected void cleanUp() throws Exception {
setPreferTestNetworks(false);
@@ -251,6 +260,7 @@
if (mRunTests) cleanUp();
} finally {
mHandlerThread.quitSafely();
+ mHandlerThread.join();
mUiAutomation.dropShellPermissionIdentity();
}
}
@@ -1013,6 +1023,18 @@
return new TetheringTester(mDownstreamReader, mUpstreamReader);
}
+ @NonNull
+ protected Inet6Address getClatIpv6Address(TetheringTester tester, TetheredDevice tethered)
+ throws Exception {
+ // Send an IPv4 UDP packet from client and check that a CLAT translated IPv6 UDP packet can
+ // be found on upstream interface. Get CLAT IPv6 address from the CLAT translated IPv6 UDP
+ // packet.
+ byte[] expectedPacket = probeV4TetheringConnectivity(tester, tethered, true /* is4To6 */);
+
+ // Above has guaranteed that the found packet is an IPv6 packet without ether header.
+ return Struct.parse(Ipv6Header.class, ByteBuffer.wrap(expectedPacket)).srcIp;
+ }
+
protected <T> List<T> toList(T... array) {
return Arrays.asList(array);
}
diff --git a/Tethering/tests/integration/src/android/net/TetheringTester.java b/Tethering/tests/integration/base/android/net/TetheringTester.java
similarity index 100%
rename from Tethering/tests/integration/src/android/net/TetheringTester.java
rename to Tethering/tests/integration/base/android/net/TetheringTester.java
diff --git a/Tethering/tests/integration/src/android/net/CtsEthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
similarity index 77%
rename from Tethering/tests/integration/src/android/net/CtsEthernetTetheringTest.java
rename to Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index aea6728..55854e2 100644
--- a/Tethering/tests/integration/src/android/net/CtsEthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -16,7 +16,6 @@
package android.net;
-import static android.Manifest.permission.DUMP;
import static android.net.InetAddresses.parseNumericAddress;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
import static android.net.TetheringManager.TETHERING_ETHERNET;
@@ -26,7 +25,6 @@
import static android.system.OsConstants.ICMP_ECHO;
import static android.system.OsConstants.ICMP_ECHOREPLY;
import static android.system.OsConstants.IPPROTO_ICMP;
-import static android.system.OsConstants.IPPROTO_UDP;
import static com.android.net.module.util.ConnectivityUtils.isIPv6ULA;
import static com.android.net.module.util.HexDump.dumpHexString;
@@ -39,48 +37,34 @@
import static com.android.net.module.util.NetworkStackConstants.IPV4_CHECKSUM_OFFSET;
import static com.android.net.module.util.NetworkStackConstants.IPV4_HEADER_MIN_LEN;
import static com.android.net.module.util.NetworkStackConstants.IPV4_LENGTH_OFFSET;
-import static com.android.testutils.DeviceInfoUtils.KVersion;
-import static com.android.testutils.TestPermissionUtil.runAsShell;
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 static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
-import android.content.Context;
import android.net.TetheringManager.TetheringRequest;
import android.net.TetheringTester.TetheredDevice;
import android.os.Build;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.VintfRuntimeInfo;
import android.util.Log;
-import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.net.module.util.BpfDump;
import com.android.net.module.util.Ipv6Utils;
import com.android.net.module.util.Struct;
-import com.android.net.module.util.bpf.Tether4Key;
-import com.android.net.module.util.bpf.Tether4Value;
-import com.android.net.module.util.bpf.TetherStatsKey;
-import com.android.net.module.util.bpf.TetherStatsValue;
import com.android.net.module.util.structs.EthernetHeader;
import com.android.net.module.util.structs.Icmpv4Header;
import com.android.net.module.util.structs.Ipv4Header;
-import com.android.net.module.util.structs.Ipv6Header;
import com.android.net.module.util.structs.UdpHeader;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
-import com.android.testutils.DeviceInfoUtils;
-import com.android.testutils.DumpTestUtils;
import com.android.testutils.TapPacketReader;
import org.junit.Rule;
@@ -96,9 +80,7 @@
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -106,34 +88,13 @@
@RunWith(AndroidJUnit4.class)
@MediumTest
-public class CtsEthernetTetheringTest extends EthernetTetheringTestBase {
+public class EthernetTetheringTest extends EthernetTetheringTestBase {
@Rule
public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
- private static final String TAG = CtsEthernetTetheringTest.class.getSimpleName();
-
- private static final int DUMP_POLLING_MAX_RETRY = 100;
- private static final int DUMP_POLLING_INTERVAL_MS = 50;
- // Kernel treats a confirmed UDP connection which active after two seconds as stream mode.
- // See upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5.
- private static final int UDP_STREAM_TS_MS = 2000;
- // Give slack time for waiting UDP stream mode because handling conntrack event in user space
- // may not in precise time. Used to reduce the flaky rate.
- private static final int UDP_STREAM_SLACK_MS = 500;
- // Per RX UDP packet size: iphdr (20) + udphdr (8) + payload (2) = 30 bytes.
- private static final int RX_UDP_PACKET_SIZE = 30;
- private static final int RX_UDP_PACKET_COUNT = 456;
- // Per TX UDP packet size: ethhdr (14) + iphdr (20) + udphdr (8) + payload (2) = 44 bytes.
- private static final int TX_UDP_PACKET_SIZE = 44;
- private static final int TX_UDP_PACKET_COUNT = 123;
+ private static final String TAG = EthernetTetheringTest.class.getSimpleName();
private static final short DNS_PORT = 53;
-
- private static final String DUMPSYS_TETHERING_RAWMAP_ARG = "bpfRawMap";
- private static final String DUMPSYS_RAWMAP_ARG_STATS = "--stats";
- private static final String DUMPSYS_RAWMAP_ARG_UPSTREAM4 = "--upstream4";
- private static final String LINE_DELIMITER = "\\n";
-
private static final short ICMPECHO_CODE = 0x0;
private static final short ICMPECHO_ID = 0x0;
private static final short ICMPECHO_SEQ = 0x0;
@@ -403,7 +364,7 @@
// Enable Ethernet tethering and check that it starts.
tetheringEventCallback = enableEthernetTethering(iface, null /* any upstream */);
} finally {
- maybeUnregisterTetheringEventCallback(tetheringEventCallback);
+ stopEthernetTethering(tetheringEventCallback);
}
// There is nothing more we can do on a physical interface without connecting an actual
// client, which is not possible in this test.
@@ -529,7 +490,7 @@
// remote ip public ip private ip
// 8.8.8.8:443 <Upstream ip>:9876 <TetheredDevice ip>:9876
//
- private void runUdp4Test(boolean verifyBpf) throws Exception {
+ private void runUdp4Test() throws Exception {
final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
toList(TEST_IP4_DNS));
final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
@@ -549,123 +510,6 @@
final InetAddress clientIp = tethered.ipv4Addr;
sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
-
- if (verifyBpf) {
- // Send second UDP packet in original direction.
- // The BPF coordinator only offloads the ASSURED conntrack entry. The "request + reply"
- // packets can make status IPS_SEEN_REPLY to be set. Need one more packet to make
- // conntrack status IPS_ASSURED_BIT to be set. Note the third packet needs to delay
- // 2 seconds because kernel monitors a UDP connection which still alive after 2 seconds
- // and apply ASSURED flag.
- // See kernel upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5 and
- // nf_conntrack_udp_packet in net/netfilter/nf_conntrack_proto_udp.c
- Thread.sleep(UDP_STREAM_TS_MS);
- sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
-
- // Give a slack time for handling conntrack event in user space.
- Thread.sleep(UDP_STREAM_SLACK_MS);
-
- // [1] Verify IPv4 upstream rule map.
- final HashMap<Tether4Key, Tether4Value> upstreamMap = pollRawMapFromDump(
- Tether4Key.class, Tether4Value.class, DUMPSYS_RAWMAP_ARG_UPSTREAM4);
- assertNotNull(upstreamMap);
- assertEquals(1, upstreamMap.size());
-
- final Map.Entry<Tether4Key, Tether4Value> rule =
- upstreamMap.entrySet().iterator().next();
-
- final Tether4Key upstream4Key = rule.getKey();
- assertEquals(IPPROTO_UDP, upstream4Key.l4proto);
- assertTrue(Arrays.equals(tethered.ipv4Addr.getAddress(), upstream4Key.src4));
- assertEquals(LOCAL_PORT, upstream4Key.srcPort);
- assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(), upstream4Key.dst4));
- assertEquals(REMOTE_PORT, upstream4Key.dstPort);
-
- final Tether4Value upstream4Value = rule.getValue();
- assertTrue(Arrays.equals(tetheringUpstreamIp.getAddress(),
- InetAddress.getByAddress(upstream4Value.src46).getAddress()));
- assertEquals(LOCAL_PORT, upstream4Value.srcPort);
- assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(),
- InetAddress.getByAddress(upstream4Value.dst46).getAddress()));
- assertEquals(REMOTE_PORT, upstream4Value.dstPort);
-
- // [2] Verify stats map.
- // Transmit packets on both direction for verifying stats. Because we only care the
- // packet count in stats test, we just reuse the existing packets to increaes
- // the packet count on both direction.
-
- // Send packets on original direction.
- for (int i = 0; i < TX_UDP_PACKET_COUNT; i++) {
- sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester,
- false /* is4To6 */);
- }
-
- // Send packets on reply direction.
- for (int i = 0; i < RX_UDP_PACKET_COUNT; i++) {
- sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
- }
-
- // Dump stats map to verify.
- final HashMap<TetherStatsKey, TetherStatsValue> statsMap = pollRawMapFromDump(
- TetherStatsKey.class, TetherStatsValue.class, DUMPSYS_RAWMAP_ARG_STATS);
- assertNotNull(statsMap);
- assertEquals(1, statsMap.size());
-
- final Map.Entry<TetherStatsKey, TetherStatsValue> stats =
- statsMap.entrySet().iterator().next();
-
- // TODO: verify the upstream index in TetherStatsKey.
-
- final TetherStatsValue statsValue = stats.getValue();
- assertEquals(RX_UDP_PACKET_COUNT, statsValue.rxPackets);
- assertEquals(RX_UDP_PACKET_COUNT * RX_UDP_PACKET_SIZE, statsValue.rxBytes);
- assertEquals(0, statsValue.rxErrors);
- assertEquals(TX_UDP_PACKET_COUNT, statsValue.txPackets);
- assertEquals(TX_UDP_PACKET_COUNT * TX_UDP_PACKET_SIZE, statsValue.txBytes);
- assertEquals(0, statsValue.txErrors);
- }
- }
-
- private static boolean isUdpOffloadSupportedByKernel(final String kernelVersion) {
- final KVersion current = DeviceInfoUtils.getMajorMinorSubminorVersion(kernelVersion);
- return current.isInRange(new KVersion(4, 14, 222), new KVersion(4, 19, 0))
- || current.isInRange(new KVersion(4, 19, 176), new KVersion(5, 4, 0))
- || current.isAtLeast(new KVersion(5, 4, 98));
- }
-
- @Test
- public void testIsUdpOffloadSupportedByKernel() throws Exception {
- assertFalse(isUdpOffloadSupportedByKernel("4.14.221"));
- assertTrue(isUdpOffloadSupportedByKernel("4.14.222"));
- assertTrue(isUdpOffloadSupportedByKernel("4.16.0"));
- assertTrue(isUdpOffloadSupportedByKernel("4.18.0"));
- assertFalse(isUdpOffloadSupportedByKernel("4.19.0"));
-
- assertFalse(isUdpOffloadSupportedByKernel("4.19.175"));
- assertTrue(isUdpOffloadSupportedByKernel("4.19.176"));
- assertTrue(isUdpOffloadSupportedByKernel("5.2.0"));
- assertTrue(isUdpOffloadSupportedByKernel("5.3.0"));
- assertFalse(isUdpOffloadSupportedByKernel("5.4.0"));
-
- assertFalse(isUdpOffloadSupportedByKernel("5.4.97"));
- assertTrue(isUdpOffloadSupportedByKernel("5.4.98"));
- assertTrue(isUdpOffloadSupportedByKernel("5.10.0"));
- }
-
- private static void assumeKernelSupportBpfOffloadUdpV4() {
- final String kernelVersion = VintfRuntimeInfo.getKernelVersion();
- assumeTrue("Kernel version " + kernelVersion + " doesn't support IPv4 UDP BPF offload",
- isUdpOffloadSupportedByKernel(kernelVersion));
- }
-
- @Test
- public void testKernelSupportBpfOffloadUdpV4() throws Exception {
- assumeKernelSupportBpfOffloadUdpV4();
- }
-
- @Test
- public void testTetherConfigBpfOffloadEnabled() throws Exception {
- assumeTrue(isTetherConfigBpfOffloadEnabled());
}
/**
@@ -674,85 +518,7 @@
*/
@Test
public void testTetherUdpV4() throws Exception {
- runUdp4Test(false /* verifyBpf */);
- }
-
- /**
- * BPF offload IPv4 UDP tethering test. Verify that UDP tethered packets are offloaded by BPF.
- * Minimum test requirement:
- * 1. S+ device.
- * 2. Tethering config enables tethering BPF offload.
- * 3. Kernel supports IPv4 UDP BPF offload. See #isUdpOffloadSupportedByKernel.
- *
- * TODO: consider enabling the test even tethering config disables BPF offload. See b/238288883
- */
- @Test
- @IgnoreUpTo(Build.VERSION_CODES.R)
- public void testTetherUdpV4_VerifyBpf() throws Exception {
- assumeTrue("Tethering config disabled BPF offload", isTetherConfigBpfOffloadEnabled());
- assumeKernelSupportBpfOffloadUdpV4();
-
- runUdp4Test(true /* verifyBpf */);
- }
-
- @NonNull
- private <K extends Struct, V extends Struct> HashMap<K, V> dumpAndParseRawMap(
- Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
- throws Exception {
- final String[] args = new String[] {DUMPSYS_TETHERING_RAWMAP_ARG, mapArg};
- final String rawMapStr = runAsShell(DUMP, () ->
- DumpTestUtils.dumpService(Context.TETHERING_SERVICE, args));
- final HashMap<K, V> map = new HashMap<>();
-
- for (final String line : rawMapStr.split(LINE_DELIMITER)) {
- final Pair<K, V> rule =
- BpfDump.fromBase64EncodedString(keyClass, valueClass, line.trim());
- map.put(rule.first, rule.second);
- }
- return map;
- }
-
- @Nullable
- private <K extends Struct, V extends Struct> HashMap<K, V> pollRawMapFromDump(
- Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
- throws Exception {
- for (int retryCount = 0; retryCount < DUMP_POLLING_MAX_RETRY; retryCount++) {
- final HashMap<K, V> map = dumpAndParseRawMap(keyClass, valueClass, mapArg);
- if (!map.isEmpty()) return map;
-
- Thread.sleep(DUMP_POLLING_INTERVAL_MS);
- }
-
- fail("Cannot get rules after " + DUMP_POLLING_MAX_RETRY * DUMP_POLLING_INTERVAL_MS + "ms");
- return null;
- }
-
- private boolean isTetherConfigBpfOffloadEnabled() throws Exception {
- final String dumpStr = runAsShell(DUMP, () ->
- DumpTestUtils.dumpService(Context.TETHERING_SERVICE, "--short"));
-
- // BPF offload tether config can be overridden by "config_tether_enable_bpf_offload" in
- // packages/modules/Connectivity/Tethering/res/values/config.xml. OEM may disable config by
- // RRO to override the enabled default value. Get the tethering config via dumpsys.
- // $ dumpsys tethering
- // mIsBpfEnabled: true
- boolean enabled = dumpStr.contains("mIsBpfEnabled: true");
- if (!enabled) {
- Log.d(TAG, "BPF offload tether config not enabled: " + dumpStr);
- }
- return enabled;
- }
-
- @NonNull
- private Inet6Address getClatIpv6Address(TetheringTester tester, TetheredDevice tethered)
- throws Exception {
- // Send an IPv4 UDP packet from client and check that a CLAT translated IPv6 UDP packet can
- // be found on upstream interface. Get CLAT IPv6 address from the CLAT translated IPv6 UDP
- // packet.
- byte[] expectedPacket = probeV4TetheringConnectivity(tester, tethered, true /* is4To6 */);
-
- // Above has guaranteed that the found packet is an IPv6 packet without ether header.
- return Struct.parse(Ipv6Header.class, ByteBuffer.wrap(expectedPacket)).srcIp;
+ runUdp4Test();
}
// Test network topology:
diff --git a/Tethering/tests/mts/Android.bp b/Tethering/tests/mts/Android.bp
index ae36499..4f4b03c 100644
--- a/Tethering/tests/mts/Android.bp
+++ b/Tethering/tests/mts/Android.bp
@@ -33,6 +33,7 @@
],
static_libs: [
+ "TetheringIntegrationTestsBaseLib",
"androidx.test.rules",
// mockito-target-extended-minus-junit4 used in this lib have dependency with
// jni_libs libdexmakerjvmtiagent and libstaticjvmtiagent.
diff --git a/Tethering/tests/mts/AndroidManifest.xml b/Tethering/tests/mts/AndroidManifest.xml
index 6d2abca..42f2da9 100644
--- a/Tethering/tests/mts/AndroidManifest.xml
+++ b/Tethering/tests/mts/AndroidManifest.xml
@@ -27,8 +27,6 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.tethering.mts"
android:label="MTS tests of android.tethering">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/Tethering/tests/mts/src/android/tethering/mts/MtsEthernetTetheringTest.java b/Tethering/tests/mts/src/android/tethering/mts/MtsEthernetTetheringTest.java
new file mode 100644
index 0000000..c2bc812
--- /dev/null
+++ b/Tethering/tests/mts/src/android/tethering/mts/MtsEthernetTetheringTest.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2022 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;
+
+import static android.Manifest.permission.DUMP;
+import static android.system.OsConstants.IPPROTO_UDP;
+
+import static com.android.testutils.DeviceInfoUtils.KVersion;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
+
+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 static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.TetheringTester.TetheredDevice;
+import android.os.Build;
+import android.os.VintfRuntimeInfo;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.net.module.util.BpfDump;
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
+import com.android.net.module.util.bpf.TetherStatsKey;
+import com.android.net.module.util.bpf.TetherStatsValue;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import com.android.testutils.DeviceInfoUtils;
+import com.android.testutils.DumpTestUtils;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class MtsEthernetTetheringTest extends EthernetTetheringTestBase {
+ @Rule
+ public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
+ private static final String TAG = MtsEthernetTetheringTest.class.getSimpleName();
+
+ private static final int DUMP_POLLING_MAX_RETRY = 100;
+ private static final int DUMP_POLLING_INTERVAL_MS = 50;
+ // Kernel treats a confirmed UDP connection which active after two seconds as stream mode.
+ // See upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5.
+ private static final int UDP_STREAM_TS_MS = 2000;
+ // Give slack time for waiting UDP stream mode because handling conntrack event in user space
+ // may not in precise time. Used to reduce the flaky rate.
+ private static final int UDP_STREAM_SLACK_MS = 500;
+ // Per RX UDP packet size: iphdr (20) + udphdr (8) + payload (2) = 30 bytes.
+ private static final int RX_UDP_PACKET_SIZE = 30;
+ private static final int RX_UDP_PACKET_COUNT = 456;
+ // Per TX UDP packet size: iphdr (20) + udphdr (8) + payload (2) = 30 bytes.
+ private static final int TX_UDP_PACKET_SIZE = 30;
+ private static final int TX_UDP_PACKET_COUNT = 123;
+
+ private static final String DUMPSYS_TETHERING_RAWMAP_ARG = "bpfRawMap";
+ private static final String DUMPSYS_RAWMAP_ARG_STATS = "--stats";
+ private static final String DUMPSYS_RAWMAP_ARG_UPSTREAM4 = "--upstream4";
+ private static final String LINE_DELIMITER = "\\n";
+
+ private static boolean isUdpOffloadSupportedByKernel(final String kernelVersion) {
+ final KVersion current = DeviceInfoUtils.getMajorMinorSubminorVersion(kernelVersion);
+ return current.isInRange(new KVersion(4, 14, 222), new KVersion(4, 19, 0))
+ || current.isInRange(new KVersion(4, 19, 176), new KVersion(5, 4, 0))
+ || current.isAtLeast(new KVersion(5, 4, 98));
+ }
+
+ @Test
+ public void testIsUdpOffloadSupportedByKernel() throws Exception {
+ assertFalse(isUdpOffloadSupportedByKernel("4.14.221"));
+ assertTrue(isUdpOffloadSupportedByKernel("4.14.222"));
+ assertTrue(isUdpOffloadSupportedByKernel("4.16.0"));
+ assertTrue(isUdpOffloadSupportedByKernel("4.18.0"));
+ assertFalse(isUdpOffloadSupportedByKernel("4.19.0"));
+
+ assertFalse(isUdpOffloadSupportedByKernel("4.19.175"));
+ assertTrue(isUdpOffloadSupportedByKernel("4.19.176"));
+ assertTrue(isUdpOffloadSupportedByKernel("5.2.0"));
+ assertTrue(isUdpOffloadSupportedByKernel("5.3.0"));
+ assertFalse(isUdpOffloadSupportedByKernel("5.4.0"));
+
+ assertFalse(isUdpOffloadSupportedByKernel("5.4.97"));
+ assertTrue(isUdpOffloadSupportedByKernel("5.4.98"));
+ assertTrue(isUdpOffloadSupportedByKernel("5.10.0"));
+ }
+
+ private static void assumeKernelSupportBpfOffloadUdpV4() {
+ final String kernelVersion = VintfRuntimeInfo.getKernelVersion();
+ assumeTrue("Kernel version " + kernelVersion + " doesn't support IPv4 UDP BPF offload",
+ isUdpOffloadSupportedByKernel(kernelVersion));
+ }
+
+ @Test
+ public void testKernelSupportBpfOffloadUdpV4() throws Exception {
+ assumeKernelSupportBpfOffloadUdpV4();
+ }
+
+ private boolean isTetherConfigBpfOffloadEnabled() throws Exception {
+ final String dumpStr = runAsShell(DUMP, () ->
+ DumpTestUtils.dumpService(Context.TETHERING_SERVICE, "--short"));
+
+ // BPF offload tether config can be overridden by "config_tether_enable_bpf_offload" in
+ // packages/modules/Connectivity/Tethering/res/values/config.xml. OEM may disable config by
+ // RRO to override the enabled default value. Get the tethering config via dumpsys.
+ // $ dumpsys tethering
+ // mIsBpfEnabled: true
+ boolean enabled = dumpStr.contains("mIsBpfEnabled: true");
+ if (!enabled) {
+ Log.d(TAG, "BPF offload tether config not enabled: " + dumpStr);
+ }
+ return enabled;
+ }
+
+ @Test
+ public void testTetherConfigBpfOffloadEnabled() throws Exception {
+ assumeTrue(isTetherConfigBpfOffloadEnabled());
+ }
+
+ @NonNull
+ private <K extends Struct, V extends Struct> HashMap<K, V> dumpAndParseRawMap(
+ Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
+ throws Exception {
+ final String[] args = new String[] {DUMPSYS_TETHERING_RAWMAP_ARG, mapArg};
+ final String rawMapStr = runAsShell(DUMP, () ->
+ DumpTestUtils.dumpService(Context.TETHERING_SERVICE, args));
+ final HashMap<K, V> map = new HashMap<>();
+
+ for (final String line : rawMapStr.split(LINE_DELIMITER)) {
+ final Pair<K, V> rule =
+ BpfDump.fromBase64EncodedString(keyClass, valueClass, line.trim());
+ map.put(rule.first, rule.second);
+ }
+ return map;
+ }
+
+ @Nullable
+ private <K extends Struct, V extends Struct> HashMap<K, V> pollRawMapFromDump(
+ Class<K> keyClass, Class<V> valueClass, @NonNull String mapArg)
+ throws Exception {
+ for (int retryCount = 0; retryCount < DUMP_POLLING_MAX_RETRY; retryCount++) {
+ final HashMap<K, V> map = dumpAndParseRawMap(keyClass, valueClass, mapArg);
+ if (!map.isEmpty()) return map;
+
+ Thread.sleep(DUMP_POLLING_INTERVAL_MS);
+ }
+
+ fail("Cannot get rules after " + DUMP_POLLING_MAX_RETRY * DUMP_POLLING_INTERVAL_MS + "ms");
+ return null;
+ }
+
+ // Test network topology:
+ //
+ // public network (rawip) private network
+ // | UE |
+ // +------------+ V +------------+------------+ V +------------+
+ // | Sever +---------+ Upstream | Downstream +---------+ Client |
+ // +------------+ +------------+------------+ +------------+
+ // remote ip public ip private ip
+ // 8.8.8.8:443 <Upstream ip>:9876 <TetheredDevice ip>:9876
+ //
+ private void runUdp4Test() throws Exception {
+ final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
+ toList(TEST_IP4_DNS));
+ final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
+
+ // TODO: remove the connectivity verification for upstream connected notification race.
+ // Because async upstream connected notification can't guarantee the tethering routing is
+ // ready to use. Need to test tethering connectivity before testing.
+ // For short term plan, consider using IPv6 RA to get MAC address because the prefix comes
+ // from upstream. That can guarantee that the routing is ready. Long term plan is that
+ // refactors upstream connected notification from async to sync.
+ probeV4TetheringConnectivity(tester, tethered, false /* is4To6 */);
+
+ final MacAddress srcMac = tethered.macAddr;
+ final MacAddress dstMac = tethered.routerMacAddr;
+ final InetAddress remoteIp = REMOTE_IP4_ADDR;
+ final InetAddress tetheringUpstreamIp = TEST_IP4_ADDR.getAddress();
+ final InetAddress clientIp = tethered.ipv4Addr;
+ sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
+ sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
+
+ // Send second UDP packet in original direction.
+ // The BPF coordinator only offloads the ASSURED conntrack entry. The "request + reply"
+ // packets can make status IPS_SEEN_REPLY to be set. Need one more packet to make
+ // conntrack status IPS_ASSURED_BIT to be set. Note the third packet needs to delay
+ // 2 seconds because kernel monitors a UDP connection which still alive after 2 seconds
+ // and apply ASSURED flag.
+ // See kernel upstream commit b7b1d02fc43925a4d569ec221715db2dfa1ce4f5 and
+ // nf_conntrack_udp_packet in net/netfilter/nf_conntrack_proto_udp.c
+ Thread.sleep(UDP_STREAM_TS_MS);
+ sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester, false /* is4To6 */);
+
+ // Give a slack time for handling conntrack event in user space.
+ Thread.sleep(UDP_STREAM_SLACK_MS);
+
+ // [1] Verify IPv4 upstream rule map.
+ final HashMap<Tether4Key, Tether4Value> upstreamMap = pollRawMapFromDump(
+ Tether4Key.class, Tether4Value.class, DUMPSYS_RAWMAP_ARG_UPSTREAM4);
+ assertNotNull(upstreamMap);
+ assertEquals(1, upstreamMap.size());
+
+ final Map.Entry<Tether4Key, Tether4Value> rule =
+ upstreamMap.entrySet().iterator().next();
+
+ final Tether4Key upstream4Key = rule.getKey();
+ assertEquals(IPPROTO_UDP, upstream4Key.l4proto);
+ assertTrue(Arrays.equals(tethered.ipv4Addr.getAddress(), upstream4Key.src4));
+ assertEquals(LOCAL_PORT, upstream4Key.srcPort);
+ assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(), upstream4Key.dst4));
+ assertEquals(REMOTE_PORT, upstream4Key.dstPort);
+
+ final Tether4Value upstream4Value = rule.getValue();
+ assertTrue(Arrays.equals(tetheringUpstreamIp.getAddress(),
+ InetAddress.getByAddress(upstream4Value.src46).getAddress()));
+ assertEquals(LOCAL_PORT, upstream4Value.srcPort);
+ assertTrue(Arrays.equals(REMOTE_IP4_ADDR.getAddress(),
+ InetAddress.getByAddress(upstream4Value.dst46).getAddress()));
+ assertEquals(REMOTE_PORT, upstream4Value.dstPort);
+
+ // [2] Verify stats map.
+ // Transmit packets on both direction for verifying stats. Because we only care the
+ // packet count in stats test, we just reuse the existing packets to increaes
+ // the packet count on both direction.
+
+ // Send packets on original direction.
+ for (int i = 0; i < TX_UDP_PACKET_COUNT; i++) {
+ sendUploadPacketUdp(srcMac, dstMac, clientIp, remoteIp, tester,
+ false /* is4To6 */);
+ }
+
+ // Send packets on reply direction.
+ for (int i = 0; i < RX_UDP_PACKET_COUNT; i++) {
+ sendDownloadPacketUdp(remoteIp, tetheringUpstreamIp, tester, false /* is6To4 */);
+ }
+
+ // Dump stats map to verify.
+ final HashMap<TetherStatsKey, TetherStatsValue> statsMap = pollRawMapFromDump(
+ TetherStatsKey.class, TetherStatsValue.class, DUMPSYS_RAWMAP_ARG_STATS);
+ assertNotNull(statsMap);
+ assertEquals(1, statsMap.size());
+
+ final Map.Entry<TetherStatsKey, TetherStatsValue> stats =
+ statsMap.entrySet().iterator().next();
+
+ // TODO: verify the upstream index in TetherStatsKey.
+
+ final TetherStatsValue statsValue = stats.getValue();
+ assertEquals(RX_UDP_PACKET_COUNT, statsValue.rxPackets);
+ assertEquals(RX_UDP_PACKET_COUNT * RX_UDP_PACKET_SIZE, statsValue.rxBytes);
+ assertEquals(0, statsValue.rxErrors);
+ assertEquals(TX_UDP_PACKET_COUNT, statsValue.txPackets);
+ assertEquals(TX_UDP_PACKET_COUNT * TX_UDP_PACKET_SIZE, statsValue.txBytes);
+ assertEquals(0, statsValue.txErrors);
+ }
+
+ /**
+ * BPF offload IPv4 UDP tethering test. Verify that UDP tethered packets are offloaded by BPF.
+ * Minimum test requirement:
+ * 1. S+ device.
+ * 2. Tethering config enables tethering BPF offload.
+ * 3. Kernel supports IPv4 UDP BPF offload. See #isUdpOffloadSupportedByKernel.
+ *
+ * TODO: consider enabling the test even tethering config disables BPF offload. See b/238288883
+ */
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testTetherBpfOffloadUdpV4() throws Exception {
+ assumeTrue("Tethering config disabled BPF offload", isTetherConfigBpfOffloadEnabled());
+ assumeKernelSupportBpfOffloadUdpV4();
+
+ runUdp4Test();
+ }
+}
diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
index 706df4e..b3fb3e4 100644
--- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
+++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
@@ -80,7 +80,7 @@
// Looper must be prepared here since AndroidJUnitRunner runs tests on separate threads.
if (Looper.myLooper() == null) Looper.prepare();
- mDeps = new OffloadHardwareInterface.Dependencies(mLog);
+ mDeps = new OffloadHardwareInterface.Dependencies(mHandler, mLog);
mOffloadHw = new OffloadHardwareInterface(mHandler, mLog, mDeps);
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index 1978e99..4f32f3c 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -16,6 +16,8 @@
package com.android.networkstack.tethering;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.ROAMING_NO;
@@ -77,6 +79,7 @@
import android.app.usage.NetworkStatsManager;
import android.net.INetd;
import android.net.InetAddresses;
+import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MacAddress;
@@ -89,6 +92,7 @@
import android.os.Build;
import android.os.Handler;
import android.os.test.TestLooper;
+import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -156,11 +160,13 @@
private static final int INVALID_IFINDEX = 0;
private static final int UPSTREAM_IFINDEX = 1001;
+ private static final int UPSTREAM_XLAT_IFINDEX = 1002;
private static final int UPSTREAM_IFINDEX2 = 1003;
private static final int DOWNSTREAM_IFINDEX = 2001;
private static final int DOWNSTREAM_IFINDEX2 = 2002;
private static final String UPSTREAM_IFACE = "rmnet0";
+ private static final String UPSTREAM_XLAT_IFACE = "v4-rmnet0";
private static final String UPSTREAM_IFACE2 = "wlan0";
private static final MacAddress DOWNSTREAM_MAC = MacAddress.fromString("12:34:56:78:90:ab");
@@ -183,6 +189,10 @@
private static final Inet4Address PRIVATE_ADDR2 =
(Inet4Address) InetAddresses.parseNumericAddress("192.168.90.12");
+ private static final Inet4Address XLAT_LOCAL_IPV4ADDR =
+ (Inet4Address) InetAddresses.parseNumericAddress("192.0.0.46");
+ private static final IpPrefix NAT64_IP_PREFIX = new IpPrefix("64:ff9b::/96");
+
// Generally, public port and private port are the same in the NAT conntrack message.
// TODO: consider using different private port and public port for testing.
private static final short REMOTE_PORT = (short) 443;
@@ -194,6 +204,10 @@
private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams(
UPSTREAM_IFACE, UPSTREAM_IFINDEX, null /* macAddr, rawip */,
NetworkStackConstants.ETHER_MTU);
+ private static final InterfaceParams UPSTREAM_XLAT_IFACE_PARAMS = new InterfaceParams(
+ UPSTREAM_XLAT_IFACE, UPSTREAM_XLAT_IFINDEX, null /* macAddr, rawip */,
+ NetworkStackConstants.ETHER_MTU - 28
+ /* mtu delta from external/android-clat/clatd.c */);
private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams(
UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.fromString("44:55:66:00:00:0c"),
NetworkStackConstants.ETHER_MTU);
@@ -2281,4 +2295,170 @@
verifyAddTetherOffloadRule4Mtu(INVALID_MTU, false /* isKernelMtu */,
NetworkStackConstants.ETHER_MTU /* expectedMtu */);
}
+
+ private static LinkProperties buildUpstreamLinkProperties(final String interfaceName,
+ boolean withIPv4, boolean withIPv6, boolean with464xlat) {
+ final LinkProperties prop = new LinkProperties();
+ prop.setInterfaceName(interfaceName);
+
+ if (withIPv4) {
+ // Assign the address no matter what the interface is. It is okay for now because
+ // only single upstream is available.
+ // TODO: consider to assign address by interface once we need to test two or more
+ // BPF supported upstreams or multi upstreams are supported.
+ prop.addLinkAddress(new LinkAddress(PUBLIC_ADDR, 24));
+ }
+
+ if (withIPv6) {
+ // TODO: make this to be constant. Currently, no test who uses this function cares what
+ // the upstream IPv6 address is.
+ prop.addLinkAddress(new LinkAddress("2001:db8::5175:15ca/64"));
+ }
+
+ if (with464xlat) {
+ final String clatInterface = "v4-" + interfaceName;
+ final LinkProperties stackedLink = new LinkProperties();
+ stackedLink.setInterfaceName(clatInterface);
+ stackedLink.addLinkAddress(new LinkAddress(XLAT_LOCAL_IPV4ADDR, 24));
+ prop.addStackedLink(stackedLink);
+ prop.setNat64Prefix(NAT64_IP_PREFIX);
+ }
+
+ return prop;
+ }
+
+ private void verifyIpv4Upstream(
+ @NonNull final HashMap<Inet4Address, Integer> ipv4UpstreamIndices,
+ @NonNull final SparseArray<String> interfaceNames) {
+ assertEquals(1, ipv4UpstreamIndices.size());
+ Integer upstreamIndex = ipv4UpstreamIndices.get(PUBLIC_ADDR);
+ assertNotNull(upstreamIndex);
+ assertEquals(UPSTREAM_IFINDEX, upstreamIndex.intValue());
+ assertEquals(1, interfaceNames.size());
+ assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+ }
+
+ private void verifyUpdateUpstreamNetworkState()
+ throws Exception {
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+ final HashMap<Inet4Address, Integer> ipv4UpstreamIndices =
+ coordinator.getIpv4UpstreamIndicesForTesting();
+ assertTrue(ipv4UpstreamIndices.isEmpty());
+ final SparseArray<String> interfaceNames =
+ coordinator.getInterfaceNamesForTesting();
+ assertEquals(0, interfaceNames.size());
+
+ // Verify the following are added or removed after upstream changes.
+ // - BpfCoordinator#mIpv4UpstreamIndices (for building IPv4 offload rules)
+ // - BpfCoordinator#mInterfaceNames (for updating limit)
+ //
+ // +-------+-------+-----------------------+
+ // | Test | Up | Protocol |
+ // | Case# | stream+-------+-------+-------+
+ // | | | IPv4 | IPv6 | Xlat |
+ // +-------+-------+-------+-------+-------+
+ // | 1 | Cell | O | | |
+ // +-------+-------+-------+-------+-------+
+ // | 2 | Cell | | O | |
+ // +-------+-------+-------+-------+-------+
+ // | 3 | Cell | O | O | |
+ // +-------+-------+-------+-------+-------+
+ // | 4 | - | | | |
+ // +-------+-------+-------+-------+-------+
+ // | | Cell | O | | |
+ // | +-------+-------+-------+-------+
+ // | 5 | Cell | | O | O | <-- doesn't support offload (xlat)
+ // | +-------+-------+-------+-------+
+ // | | Cell | O | | |
+ // +-------+-------+-------+-------+-------+
+ // | 6 | Wifi | O | O | | <-- doesn't support offload (ether ip)
+ // +-------+-------+-------+-------+-------+
+
+ // [1] Mobile IPv4 only
+ coordinator.addUpstreamNameToLookupTable(UPSTREAM_IFINDEX, UPSTREAM_IFACE);
+ doReturn(UPSTREAM_IFACE_PARAMS).when(mDeps).getInterfaceParams(UPSTREAM_IFACE);
+ final UpstreamNetworkState mobileIPv4UpstreamState = new UpstreamNetworkState(
+ buildUpstreamLinkProperties(UPSTREAM_IFACE,
+ true /* IPv4 */, false /* IPv6 */, false /* 464xlat */),
+ new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR),
+ new Network(TEST_NET_ID));
+ coordinator.updateUpstreamNetworkState(mobileIPv4UpstreamState);
+ verifyIpv4Upstream(ipv4UpstreamIndices, interfaceNames);
+
+ // [2] Mobile IPv6 only
+ final UpstreamNetworkState mobileIPv6UpstreamState = new UpstreamNetworkState(
+ buildUpstreamLinkProperties(UPSTREAM_IFACE,
+ false /* IPv4 */, true /* IPv6 */, false /* 464xlat */),
+ new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR),
+ new Network(TEST_NET_ID));
+ coordinator.updateUpstreamNetworkState(mobileIPv6UpstreamState);
+ assertTrue(ipv4UpstreamIndices.isEmpty());
+ assertEquals(1, interfaceNames.size());
+ assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+
+ // [3] Mobile IPv4 and IPv6
+ final UpstreamNetworkState mobileDualStackUpstreamState = new UpstreamNetworkState(
+ buildUpstreamLinkProperties(UPSTREAM_IFACE,
+ true /* IPv4 */, true /* IPv6 */, false /* 464xlat */),
+ new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR),
+ new Network(TEST_NET_ID));
+ coordinator.updateUpstreamNetworkState(mobileDualStackUpstreamState);
+ verifyIpv4Upstream(ipv4UpstreamIndices, interfaceNames);
+
+ // [4] Lost upstream
+ coordinator.updateUpstreamNetworkState(null);
+ assertTrue(ipv4UpstreamIndices.isEmpty());
+ assertEquals(1, interfaceNames.size());
+ assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+
+ // [5] verify xlat interface
+ // Expect that xlat interface information isn't added to mapping.
+ doReturn(UPSTREAM_XLAT_IFACE_PARAMS).when(mDeps).getInterfaceParams(
+ UPSTREAM_XLAT_IFACE);
+ final UpstreamNetworkState mobile464xlatUpstreamState = new UpstreamNetworkState(
+ buildUpstreamLinkProperties(UPSTREAM_IFACE,
+ false /* IPv4 */, true /* IPv6 */, true /* 464xlat */),
+ new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR),
+ new Network(TEST_NET_ID));
+
+ // Need to add a valid IPv4 upstream to verify that xlat interface doesn't support.
+ // Mobile IPv4 only
+ coordinator.updateUpstreamNetworkState(mobileIPv4UpstreamState);
+ verifyIpv4Upstream(ipv4UpstreamIndices, interfaceNames);
+
+ // Mobile IPv6 and xlat
+ // IpServer doesn't add xlat interface mapping via #addUpstreamNameToLookupTable on
+ // S and T devices.
+ coordinator.updateUpstreamNetworkState(mobile464xlatUpstreamState);
+ // Upstream IPv4 address mapping is removed because xlat interface is not supported.
+ assertTrue(ipv4UpstreamIndices.isEmpty());
+ assertEquals(1, interfaceNames.size());
+ assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+
+ // Need to add a valid IPv4 upstream to verify that wifi interface doesn't support.
+ // Mobile IPv4 only
+ coordinator.updateUpstreamNetworkState(mobileIPv4UpstreamState);
+ verifyIpv4Upstream(ipv4UpstreamIndices, interfaceNames);
+
+ // [6] Wifi IPv4 and IPv6
+ // Expect that upstream index map is cleared because ether ip is not supported.
+ coordinator.addUpstreamNameToLookupTable(UPSTREAM_IFINDEX2, UPSTREAM_IFACE2);
+ doReturn(UPSTREAM_IFACE_PARAMS2).when(mDeps).getInterfaceParams(UPSTREAM_IFACE2);
+ final UpstreamNetworkState wifiDualStackUpstreamState = new UpstreamNetworkState(
+ buildUpstreamLinkProperties(UPSTREAM_IFACE2,
+ true /* IPv4 */, true /* IPv6 */, false /* 464xlat */),
+ new NetworkCapabilities().addTransportType(TRANSPORT_WIFI),
+ new Network(TEST_NET_ID2));
+ coordinator.updateUpstreamNetworkState(wifiDualStackUpstreamState);
+ assertTrue(ipv4UpstreamIndices.isEmpty());
+ assertEquals(2, interfaceNames.size());
+ assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX));
+ assertTrue(interfaceNames.contains(UPSTREAM_IFINDEX2));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testUpdateUpstreamNetworkState() throws Exception {
+ verifyUpdateUpstreamNetworkState();
+ }
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
index faca1c8..36c15a7 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
@@ -31,8 +31,8 @@
import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_IFACE;
import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_UID;
import static com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_0;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_1;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_0;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_1;
import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
import static com.android.testutils.MiscAsserts.assertContainsAll;
import static com.android.testutils.MiscAsserts.assertThrows;
@@ -79,6 +79,7 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.net.module.util.SharedLog;
+import com.android.networkstack.tethering.OffloadHardwareInterface.OffloadHalCallback;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.TestableNetworkStatsProviderCbBinder;
@@ -125,8 +126,8 @@
private OffloadController.OffloadTetheringStatsProvider mTetherStatsProvider;
private final ArgumentCaptor<ArrayList> mStringArrayCaptor =
ArgumentCaptor.forClass(ArrayList.class);
- private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor =
- ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class);
+ private final ArgumentCaptor<OffloadHalCallback> mOffloadHalCallbackCaptor =
+ ArgumentCaptor.forClass(OffloadHalCallback.class);
private MockContentResolver mContentResolver;
private final TestLooper mTestLooper = new TestLooper();
private OffloadController.Dependencies mDeps = new OffloadController.Dependencies() {
@@ -151,10 +152,9 @@
FakeSettingsProvider.clearSettingsProvider();
}
- private void setupFunctioningHardwareInterface(int controlVersion) {
- when(mHardware.initOffloadConfig()).thenReturn(true);
- when(mHardware.initOffloadControl(mControlCallbackCaptor.capture()))
- .thenReturn(controlVersion);
+ private void setupFunctioningHardwareInterface(int offloadHalVersion) {
+ when(mHardware.initOffload(mOffloadHalCallbackCaptor.capture()))
+ .thenReturn(offloadHalVersion);
when(mHardware.setUpstreamParameters(anyString(), any(), any(), any())).thenReturn(true);
when(mHardware.getForwardedStats(any())).thenReturn(new ForwardedStats());
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
@@ -192,9 +192,9 @@
@Test
public void testStartStop() throws Exception {
stopOffloadController(
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/));
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/));
stopOffloadController(
- startOffloadController(OFFLOAD_HAL_VERSION_1_1, true /*expectStart*/));
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_1, true /*expectStart*/));
}
@NonNull
@@ -206,9 +206,8 @@
final InOrder inOrder = inOrder(mHardware);
inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, times(expectStart ? 1 : 0)).initOffloadConfig();
- inOrder.verify(mHardware, times(expectStart ? 1 : 0)).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
+ inOrder.verify(mHardware, times(expectStart ? 1 : 0)).initOffload(
+ any(OffloadHalCallback.class));
inOrder.verifyNoMoreInteractions();
// Clear counters only instead of whole mock to preserve the mocking setup.
clearInvocations(mHardware);
@@ -218,7 +217,7 @@
private void stopOffloadController(final OffloadController offload) throws Exception {
final InOrder inOrder = inOrder(mHardware);
offload.stop();
- inOrder.verify(mHardware, times(1)).stopOffloadControl();
+ inOrder.verify(mHardware, times(1)).stopOffload();
inOrder.verifyNoMoreInteractions();
reset(mHardware);
}
@@ -228,7 +227,7 @@
when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1);
assertThrows(SettingNotFoundException.class, () ->
Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, false /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, false /*expectStart*/);
}
@Test
@@ -236,26 +235,26 @@
when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0);
assertThrows(SettingNotFoundException.class, () ->
Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/);
}
@Test
public void testSettingsAllowsStart() throws Exception {
Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0);
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/);
}
@Test
public void testSettingsDisablesStart() throws Exception {
Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 1);
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, false /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, false /*expectStart*/);
}
@Test
public void testSetUpstreamLinkPropertiesWorking() throws Exception {
enableOffload();
final OffloadController offload =
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/);
// In reality, the UpstreamNetworkMonitor would have passed down to us
// a covering set of local prefixes representing a minimum essential
@@ -426,7 +425,7 @@
public void testGetForwardedStats() throws Exception {
enableOffload();
final OffloadController offload =
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/);
final String ethernetIface = "eth1";
final String mobileIface = "rmnet_data0";
@@ -521,11 +520,11 @@
// Verify the OffloadController is called by R framework, where the framework doesn't send
// warning.
// R only uses HAL 1.0.
- checkSetDataWarningAndLimit(false, OFFLOAD_HAL_VERSION_1_0);
+ checkSetDataWarningAndLimit(false, OFFLOAD_HAL_VERSION_HIDL_1_0);
// Verify the OffloadController is called by S+ framework, where the framework sends
// warning along with limit.
- checkSetDataWarningAndLimit(true, OFFLOAD_HAL_VERSION_1_0);
- checkSetDataWarningAndLimit(true, OFFLOAD_HAL_VERSION_1_1);
+ checkSetDataWarningAndLimit(true, OFFLOAD_HAL_VERSION_HIDL_1_0);
+ checkSetDataWarningAndLimit(true, OFFLOAD_HAL_VERSION_HIDL_1_1);
}
private void checkSetDataWarningAndLimit(boolean isProviderSetWarning, int controlVersion)
@@ -550,7 +549,7 @@
when(mHardware.setDataWarningAndLimit(anyString(), anyLong(), anyLong())).thenReturn(true);
offload.setUpstreamLinkProperties(lp);
// Applying an interface sends the initial quota to the hardware.
- if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
+ if (controlVersion >= OFFLOAD_HAL_VERSION_HIDL_1_1) {
inOrder.verify(mHardware).setDataWarningAndLimit(ethernetIface, Long.MAX_VALUE,
Long.MAX_VALUE);
} else {
@@ -576,7 +575,7 @@
mTetherStatsProvider.onSetLimit(ethernetIface, ethernetLimit);
}
waitForIdle();
- if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
+ if (controlVersion >= OFFLOAD_HAL_VERSION_HIDL_1_1) {
inOrder.verify(mHardware).setDataWarningAndLimit(ethernetIface, Long.MAX_VALUE,
ethernetLimit);
} else {
@@ -591,7 +590,7 @@
mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
}
waitForIdle();
- if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
+ if (controlVersion >= OFFLOAD_HAL_VERSION_HIDL_1_1) {
inOrder.verify(mHardware, never()).setDataWarningAndLimit(anyString(), anyLong(),
anyLong());
} else {
@@ -603,7 +602,7 @@
lp.setInterfaceName(mobileIface);
offload.setUpstreamLinkProperties(lp);
waitForIdle();
- if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
+ if (controlVersion >= OFFLOAD_HAL_VERSION_HIDL_1_1) {
inOrder.verify(mHardware).setDataWarningAndLimit(mobileIface,
isProviderSetWarning ? mobileWarning : Long.MAX_VALUE,
mobileLimit);
@@ -620,7 +619,7 @@
mTetherStatsProvider.onSetLimit(mobileIface, NetworkStatsProvider.QUOTA_UNLIMITED);
}
waitForIdle();
- if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
+ if (controlVersion >= OFFLOAD_HAL_VERSION_HIDL_1_1) {
inOrder.verify(mHardware).setDataWarningAndLimit(mobileIface, Long.MAX_VALUE,
Long.MAX_VALUE);
} else {
@@ -655,15 +654,15 @@
}
waitForIdle();
inOrder.verify(mHardware).getForwardedStats(ethernetIface);
- inOrder.verify(mHardware).stopOffloadControl();
+ inOrder.verify(mHardware).stopOffload();
}
@Test
public void testDataWarningAndLimitCallback_LimitReached() throws Exception {
enableOffload();
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/);
- final OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
+ final OffloadHalCallback callback = mOffloadHalCallbackCaptor.getValue();
callback.onStoppedLimitReached();
mTetherStatsProviderCb.expectNotifyStatsUpdated();
@@ -679,8 +678,8 @@
@Test
@IgnoreUpTo(Build.VERSION_CODES.R) // HAL 1.1 is only supported from S
public void testDataWarningAndLimitCallback_WarningReached() throws Exception {
- startOffloadController(OFFLOAD_HAL_VERSION_1_1, true /*expectStart*/);
- final OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_1, true /*expectStart*/);
+ final OffloadHalCallback callback = mOffloadHalCallbackCaptor.getValue();
callback.onWarningReached();
mTetherStatsProviderCb.expectNotifyStatsUpdated();
@@ -695,7 +694,7 @@
public void testAddRemoveDownstreams() throws Exception {
enableOffload();
final OffloadController offload =
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/);
final InOrder inOrder = inOrder(mHardware);
// Tethering makes several calls to setLocalPrefixes() before add/remove
@@ -710,14 +709,14 @@
usbLinkProperties.addRoute(
new RouteInfo(new IpPrefix(USB_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, USB_PREFIX);
+ inOrder.verify(mHardware, times(1)).addDownstream(RNDIS0, USB_PREFIX);
inOrder.verifyNoMoreInteractions();
// [2] Routes for IPv6 link-local prefixes should never be added.
usbLinkProperties.addRoute(
new RouteInfo(new IpPrefix(IPV6_LINKLOCAL), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString());
+ inOrder.verify(mHardware, never()).addDownstream(eq(RNDIS0), anyString());
inOrder.verifyNoMoreInteractions();
// [3] Add an IPv6 prefix for good measure. Only new offload-able
@@ -726,14 +725,14 @@
usbLinkProperties.addRoute(
new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX);
+ inOrder.verify(mHardware, times(1)).addDownstream(RNDIS0, IPV6_DOC_PREFIX);
inOrder.verifyNoMoreInteractions();
// [4] Adding addresses doesn't affect notifyDownstreamLinkProperties().
// The address is passed in by a separate setLocalPrefixes() invocation.
usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::2/64"));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString());
+ inOrder.verify(mHardware, never()).addDownstream(eq(RNDIS0), anyString());
// [5] Differences in local routes are converted into addDownstream()
// and removeDownstream() invocations accordingly.
@@ -742,8 +741,8 @@
usbLinkProperties.addRoute(
new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX), null, null, RTN_UNICAST));
offload.notifyDownstreamLinkProperties(usbLinkProperties);
- inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX);
- inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX);
+ inOrder.verify(mHardware, times(1)).removeDownstream(RNDIS0, IPV6_DOC_PREFIX);
+ inOrder.verify(mHardware, times(1)).addDownstream(RNDIS0, IPV6_DISCARD_PREFIX);
inOrder.verifyNoMoreInteractions();
// [6] Removing a downstream interface which was never added causes no
@@ -753,8 +752,8 @@
// [7] Removing an active downstream removes all remaining prefixes.
offload.removeDownstreamInterface(RNDIS0);
- inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, USB_PREFIX);
- inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX);
+ inOrder.verify(mHardware, times(1)).removeDownstream(RNDIS0, USB_PREFIX);
+ inOrder.verify(mHardware, times(1)).removeDownstream(RNDIS0, IPV6_DISCARD_PREFIX);
inOrder.verifyNoMoreInteractions();
}
@@ -762,7 +761,7 @@
public void testControlCallbackOnStoppedUnsupportedFetchesAllStats() throws Exception {
enableOffload();
final OffloadController offload =
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/);
// Pretend to set a few different upstreams (only the interface name
// matters for this test; we're ignoring IP and route information).
@@ -776,7 +775,7 @@
// that happen with setUpstreamParameters().
clearInvocations(mHardware);
- OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
+ OffloadHalCallback callback = mOffloadHalCallbackCaptor.getValue();
callback.onStoppedUnsupported();
// Verify forwarded stats behaviour.
@@ -793,7 +792,7 @@
throws Exception {
enableOffload();
final OffloadController offload =
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/);
// Pretend to set a few different upstreams (only the interface name
// matters for this test; we're ignoring IP and route information).
@@ -840,7 +839,7 @@
// that happen with setUpstreamParameters().
clearInvocations(mHardware);
- OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
+ OffloadHalCallback callback = mOffloadHalCallbackCaptor.getValue();
callback.onSupportAvailable();
// Verify forwarded stats behaviour.
@@ -859,8 +858,8 @@
// into OffloadController proper. After this, also check for:
// "192.168.43.1/32", "2001:2::1/128", "2001:2::2/128"
"127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64");
- verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "192.168.43.0/24");
- verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "2001:2::/64");
+ verify(mHardware, times(1)).addDownstream(WLAN0, "192.168.43.0/24");
+ verify(mHardware, times(1)).addDownstream(WLAN0, "2001:2::/64");
verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any());
verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong());
verifyNoMoreInteractions(mHardware);
@@ -871,7 +870,7 @@
enableOffload();
setOffloadPollInterval(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
final OffloadController offload =
- startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
+ startOffloadController(OFFLOAD_HAL_VERSION_HIDL_1_0, true /*expectStart*/);
// Initialize with fake eth upstream.
final String ethernetIface = "eth1";
@@ -925,7 +924,7 @@
offload.setUpstreamLinkProperties(makeEthernetLinkProperties());
mTetherStatsProvider.onSetAlert(0);
waitForIdle();
- if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
+ if (controlVersion >= OFFLOAD_HAL_VERSION_HIDL_1_1) {
mTetherStatsProviderCb.assertNoCallback();
} else {
mTetherStatsProviderCb.expectNotifyAlertReached();
@@ -935,7 +934,7 @@
@Test
public void testSoftwarePollingUsed() throws Exception {
- checkSoftwarePollingUsed(OFFLOAD_HAL_VERSION_1_0);
- checkSoftwarePollingUsed(OFFLOAD_HAL_VERSION_1_1);
+ checkSoftwarePollingUsed(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ checkSoftwarePollingUsed(OFFLOAD_HAL_VERSION_HIDL_1_1);
}
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHalAidlImplTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHalAidlImplTest.java
new file mode 100644
index 0000000..c9ce64f
--- /dev/null
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHalAidlImplTest.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2022 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.networkstack.tethering;
+
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_AIDL;
+
+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.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.tetheroffload.ForwardedStats;
+import android.hardware.tetheroffload.IOffload;
+import android.hardware.tetheroffload.IPv4AddrPortPair;
+import android.hardware.tetheroffload.ITetheringOffloadCallback;
+import android.hardware.tetheroffload.NatTimeoutUpdate;
+import android.hardware.tetheroffload.NetworkProtocol;
+import android.hardware.tetheroffload.OffloadCallbackEvent;
+import android.os.Handler;
+import android.os.NativeHandle;
+import android.os.ParcelFileDescriptor;
+import android.os.ServiceSpecificException;
+import android.os.test.TestLooper;
+import android.system.OsConstants;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.net.module.util.SharedLog;
+import com.android.networkstack.tethering.OffloadHardwareInterface.OffloadHalCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileDescriptor;
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class OffloadHalAidlImplTest {
+ private static final String RMNET0 = "test_rmnet_data0";
+
+ private final SharedLog mLog = new SharedLog("test");
+ private final TestLooper mTestLooper = new TestLooper();
+
+ private IOffload mIOffloadMock;
+ private OffloadHalAidlImpl mIOffloadHal;
+ private ITetheringOffloadCallback mTetheringOffloadCallback;
+ private OffloadHalCallback mOffloadHalCallback;
+
+ private void initAndValidateOffloadHal(boolean initSuccess)
+ throws Exception {
+ final FileDescriptor fd1 = new FileDescriptor();
+ final FileDescriptor fd2 = new FileDescriptor();
+ final NativeHandle handle1 = new NativeHandle(fd1, true);
+ final NativeHandle handle2 = new NativeHandle(fd2, true);
+ final ArgumentCaptor<ParcelFileDescriptor> fdCaptor1 =
+ ArgumentCaptor.forClass(ParcelFileDescriptor.class);
+ final ArgumentCaptor<ParcelFileDescriptor> fdCaptor2 =
+ ArgumentCaptor.forClass(ParcelFileDescriptor.class);
+ final ArgumentCaptor<ITetheringOffloadCallback> offloadCallbackCaptor =
+ ArgumentCaptor.forClass(ITetheringOffloadCallback.class);
+ if (initSuccess) {
+ doNothing().when(mIOffloadMock).initOffload(any(), any(), any());
+ } else {
+ doThrow(new IllegalStateException()).when(mIOffloadMock).initOffload(any(), any(),
+ any());
+ }
+ assertEquals(mIOffloadHal.initOffload(handle1, handle2, mOffloadHalCallback),
+ initSuccess);
+ verify(mIOffloadMock).initOffload(fdCaptor1.capture(), fdCaptor2.capture(),
+ offloadCallbackCaptor.capture());
+ assertEquals(fdCaptor1.getValue().getFd(), fd1.getInt$());
+ assertEquals(fdCaptor2.getValue().getFd(), fd2.getInt$());
+ mTetheringOffloadCallback = offloadCallbackCaptor.getValue();
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mIOffloadMock = mock(IOffload.class);
+ mIOffloadHal = new OffloadHalAidlImpl(OFFLOAD_HAL_VERSION_AIDL, mIOffloadMock,
+ new Handler(mTestLooper.getLooper()), mLog);
+ mOffloadHalCallback = spy(new OffloadHalCallback());
+ }
+
+ @Test
+ public void testInitOffloadSuccess() throws Exception {
+ initAndValidateOffloadHal(true /* initSuccess */);
+ }
+
+ @Test
+ public void testInitOffloadFailure() throws Exception {
+ initAndValidateOffloadHal(false /* initSuccess */);
+ }
+
+ @Test
+ public void testStopOffloadSuccess() throws Exception {
+ initAndValidateOffloadHal(true);
+ doNothing().when(mIOffloadMock).stopOffload();
+ assertTrue(mIOffloadHal.stopOffload());
+ verify(mIOffloadMock).stopOffload();
+ }
+
+ @Test
+ public void testStopOffloadFailure() throws Exception {
+ initAndValidateOffloadHal(true);
+ doThrow(new IllegalStateException()).when(mIOffloadMock).stopOffload();
+ assertFalse(mIOffloadHal.stopOffload());
+ }
+
+ private void doTestGetForwardedStats(boolean expectSuccess) throws Exception {
+ initAndValidateOffloadHal(true);
+ final ForwardedStats returnStats = new ForwardedStats();
+ if (expectSuccess) {
+ returnStats.rxBytes = 12345;
+ returnStats.txBytes = 67890;
+ when(mIOffloadMock.getForwardedStats(anyString())).thenReturn(returnStats);
+ } else {
+ when(mIOffloadMock.getForwardedStats(anyString()))
+ .thenThrow(new ServiceSpecificException(IOffload.ERROR_CODE_UNUSED));
+ }
+ final OffloadHardwareInterface.ForwardedStats stats =
+ mIOffloadHal.getForwardedStats(RMNET0);
+ verify(mIOffloadMock).getForwardedStats(eq(RMNET0));
+ assertNotNull(stats);
+ assertEquals(stats.rxBytes, returnStats.rxBytes);
+ assertEquals(stats.txBytes, returnStats.txBytes);
+ }
+
+ @Test
+ public void testGetForwardedStatsSuccess() throws Exception {
+ doTestGetForwardedStats(true);
+ }
+
+ @Test
+ public void testGetForwardedStatsFailure() throws Exception {
+ doTestGetForwardedStats(false);
+ }
+
+ private void doTestSetLocalPrefixes(boolean expectSuccess) throws Exception {
+ initAndValidateOffloadHal(true);
+ final ArrayList<String> localPrefixes = new ArrayList<>();
+ localPrefixes.add("127.0.0.0/8");
+ localPrefixes.add("fe80::/64");
+ final String[] localPrefixesArray =
+ localPrefixes.toArray(new String[localPrefixes.size()]);
+ if (expectSuccess) {
+ doNothing().when(mIOffloadMock).setLocalPrefixes(any());
+ } else {
+ doThrow(new IllegalArgumentException()).when(mIOffloadMock).setLocalPrefixes(any());
+ }
+ assertEquals(expectSuccess, mIOffloadHal.setLocalPrefixes(localPrefixes));
+ verify(mIOffloadMock).setLocalPrefixes(eq(localPrefixesArray));
+ }
+
+ @Test
+ public void testSetLocalPrefixesSuccess() throws Exception {
+ doTestSetLocalPrefixes(true);
+ }
+
+ @Test
+ public void testSetLocalPrefixesFailure() throws Exception {
+ doTestSetLocalPrefixes(false);
+ }
+
+ private void doTestSetDataLimit(boolean expectSuccess) throws Exception {
+ initAndValidateOffloadHal(true);
+ final long limit = 12345;
+ if (expectSuccess) {
+ doNothing().when(mIOffloadMock).setDataWarningAndLimit(anyString(), anyLong(),
+ anyLong());
+ } else {
+ doThrow(new IllegalArgumentException())
+ .when(mIOffloadMock).setDataWarningAndLimit(anyString(), anyLong(), anyLong());
+ }
+ assertEquals(expectSuccess, mIOffloadHal.setDataLimit(RMNET0, limit));
+ verify(mIOffloadMock).setDataWarningAndLimit(eq(RMNET0), eq(Long.MAX_VALUE), eq(limit));
+ }
+
+ @Test
+ public void testSetDataLimitSuccess() throws Exception {
+ doTestSetDataLimit(true);
+ }
+
+ @Test
+ public void testSetDataLimitFailure() throws Exception {
+ doTestSetDataLimit(false);
+ }
+
+ private void doTestSetDataWarningAndLimit(boolean expectSuccess) throws Exception {
+ initAndValidateOffloadHal(true);
+ final long warning = 12345;
+ final long limit = 67890;
+ if (expectSuccess) {
+ doNothing().when(mIOffloadMock).setDataWarningAndLimit(anyString(), anyLong(),
+ anyLong());
+ } else {
+ doThrow(new IllegalArgumentException())
+ .when(mIOffloadMock).setDataWarningAndLimit(anyString(), anyLong(), anyLong());
+ }
+ assertEquals(expectSuccess, mIOffloadHal.setDataWarningAndLimit(RMNET0, warning, limit));
+ verify(mIOffloadMock).setDataWarningAndLimit(eq(RMNET0), eq(warning), eq(limit));
+ }
+
+ @Test
+ public void testSetDataWarningAndLimitSuccess() throws Exception {
+ doTestSetDataWarningAndLimit(true);
+ }
+
+ @Test
+ public void testSetDataWarningAndLimitFailure() throws Exception {
+ doTestSetDataWarningAndLimit(false);
+ }
+
+ private void doTestSetUpstreamParameters(boolean expectSuccess) throws Exception {
+ initAndValidateOffloadHal(true);
+ final String v4addr = "192.168.10.1";
+ final String v4gateway = "192.168.10.255";
+ final ArrayList<String> v6gws = new ArrayList<>(0);
+ v6gws.add("2001:db8::1");
+ String[] v6gwsArray = v6gws.toArray(new String[v6gws.size()]);
+ if (expectSuccess) {
+ doNothing().when(mIOffloadMock).setUpstreamParameters(anyString(), anyString(),
+ anyString(), any());
+ } else {
+ doThrow(new IllegalArgumentException()).when(mIOffloadMock).setUpstreamParameters(
+ anyString(), anyString(), anyString(), any());
+ }
+ assertEquals(expectSuccess, mIOffloadHal.setUpstreamParameters(RMNET0, v4addr, v4gateway,
+ v6gws));
+ verify(mIOffloadMock).setUpstreamParameters(eq(RMNET0), eq(v4addr), eq(v4gateway),
+ eq(v6gwsArray));
+ }
+
+ @Test
+ public void testSetUpstreamParametersSuccess() throws Exception {
+ doTestSetUpstreamParameters(true);
+ }
+
+ @Test
+ public void testSetUpstreamParametersFailure() throws Exception {
+ doTestSetUpstreamParameters(false);
+ }
+
+ private void doTestAddDownstream(boolean expectSuccess) throws Exception {
+ initAndValidateOffloadHal(true);
+ final String ifName = "wlan1";
+ final String prefix = "192.168.43.0/24";
+ if (expectSuccess) {
+ doNothing().when(mIOffloadMock).addDownstream(anyString(), anyString());
+ } else {
+ doThrow(new IllegalStateException()).when(mIOffloadMock).addDownstream(anyString(),
+ anyString());
+ }
+ assertEquals(expectSuccess, mIOffloadHal.addDownstream(ifName, prefix));
+ verify(mIOffloadMock).addDownstream(eq(ifName), eq(prefix));
+ }
+
+ @Test
+ public void testAddDownstreamSuccess() throws Exception {
+ doTestAddDownstream(true);
+ }
+
+ @Test
+ public void testAddDownstreamFailure() throws Exception {
+ doTestAddDownstream(false);
+ }
+
+ private void doTestRemoveDownstream(boolean expectSuccess) throws Exception {
+ initAndValidateOffloadHal(true);
+ final String ifName = "wlan1";
+ final String prefix = "192.168.43.0/24";
+ if (expectSuccess) {
+ doNothing().when(mIOffloadMock).removeDownstream(anyString(), anyString());
+ } else {
+ doThrow(new IllegalArgumentException()).when(mIOffloadMock).removeDownstream(
+ anyString(), anyString());
+ }
+ assertEquals(expectSuccess, mIOffloadHal.removeDownstream(ifName, prefix));
+ verify(mIOffloadMock).removeDownstream(eq(ifName), eq(prefix));
+ }
+
+ @Test
+ public void testRemoveDownstreamSuccess() throws Exception {
+ doTestRemoveDownstream(true);
+ }
+
+ @Test
+ public void testRemoveDownstreamFailure() throws Exception {
+ doTestRemoveDownstream(false);
+ }
+
+ @Test
+ public void testTetheringOffloadCallback() throws Exception {
+ initAndValidateOffloadHal(true);
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STARTED);
+ mTestLooper.dispatchAll();
+ final InOrder inOrder = inOrder(mOffloadHalCallback);
+ inOrder.verify(mOffloadHalCallback).onStarted();
+ inOrder.verifyNoMoreInteractions();
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR);
+ mTestLooper.dispatchAll();
+ inOrder.verify(mOffloadHalCallback).onStoppedError();
+ inOrder.verifyNoMoreInteractions();
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED);
+ mTestLooper.dispatchAll();
+ inOrder.verify(mOffloadHalCallback).onStoppedUnsupported();
+ inOrder.verifyNoMoreInteractions();
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE);
+ mTestLooper.dispatchAll();
+ inOrder.verify(mOffloadHalCallback).onSupportAvailable();
+ inOrder.verifyNoMoreInteractions();
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED);
+ mTestLooper.dispatchAll();
+ inOrder.verify(mOffloadHalCallback).onStoppedLimitReached();
+ inOrder.verifyNoMoreInteractions();
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_WARNING_REACHED);
+ mTestLooper.dispatchAll();
+ inOrder.verify(mOffloadHalCallback).onWarningReached();
+ inOrder.verifyNoMoreInteractions();
+
+ final NatTimeoutUpdate tcpParams = buildNatTimeoutUpdate(NetworkProtocol.TCP);
+ mTetheringOffloadCallback.updateTimeout(tcpParams);
+ mTestLooper.dispatchAll();
+ inOrder.verify(mOffloadHalCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_TCP),
+ eq(tcpParams.src.addr),
+ eq(tcpParams.src.port),
+ eq(tcpParams.dst.addr),
+ eq(tcpParams.dst.port));
+ inOrder.verifyNoMoreInteractions();
+
+ final NatTimeoutUpdate udpParams = buildNatTimeoutUpdate(NetworkProtocol.UDP);
+ mTetheringOffloadCallback.updateTimeout(udpParams);
+ mTestLooper.dispatchAll();
+ inOrder.verify(mOffloadHalCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_UDP),
+ eq(udpParams.src.addr),
+ eq(udpParams.src.port),
+ eq(udpParams.dst.addr),
+ eq(udpParams.dst.port));
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) {
+ final NatTimeoutUpdate params = new NatTimeoutUpdate();
+ params.proto = proto;
+ params.src = new IPv4AddrPortPair();
+ params.dst = new IPv4AddrPortPair();
+ params.src.addr = "192.168.43.200";
+ params.src.port = 100;
+ params.dst.addr = "172.50.46.169";
+ params.dst.port = 150;
+ return params;
+ }
+}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHalHidlImplTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHalHidlImplTest.java
new file mode 100644
index 0000000..6fdab5a
--- /dev/null
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHalHidlImplTest.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2022 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.networkstack.tethering;
+
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_0;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_1;
+import static com.android.networkstack.tethering.util.TetheringUtils.uint16;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
+import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
+import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
+import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
+import android.hardware.tetheroffload.control.V1_1.ITetheringOffloadCallback;
+import android.hardware.tetheroffload.control.V1_1.OffloadCallbackEvent;
+import android.os.Handler;
+import android.os.NativeHandle;
+import android.os.test.TestLooper;
+import android.system.OsConstants;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.net.module.util.SharedLog;
+import com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats;
+import com.android.networkstack.tethering.OffloadHardwareInterface.OffloadHalCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileDescriptor;
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class OffloadHalHidlImplTest {
+ private static final String RMNET0 = "test_rmnet_data0";
+
+ private final SharedLog mLog = new SharedLog("test");
+ private final TestLooper mTestLooper = new TestLooper();
+
+ private OffloadHalHidlImpl mIOffloadHal;
+ private IOffloadConfig mIOffloadConfigMock;
+ private IOffloadControl mIOffloadControlMock;
+ private ITetheringOffloadCallback mTetheringOffloadCallback;
+ private OffloadHalCallback mOffloadHalCallback;
+
+ private void createAndInitOffloadHal(int version) throws Exception {
+ final FileDescriptor fd1 = new FileDescriptor();
+ final FileDescriptor fd2 = new FileDescriptor();
+ final NativeHandle handle1 = new NativeHandle(fd1, true);
+ final NativeHandle handle2 = new NativeHandle(fd2, true);
+ mIOffloadConfigMock = mock(IOffloadConfig.class);
+ switch (version) {
+ case OFFLOAD_HAL_VERSION_HIDL_1_0:
+ mIOffloadControlMock = mock(IOffloadControl.class);
+ break;
+ case OFFLOAD_HAL_VERSION_HIDL_1_1:
+ mIOffloadControlMock = mock(
+ android.hardware.tetheroffload.control.V1_1.IOffloadControl.class);
+ break;
+ default:
+ fail("Nonexistent HAL version");
+ return;
+ }
+ mIOffloadHal = new OffloadHalHidlImpl(version, mIOffloadConfigMock,
+ mIOffloadControlMock, new Handler(mTestLooper.getLooper()), mLog);
+ mIOffloadHal.initOffload(handle1, handle2, mOffloadHalCallback);
+
+ final ArgumentCaptor<NativeHandle> nativeHandleCaptor1 =
+ ArgumentCaptor.forClass(NativeHandle.class);
+ final ArgumentCaptor<NativeHandle> nativeHandleCaptor2 =
+ ArgumentCaptor.forClass(NativeHandle.class);
+ final ArgumentCaptor<ITetheringOffloadCallback> offloadCallbackCaptor =
+ ArgumentCaptor.forClass(ITetheringOffloadCallback.class);
+ verify(mIOffloadConfigMock).setHandles(nativeHandleCaptor1.capture(),
+ nativeHandleCaptor2.capture(), any());
+ verify(mIOffloadControlMock).initOffload(offloadCallbackCaptor.capture(), any());
+ assertEquals(nativeHandleCaptor1.getValue().getFileDescriptor().getInt$(),
+ handle1.getFileDescriptor().getInt$());
+ assertEquals(nativeHandleCaptor2.getValue().getFileDescriptor().getInt$(),
+ handle2.getFileDescriptor().getInt$());
+ mTetheringOffloadCallback = offloadCallbackCaptor.getValue();
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mOffloadHalCallback = spy(new OffloadHalCallback());
+ }
+
+ @Test
+ public void testGetForwardedStats() throws Exception {
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ final long rxBytes = 12345;
+ final long txBytes = 67890;
+ doAnswer(invocation -> {
+ ((IOffloadControl.getForwardedStatsCallback) invocation.getArgument(1))
+ .onValues(rxBytes, txBytes);
+ return null;
+ }).when(mIOffloadControlMock).getForwardedStats(eq(RMNET0), any());
+ final ForwardedStats stats = mIOffloadHal.getForwardedStats(RMNET0);
+ verify(mIOffloadControlMock).getForwardedStats(eq(RMNET0), any());
+ assertNotNull(stats);
+ assertEquals(rxBytes, stats.rxBytes);
+ assertEquals(txBytes, stats.txBytes);
+ }
+
+ private void doTestSetLocalPrefixes(boolean expectSuccess) throws Exception {
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ final ArrayList<String> localPrefixes = new ArrayList<>();
+ localPrefixes.add("127.0.0.0/8");
+ localPrefixes.add("fe80::/64");
+ doAnswer(invocation -> {
+ ((IOffloadControl.setLocalPrefixesCallback) invocation.getArgument(1))
+ .onValues(expectSuccess, "");
+ return null;
+ }).when(mIOffloadControlMock).setLocalPrefixes(eq(localPrefixes), any());
+ assertEquals(expectSuccess, mIOffloadHal.setLocalPrefixes(localPrefixes));
+ verify(mIOffloadControlMock).setLocalPrefixes(eq(localPrefixes), any());
+ }
+
+ @Test
+ public void testSetLocalPrefixesSuccess() throws Exception {
+ doTestSetLocalPrefixes(true);
+ }
+
+ @Test
+ public void testSetLocalPrefixesFailure() throws Exception {
+ doTestSetLocalPrefixes(false);
+ }
+
+ private void doTestSetDataLimit(boolean expectSuccess) throws Exception {
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ final long limit = 12345;
+ doAnswer(invocation -> {
+ ((IOffloadControl.setDataLimitCallback) invocation.getArgument(2))
+ .onValues(expectSuccess, "");
+ return null;
+ }).when(mIOffloadControlMock).setDataLimit(eq(RMNET0), eq(limit), any());
+ assertEquals(expectSuccess, mIOffloadHal.setDataLimit(RMNET0, limit));
+ verify(mIOffloadControlMock).setDataLimit(eq(RMNET0), eq(limit), any());
+ }
+
+ @Test
+ public void testSetDataLimitSuccess() throws Exception {
+ doTestSetDataLimit(true);
+ }
+
+ @Test
+ public void testSetDataLimitFailure() throws Exception {
+ doTestSetDataLimit(false);
+ }
+
+ private void doTestSetDataWarningAndLimit(boolean expectSuccess) throws Exception {
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_1);
+ final long warning = 12345;
+ final long limit = 67890;
+ doAnswer(invocation -> {
+ ((android.hardware.tetheroffload.control.V1_1.IOffloadControl
+ .setDataWarningAndLimitCallback) invocation.getArgument(3))
+ .onValues(expectSuccess, "");
+ return null;
+ }).when((android.hardware.tetheroffload.control.V1_1.IOffloadControl) mIOffloadControlMock)
+ .setDataWarningAndLimit(eq(RMNET0), eq(warning), eq(limit), any());
+ assertEquals(expectSuccess, mIOffloadHal.setDataWarningAndLimit(RMNET0, warning, limit));
+ verify((android.hardware.tetheroffload.control.V1_1.IOffloadControl) mIOffloadControlMock)
+ .setDataWarningAndLimit(eq(RMNET0), eq(warning), eq(limit), any());
+ }
+
+ @Test
+ public void testSetDataWarningAndLimitSuccess() throws Exception {
+ doTestSetDataWarningAndLimit(true);
+ }
+
+ @Test
+ public void testSetDataWarningAndLimitFailure() throws Exception {
+ // Verify that V1.0 control HAL would reject the function call with exception.
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ final long warning = 12345;
+ final long limit = 67890;
+ assertThrows(UnsupportedOperationException.class,
+ () -> mIOffloadHal.setDataWarningAndLimit(RMNET0, warning, limit));
+
+ doTestSetDataWarningAndLimit(false);
+ }
+
+ private void doTestSetUpstreamParameters(boolean expectSuccess) throws Exception {
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ final String v4addr = "192.168.10.1";
+ final String v4gateway = "192.168.10.255";
+ final ArrayList<String> v6gws = new ArrayList<>(0);
+ v6gws.add("2001:db8::1");
+ doAnswer(invocation -> {
+ ((IOffloadControl.setUpstreamParametersCallback) invocation.getArgument(4))
+ .onValues(expectSuccess, "");
+ return null;
+ }).when(mIOffloadControlMock).setUpstreamParameters(eq(RMNET0), eq(v4addr), eq(v4gateway),
+ eq(v6gws), any());
+ assertEquals(expectSuccess, mIOffloadHal.setUpstreamParameters(RMNET0, v4addr, v4gateway,
+ v6gws));
+ verify(mIOffloadControlMock).setUpstreamParameters(eq(RMNET0), eq(v4addr), eq(v4gateway),
+ eq(v6gws), any());
+ }
+
+ @Test
+ public void testSetUpstreamParametersSuccess() throws Exception {
+ doTestSetUpstreamParameters(true);
+ }
+
+ @Test
+ public void testSetUpstreamParametersFailure() throws Exception {
+ doTestSetUpstreamParameters(false);
+ }
+
+ private void doTestAddDownstream(boolean expectSuccess) throws Exception {
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ final String ifName = "wlan1";
+ final String prefix = "192.168.43.0/24";
+ doAnswer(invocation -> {
+ ((IOffloadControl.addDownstreamCallback) invocation.getArgument(2))
+ .onValues(expectSuccess, "");
+ return null;
+ }).when(mIOffloadControlMock).addDownstream(eq(ifName), eq(prefix), any());
+ assertEquals(expectSuccess, mIOffloadHal.addDownstream(ifName, prefix));
+ verify(mIOffloadControlMock).addDownstream(eq(ifName), eq(prefix), any());
+ }
+
+ @Test
+ public void testAddDownstreamSuccess() throws Exception {
+ doTestAddDownstream(true);
+ }
+
+ @Test
+ public void testAddDownstreamFailure() throws Exception {
+ doTestAddDownstream(false);
+ }
+
+ private void doTestRemoveDownstream(boolean expectSuccess) throws Exception {
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ final String ifName = "wlan1";
+ final String prefix = "192.168.43.0/24";
+ doAnswer(invocation -> {
+ ((IOffloadControl.removeDownstreamCallback) invocation.getArgument(2))
+ .onValues(expectSuccess, "");
+ return null;
+ }).when(mIOffloadControlMock).removeDownstream(eq(ifName), eq(prefix), any());
+ assertEquals(expectSuccess, mIOffloadHal.removeDownstream(ifName, prefix));
+ verify(mIOffloadControlMock).removeDownstream(eq(ifName), eq(prefix), any());
+ }
+
+ @Test
+ public void testRemoveDownstreamSuccess() throws Exception {
+ doTestRemoveDownstream(true);
+ }
+
+ @Test
+ public void testRemoveDownstreamFailure() throws Exception {
+ doTestRemoveDownstream(false);
+ }
+
+ @Test
+ public void testTetheringOffloadCallback() throws Exception {
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_0);
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STARTED);
+ mTestLooper.dispatchAll();
+ verify(mOffloadHalCallback).onStarted();
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR);
+ mTestLooper.dispatchAll();
+ verify(mOffloadHalCallback).onStoppedError();
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED);
+ mTestLooper.dispatchAll();
+ verify(mOffloadHalCallback).onStoppedUnsupported();
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE);
+ mTestLooper.dispatchAll();
+ verify(mOffloadHalCallback).onSupportAvailable();
+
+ mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED);
+ mTestLooper.dispatchAll();
+ verify(mOffloadHalCallback).onStoppedLimitReached();
+
+ final NatTimeoutUpdate tcpParams = buildNatTimeoutUpdate(NetworkProtocol.TCP);
+ mTetheringOffloadCallback.updateTimeout(tcpParams);
+ mTestLooper.dispatchAll();
+ verify(mOffloadHalCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_TCP),
+ eq(tcpParams.src.addr),
+ eq(uint16(tcpParams.src.port)),
+ eq(tcpParams.dst.addr),
+ eq(uint16(tcpParams.dst.port)));
+
+ final NatTimeoutUpdate udpParams = buildNatTimeoutUpdate(NetworkProtocol.UDP);
+ mTetheringOffloadCallback.updateTimeout(udpParams);
+ mTestLooper.dispatchAll();
+ verify(mOffloadHalCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_UDP),
+ eq(udpParams.src.addr),
+ eq(uint16(udpParams.src.port)),
+ eq(udpParams.dst.addr),
+ eq(uint16(udpParams.dst.port)));
+ reset(mOffloadHalCallback);
+
+ createAndInitOffloadHal(OFFLOAD_HAL_VERSION_HIDL_1_1);
+
+ // Verify the interface will process the events that comes from V1.1 HAL.
+ mTetheringOffloadCallback.onEvent_1_1(OffloadCallbackEvent.OFFLOAD_STARTED);
+ mTestLooper.dispatchAll();
+ final InOrder inOrder = inOrder(mOffloadHalCallback);
+ inOrder.verify(mOffloadHalCallback).onStarted();
+ inOrder.verifyNoMoreInteractions();
+
+ mTetheringOffloadCallback.onEvent_1_1(OffloadCallbackEvent.OFFLOAD_WARNING_REACHED);
+ mTestLooper.dispatchAll();
+ inOrder.verify(mOffloadHalCallback).onWarningReached();
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) {
+ final NatTimeoutUpdate params = new NatTimeoutUpdate();
+ params.proto = proto;
+ params.src.addr = "192.168.43.200";
+ params.src.port = 100;
+ params.dst.addr = "172.50.46.169";
+ params.dst.port = 150;
+ return params;
+ }
+}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
index 36b439b..b1f875b 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
@@ -20,36 +20,29 @@
import static android.system.OsConstants.AF_UNIX;
import static android.system.OsConstants.SOCK_STREAM;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_0;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_1;
-import static com.android.networkstack.tethering.util.TetheringUtils.uint16;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_AIDL;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_0;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_1;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
-import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
-import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
-import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
-import android.hardware.tetheroffload.control.V1_1.ITetheringOffloadCallback;
-import android.hardware.tetheroffload.control.V1_1.OffloadCallbackEvent;
import android.os.Handler;
import android.os.NativeHandle;
import android.os.test.TestLooper;
import android.system.ErrnoException;
import android.system.Os;
-import android.system.OsConstants;
-import android.util.Pair;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -57,12 +50,13 @@
import com.android.net.module.util.SharedLog;
import com.android.net.module.util.netlink.StructNfGenMsg;
import com.android.net.module.util.netlink.StructNlMsgHdr;
+import com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats;
+import com.android.networkstack.tethering.OffloadHardwareInterface.OffloadHalCallback;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -79,11 +73,9 @@
private final TestLooper mTestLooper = new TestLooper();
private OffloadHardwareInterface mOffloadHw;
- private ITetheringOffloadCallback mTetheringOffloadCallback;
- private OffloadHardwareInterface.ControlCallback mControlCallback;
+ private OffloadHalCallback mOffloadHalCallback;
- @Mock private IOffloadConfig mIOffloadConfig;
- private IOffloadControl mIOffloadControl;
+ @Mock private IOffloadHal mIOffload;
@Mock private NativeHandle mNativeHandle;
// Random values to test Netlink message.
@@ -91,32 +83,16 @@
private static final short TEST_FLAGS = 263;
class MyDependencies extends OffloadHardwareInterface.Dependencies {
- private final int mMockControlVersion;
- MyDependencies(SharedLog log, final int mockControlVersion) {
- super(log);
- mMockControlVersion = mockControlVersion;
+ private final int mMockOffloadHalVersion;
+ MyDependencies(Handler handler, SharedLog log, final int mockOffloadHalVersion) {
+ super(handler, log);
+ mMockOffloadHalVersion = mockOffloadHalVersion;
+ when(mIOffload.getVersion()).thenReturn(mMockOffloadHalVersion);
}
@Override
- public IOffloadConfig getOffloadConfig() {
- return mIOffloadConfig;
- }
-
- @Override
- public Pair<IOffloadControl, Integer> getOffloadControl() {
- switch (mMockControlVersion) {
- case OFFLOAD_HAL_VERSION_1_0:
- mIOffloadControl = mock(IOffloadControl.class);
- break;
- case OFFLOAD_HAL_VERSION_1_1:
- mIOffloadControl =
- mock(android.hardware.tetheroffload.control.V1_1.IOffloadControl.class);
- break;
- default:
- throw new IllegalArgumentException("Invalid offload control version "
- + mMockControlVersion);
- }
- return new Pair<IOffloadControl, Integer>(mIOffloadControl, mMockControlVersion);
+ public IOffloadHal getOffload() {
+ return mMockOffloadHalVersion == OFFLOAD_HAL_VERSION_NONE ? null : mIOffload;
}
@Override
@@ -128,156 +104,140 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mControlCallback = spy(new OffloadHardwareInterface.ControlCallback());
+ mOffloadHalCallback = new OffloadHalCallback();
+ when(mIOffload.initOffload(any(NativeHandle.class), any(NativeHandle.class),
+ any(OffloadHalCallback.class))).thenReturn(true);
}
- private void startOffloadHardwareInterface(int controlVersion) throws Exception {
+ private void startOffloadHardwareInterface(int offloadHalVersion)
+ throws Exception {
final SharedLog log = new SharedLog("test");
- mOffloadHw = new OffloadHardwareInterface(new Handler(mTestLooper.getLooper()), log,
- new MyDependencies(log, controlVersion));
- mOffloadHw.initOffloadConfig();
- mOffloadHw.initOffloadControl(mControlCallback);
- final ArgumentCaptor<ITetheringOffloadCallback> mOffloadCallbackCaptor =
- ArgumentCaptor.forClass(ITetheringOffloadCallback.class);
- verify(mIOffloadControl).initOffload(mOffloadCallbackCaptor.capture(), any());
- mTetheringOffloadCallback = mOffloadCallbackCaptor.getValue();
+ final Handler handler = new Handler(mTestLooper.getLooper());
+ final int num = offloadHalVersion != OFFLOAD_HAL_VERSION_NONE ? 1 : 0;
+ mOffloadHw = new OffloadHardwareInterface(handler, log,
+ new MyDependencies(handler, log, offloadHalVersion));
+ assertEquals(offloadHalVersion, mOffloadHw.initOffload(mOffloadHalCallback));
+ verify(mIOffload, times(num)).initOffload(any(NativeHandle.class), any(NativeHandle.class),
+ eq(mOffloadHalCallback));
+ }
+
+ @Test
+ public void testInitFailureWithNoHal() throws Exception {
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_NONE);
+ }
+
+ @Test
+ public void testInitSuccessWithAidl() throws Exception {
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_AIDL);
+ }
+
+ @Test
+ public void testInitSuccessWithHidl_1_0() throws Exception {
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ }
+
+ @Test
+ public void testInitSuccessWithHidl_1_1() throws Exception {
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_1);
}
@Test
public void testGetForwardedStats() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0);
- final OffloadHardwareInterface.ForwardedStats stats = mOffloadHw.getForwardedStats(RMNET0);
- verify(mIOffloadControl).getForwardedStats(eq(RMNET0), any());
- assertNotNull(stats);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ ForwardedStats stats = new ForwardedStats(12345, 56780);
+ when(mIOffload.getForwardedStats(anyString())).thenReturn(stats);
+ assertEquals(mOffloadHw.getForwardedStats(RMNET0), stats);
+ verify(mIOffload).getForwardedStats(eq(RMNET0));
}
@Test
public void testSetLocalPrefixes() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
final ArrayList<String> localPrefixes = new ArrayList<>();
localPrefixes.add("127.0.0.0/8");
localPrefixes.add("fe80::/64");
- mOffloadHw.setLocalPrefixes(localPrefixes);
- verify(mIOffloadControl).setLocalPrefixes(eq(localPrefixes), any());
+ when(mIOffload.setLocalPrefixes(any())).thenReturn(true);
+ assertTrue(mOffloadHw.setLocalPrefixes(localPrefixes));
+ verify(mIOffload).setLocalPrefixes(eq(localPrefixes));
+ when(mIOffload.setLocalPrefixes(any())).thenReturn(false);
+ assertFalse(mOffloadHw.setLocalPrefixes(localPrefixes));
}
@Test
public void testSetDataLimit() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
final long limit = 12345;
- mOffloadHw.setDataLimit(RMNET0, limit);
- verify(mIOffloadControl).setDataLimit(eq(RMNET0), eq(limit), any());
+ when(mIOffload.setDataLimit(anyString(), anyLong())).thenReturn(true);
+ assertTrue(mOffloadHw.setDataLimit(RMNET0, limit));
+ verify(mIOffload).setDataLimit(eq(RMNET0), eq(limit));
+ when(mIOffload.setDataLimit(anyString(), anyLong())).thenReturn(false);
+ assertFalse(mOffloadHw.setDataLimit(RMNET0, limit));
+ }
+
+ @Test
+ public void testSetDataWarningAndLimitFailureWithHidl_1_0() throws Exception {
+ // Verify V1.0 control HAL would reject the function call with exception.
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ final long warning = 12345;
+ final long limit = 67890;
+ assertThrows(UnsupportedOperationException.class,
+ () -> mOffloadHw.setDataWarningAndLimit(RMNET0, warning, limit));
}
@Test
public void testSetDataWarningAndLimit() throws Exception {
- // Verify V1.0 control HAL would reject the function call with exception.
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0);
+ // Verify V1.1 control HAL could receive this function call.
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_1);
final long warning = 12345;
final long limit = 67890;
- assertThrows(IllegalArgumentException.class,
- () -> mOffloadHw.setDataWarningAndLimit(RMNET0, warning, limit));
- reset(mIOffloadControl);
-
- // Verify V1.1 control HAL could receive this function call.
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_1);
- mOffloadHw.setDataWarningAndLimit(RMNET0, warning, limit);
- verify((android.hardware.tetheroffload.control.V1_1.IOffloadControl) mIOffloadControl)
- .setDataWarningAndLimit(eq(RMNET0), eq(warning), eq(limit), any());
+ when(mIOffload.setDataWarningAndLimit(anyString(), anyLong(), anyLong())).thenReturn(true);
+ assertTrue(mOffloadHw.setDataWarningAndLimit(RMNET0, warning, limit));
+ verify(mIOffload).setDataWarningAndLimit(eq(RMNET0), eq(warning), eq(limit));
+ when(mIOffload.setDataWarningAndLimit(anyString(), anyLong(), anyLong())).thenReturn(false);
+ assertFalse(mOffloadHw.setDataWarningAndLimit(RMNET0, warning, limit));
}
@Test
public void testSetUpstreamParameters() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
final String v4addr = "192.168.10.1";
final String v4gateway = "192.168.10.255";
final ArrayList<String> v6gws = new ArrayList<>(0);
v6gws.add("2001:db8::1");
- mOffloadHw.setUpstreamParameters(RMNET0, v4addr, v4gateway, v6gws);
- verify(mIOffloadControl).setUpstreamParameters(eq(RMNET0), eq(v4addr), eq(v4gateway),
- eq(v6gws), any());
+ when(mIOffload.setUpstreamParameters(anyString(), anyString(), anyString(), any()))
+ .thenReturn(true);
+ assertTrue(mOffloadHw.setUpstreamParameters(RMNET0, v4addr, v4gateway, v6gws));
+ verify(mIOffload).setUpstreamParameters(eq(RMNET0), eq(v4addr), eq(v4gateway), eq(v6gws));
final ArgumentCaptor<ArrayList<String>> mArrayListCaptor =
ArgumentCaptor.forClass(ArrayList.class);
- mOffloadHw.setUpstreamParameters(null, null, null, null);
- verify(mIOffloadControl).setUpstreamParameters(eq(""), eq(""), eq(""),
- mArrayListCaptor.capture(), any());
+ when(mIOffload.setUpstreamParameters(anyString(), anyString(), anyString(), any()))
+ .thenReturn(false);
+ assertFalse(mOffloadHw.setUpstreamParameters(null, null, null, null));
+ verify(mIOffload).setUpstreamParameters(eq(""), eq(""), eq(""), mArrayListCaptor.capture());
assertEquals(mArrayListCaptor.getValue().size(), 0);
}
@Test
- public void testUpdateDownstreamPrefix() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0);
+ public void testUpdateDownstream() throws Exception {
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
final String ifName = "wlan1";
final String prefix = "192.168.43.0/24";
- mOffloadHw.addDownstreamPrefix(ifName, prefix);
- verify(mIOffloadControl).addDownstream(eq(ifName), eq(prefix), any());
-
- mOffloadHw.removeDownstreamPrefix(ifName, prefix);
- verify(mIOffloadControl).removeDownstream(eq(ifName), eq(prefix), any());
- }
-
- @Test
- public void testTetheringOffloadCallback() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0);
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STARTED);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onStarted();
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onStoppedError();
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onStoppedUnsupported();
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onSupportAvailable();
-
- mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onStoppedLimitReached();
-
- final NatTimeoutUpdate tcpParams = buildNatTimeoutUpdate(NetworkProtocol.TCP);
- mTetheringOffloadCallback.updateTimeout(tcpParams);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_TCP),
- eq(tcpParams.src.addr),
- eq(uint16(tcpParams.src.port)),
- eq(tcpParams.dst.addr),
- eq(uint16(tcpParams.dst.port)));
-
- final NatTimeoutUpdate udpParams = buildNatTimeoutUpdate(NetworkProtocol.UDP);
- mTetheringOffloadCallback.updateTimeout(udpParams);
- mTestLooper.dispatchAll();
- verify(mControlCallback).onNatTimeoutUpdate(eq(OsConstants.IPPROTO_UDP),
- eq(udpParams.src.addr),
- eq(uint16(udpParams.src.port)),
- eq(udpParams.dst.addr),
- eq(uint16(udpParams.dst.port)));
- reset(mControlCallback);
-
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_1);
-
- // Verify the interface will process the events that comes from V1.1 HAL.
- mTetheringOffloadCallback.onEvent_1_1(OffloadCallbackEvent.OFFLOAD_STARTED);
- mTestLooper.dispatchAll();
- final InOrder inOrder = inOrder(mControlCallback);
- inOrder.verify(mControlCallback).onStarted();
- inOrder.verifyNoMoreInteractions();
-
- mTetheringOffloadCallback.onEvent_1_1(OffloadCallbackEvent.OFFLOAD_WARNING_REACHED);
- mTestLooper.dispatchAll();
- inOrder.verify(mControlCallback).onWarningReached();
- inOrder.verifyNoMoreInteractions();
+ when(mIOffload.addDownstream(anyString(), anyString())).thenReturn(true);
+ assertTrue(mOffloadHw.addDownstream(ifName, prefix));
+ verify(mIOffload).addDownstream(eq(ifName), eq(prefix));
+ when(mIOffload.addDownstream(anyString(), anyString())).thenReturn(false);
+ assertFalse(mOffloadHw.addDownstream(ifName, prefix));
+ when(mIOffload.removeDownstream(anyString(), anyString())).thenReturn(true);
+ assertTrue(mOffloadHw.removeDownstream(ifName, prefix));
+ verify(mIOffload).removeDownstream(eq(ifName), eq(prefix));
+ when(mIOffload.removeDownstream(anyString(), anyString())).thenReturn(false);
+ assertFalse(mOffloadHw.removeDownstream(ifName, prefix));
}
@Test
public void testSendIpv4NfGenMsg() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
FileDescriptor writeSocket = new FileDescriptor();
FileDescriptor readSocket = new FileDescriptor();
try {
@@ -308,14 +268,4 @@
assertEquals(0 /* error */, buffer.getShort()); // res_id
assertEquals(expectedLen, buffer.position());
}
-
- private NatTimeoutUpdate buildNatTimeoutUpdate(final int proto) {
- final NatTimeoutUpdate params = new NatTimeoutUpdate();
- params.proto = proto;
- params.src.addr = "192.168.43.200";
- params.src.port = 100;
- params.dst.addr = "172.50.46.169";
- params.dst.port = 150;
- return params;
- }
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
index 75c819b..ac3d713 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
@@ -156,6 +156,7 @@
@After
fun tearDown() {
fakeTetheringThread.quitSafely()
+ fakeTetheringThread.join()
}
private fun verifyActivityPendingIntent(intent: Intent, flags: Int) {
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index f90b3a4..c15b85e 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -29,6 +29,7 @@
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
@@ -67,7 +68,7 @@
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH;
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
-import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_0;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_0;
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE;
import static com.android.networkstack.tethering.TestConnectivityManager.BROADCAST_FIRST;
import static com.android.networkstack.tethering.TestConnectivityManager.CALLBACKS_FIRST;
@@ -261,6 +262,8 @@
private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
+ private static final Network[] NULL_NETWORK = new Network[] {null};
+
@Mock private ApplicationInfo mApplicationInfo;
@Mock private Context mContext;
@Mock private NetworkStatsManager mStatsManager;
@@ -303,6 +306,7 @@
private MockContentResolver mContentResolver;
private BroadcastReceiver mBroadcastReceiver;
private Tethering mTethering;
+ private TestTetheringEventCallback mTetheringEventCallback;
private PhoneStateListener mPhoneStateListener;
private InterfaceConfigurationParcel mInterfaceConfiguration;
private TetheringConfiguration mConfig;
@@ -645,8 +649,7 @@
mInterfaceConfiguration.flags = new String[0];
when(mRouterAdvertisementDaemon.start())
.thenReturn(true);
- initOffloadConfiguration(true /* offloadConfig */, OFFLOAD_HAL_VERSION_1_0,
- 0 /* defaultDisabled */);
+ initOffloadConfiguration(OFFLOAD_HAL_VERSION_HIDL_1_0, 0 /* defaultDisabled */);
when(mOffloadHardwareInterface.getForwardedStats(any())).thenReturn(mForwardedStats);
mServiceContext = new TestContext(mContext);
@@ -670,6 +673,7 @@
verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
verify(mNetd).registerUnsolicitedEventListener(any());
verifyDefaultNetworkRequestFiled();
+ mTetheringEventCallback = registerTetheringEventCallback();
final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
ArgumentCaptor.forClass(PhoneStateListener.class);
@@ -745,6 +749,16 @@
return request;
}
+ @NonNull
+ private TestTetheringEventCallback registerTetheringEventCallback() {
+ TestTetheringEventCallback callback = new TestTetheringEventCallback();
+ mTethering.registerTetheringEventCallback(callback);
+ mLooper.dispatchAll();
+ // Pull the first event which is filed immediately after the callback registration.
+ callback.expectUpstreamChanged(NULL_NETWORK);
+ return callback;
+ }
+
@After
public void tearDown() {
mServiceContext.unregisterReceiver(mBroadcastReceiver);
@@ -924,9 +938,9 @@
// tetherMatchingInterfaces() which starts by fetching all interfaces).
verify(mNetd, times(1)).interfaceGetList();
- // UpstreamNetworkMonitor should receive selected upstream
+ // Event callback should receive selected upstream
verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
- verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
+ mTetheringEventCallback.expectUpstreamChanged(upstreamState.network);
}
@Test
@@ -1181,7 +1195,7 @@
verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
- verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
+ mTetheringEventCallback.expectUpstreamChanged(upstreamState.network);
}
private void verifyDisableTryCellWhenTetheringStop(InOrder inOrder) {
@@ -1206,14 +1220,14 @@
mobile.fakeConnect();
mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
// Switch upstream to wifi.
wifi.fakeConnect();
mCm.makeDefaultNetwork(wifi, BROADCAST_FIRST);
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
}
private void verifyAutomaticUpstreamSelection(boolean configAutomatic) throws Exception {
@@ -1230,30 +1244,30 @@
// Switch upstreams a few times.
mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
mCm.makeDefaultNetwork(wifi, BROADCAST_FIRST, doDispatchAll);
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
// Wifi disconnecting should not have any affect since it's not the current upstream.
wifi.fakeDisconnect();
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ mTetheringEventCallback.assertNoUpstreamChangeCallback();
// Lose and regain upstream.
assertTrue(mUpstreamNetworkMonitor.getCurrentPreferredUpstream().linkProperties
@@ -1263,13 +1277,13 @@
mobile.fakeDisconnect();
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+ mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
mobile = new TestNetworkAgent(mCm, buildMobile464xlatUpstreamState());
mobile.fakeConnect();
mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
// Check the IP addresses to ensure that the upstream is indeed not the same as the previous
// mobile upstream, even though the netId is (unrealistically) the same.
@@ -1281,13 +1295,13 @@
mobile.fakeDisconnect();
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+ mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
mobile.fakeConnect();
mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
assertTrue(mUpstreamNetworkMonitor.getCurrentPreferredUpstream().linkProperties
.hasIPv4Address());
@@ -1328,27 +1342,27 @@
mLooper.dispatchAll();
mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST, null);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(mobile.networkId);
wifi.fakeConnect();
mLooper.dispatchAll();
mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST, null);
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
verifyDisableTryCellWhenTetheringStop(inOrder);
}
private void verifyWifiUpstreamAndUnregisterDunCallback(@NonNull final InOrder inOrder,
- @NonNull final TestNetworkAgent wifi,
- @NonNull final NetworkCallback currentDunCallack) throws Exception {
+ @NonNull final TestNetworkAgent wifi, @NonNull final NetworkCallback currentDunCallack)
+ throws Exception {
assertNotNull(currentDunCallack);
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
inOrder.verify(mCm).unregisterNetworkCallback(eq(currentDunCallack));
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
- inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ mTetheringEventCallback.expectUpstreamChanged(wifi.networkId);
+ mTetheringEventCallback.assertNoUpstreamChangeCallback();
}
@Nullable
@@ -1363,11 +1377,11 @@
captor.capture());
dunNetworkCallback = captor.getValue();
}
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+ mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
final Runnable doDispatchAll = () -> mLooper.dispatchAll();
dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
if (needToRequestNetwork) {
assertNotNull(dunNetworkCallback);
@@ -1484,11 +1498,11 @@
dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+ mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
inOrder.verify(mCm, never()).unregisterNetworkCallback(any(NetworkCallback.class));
dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
verifyDisableTryCellWhenTetheringStop(inOrder);
}
@@ -1543,8 +1557,8 @@
// automatic mode would request dun again and choose it as upstream.
mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
mLooper.dispatchAll();
- final NetworkCallback dunNetworkCallback2 =
- verifyDunUpstream(inOrder, dun, true /* needToRequestNetwork */);
+ final NetworkCallback dunNetworkCallback2 = verifyDunUpstream(inOrder, dun,
+ true /* needToRequestNetwork */);
// [3] When default network switch to wifi and mobile is still connected,
// unregister dun request and choose wifi as upstream.
@@ -1556,7 +1570,7 @@
final Runnable doDispatchAll = () -> mLooper.dispatchAll();
mobile.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ mTetheringEventCallback.assertNoUpstreamChangeCallback();
verifyDisableTryCellWhenTetheringStop(inOrder);
}
@@ -1627,19 +1641,19 @@
final Runnable doDispatchAll = () -> mLooper.dispatchAll();
dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
// [6] When mobile is connected and default network switch to mobile, keep dun as upstream.
mobile.fakeConnect();
mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ mTetheringEventCallback.assertNoUpstreamChangeCallback();
// [7] When mobile is disconnected, keep dun as upstream.
mCm.makeDefaultNetwork(null, CALLBACKS_FIRST, doDispatchAll);
mobile.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ mTetheringEventCallback.assertNoUpstreamChangeCallback();
verifyDisableTryCellWhenTetheringStop(inOrder);
}
@@ -1670,7 +1684,7 @@
final Runnable doDispatchAll = () -> mLooper.dispatchAll();
dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
// [8] Lose and regain upstream again.
dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
@@ -1714,7 +1728,7 @@
final Runnable doDispatchAll = () -> mLooper.dispatchAll();
dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
// [9] When wifi is connected and default network switch to wifi, unregister dun request
// and choose wifi as upstream. When dun is disconnected, keep wifi as upstream.
@@ -1724,7 +1738,7 @@
verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback);
dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ mTetheringEventCallback.assertNoUpstreamChangeCallback();
// [10] When mobile and mobile are connected and default network switch to mobile
// (may have low signal), automatic mode would request dun again and choose it as
@@ -1752,7 +1766,7 @@
mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
- inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ mTetheringEventCallback.assertNoUpstreamChangeCallback();
// BUG: when wifi disconnect, the dun request would not be filed again because wifi is
// no longer be default network which do not have CONNECTIVIY_ACTION broadcast.
wifi.fakeDisconnect();
@@ -1799,20 +1813,21 @@
}
private void chooseDunUpstreamTestCommon(final boolean automatic, InOrder inOrder,
- TestNetworkAgent mobile, TestNetworkAgent wifi, TestNetworkAgent dun) throws Exception {
+ TestNetworkAgent mobile, TestNetworkAgent wifi, TestNetworkAgent dun)
+ throws Exception {
final NetworkCallback dunNetworkCallback = setupDunUpstreamTest(automatic, inOrder);
// Pretend cellular connected and expect the upstream to be not set.
mobile.fakeConnect();
mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(mobile.networkId);
+ mTetheringEventCallback.assertNoUpstreamChangeCallback();
// Pretend dun connected and expect choose dun as upstream.
final Runnable doDispatchAll = () -> mLooper.dispatchAll();
dun.fakeConnect(BROADCAST_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+ mTetheringEventCallback.expectUpstreamChanged(dun.networkId);
// When wifi connected, unregister dun request and choose wifi as upstream.
wifi.fakeConnect();
@@ -1821,7 +1836,7 @@
verifyWifiUpstreamAndUnregisterDunCallback(inOrder, wifi, dunNetworkCallback);
dun.fakeDisconnect(BROADCAST_FIRST, doDispatchAll);
mLooper.dispatchAll();
- inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ mTetheringEventCallback.assertNoUpstreamChangeCallback();
}
private void runNcmTethering() {
@@ -1985,6 +2000,7 @@
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
+ verify(mTetheringMetrics, times(0)).maybeUpdateUpstreamType(any());
verify(mTetheringMetrics, times(2)).updateErrorCode(eq(TETHERING_WIFI),
eq(TETHER_ERROR_INTERNAL_ERROR));
verify(mTetheringMetrics, times(2)).sendReport(eq(TETHERING_WIFI));
@@ -2268,7 +2284,7 @@
mTethering.registerTetheringEventCallback(callback);
mLooper.dispatchAll();
callback.expectTetheredClientChanged(Collections.emptyList());
- callback.expectUpstreamChanged(new Network[] {null});
+ callback.expectUpstreamChanged(NULL_NETWORK);
callback.expectConfigurationChanged(
mTethering.getTetheringConfiguration().toStableParcelable());
TetherStatesParcel tetherState = callback.pollTetherStatesChanged();
@@ -2316,7 +2332,7 @@
tetherState = callback2.pollTetherStatesChanged();
assertArrayEquals(tetherState.availableList, new TetheringInterface[] {wifiIface});
mLooper.dispatchAll();
- callback2.expectUpstreamChanged(new Network[] {null});
+ callback2.expectUpstreamChanged(NULL_NETWORK);
callback2.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
callback.assertNoCallback();
}
@@ -2329,25 +2345,15 @@
mLooper.dispatchAll();
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
- // 1. Offload fail if no OffloadConfig.
- initOffloadConfiguration(false /* offloadConfig */, OFFLOAD_HAL_VERSION_1_0,
- 0 /* defaultDisabled */);
+ // 1. Offload fail if no IOffloadHal.
+ initOffloadConfiguration(OFFLOAD_HAL_VERSION_NONE, 0 /* defaultDisabled */);
runUsbTethering(upstreamState);
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED);
runStopUSBTethering();
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
reset(mUsbManager, mIPv6TetheringCoordinator);
- // 2. Offload fail if no OffloadControl.
- initOffloadConfiguration(true /* offloadConfig */, OFFLOAD_HAL_VERSION_NONE,
- 0 /* defaultDisabled */);
- runUsbTethering(upstreamState);
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED);
- runStopUSBTethering();
- callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
- reset(mUsbManager, mIPv6TetheringCoordinator);
- // 3. Offload fail if disabled by settings.
- initOffloadConfiguration(true /* offloadConfig */, OFFLOAD_HAL_VERSION_1_0,
- 1 /* defaultDisabled */);
+ // 2. Offload fail if disabled by settings.
+ initOffloadConfiguration(OFFLOAD_HAL_VERSION_HIDL_1_0, 1 /* defaultDisabled */);
runUsbTethering(upstreamState);
callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED);
runStopUSBTethering();
@@ -2362,11 +2368,10 @@
verify(mUsbManager).setCurrentFunctions(UsbManager.FUNCTION_NONE);
}
- private void initOffloadConfiguration(final boolean offloadConfig,
- @OffloadHardwareInterface.OffloadHalVersion final int offloadControlVersion,
+ private void initOffloadConfiguration(
+ @OffloadHardwareInterface.OffloadHalVersion final int offloadHalVersion,
final int defaultDisabled) {
- when(mOffloadHardwareInterface.initOffloadConfig()).thenReturn(offloadConfig);
- when(mOffloadHardwareInterface.initOffloadControl(any())).thenReturn(offloadControlVersion);
+ when(mOffloadHardwareInterface.initOffload(any())).thenReturn(offloadHalVersion);
when(mOffloadHardwareInterface.getDefaultTetherOffloadDisabled()).thenReturn(
defaultDisabled);
}
@@ -2663,27 +2668,67 @@
public void testUpstreamNetworkChanged() {
final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
mTetheringDependencies.mUpstreamNetworkMonitorSM;
+ final InOrder inOrder = inOrder(mNotificationUpdater);
+
+ // Gain upstream.
final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
initTetheringUpstream(upstreamState);
stateMachine.chooseUpstreamType(true);
+ mTetheringEventCallback.expectUpstreamChanged(upstreamState.network);
+ inOrder.verify(mNotificationUpdater)
+ .onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
- verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(eq(upstreamState.network));
- verify(mNotificationUpdater, times(1)).onUpstreamCapabilitiesChanged(any());
+ // Set the upstream with the same network ID but different object and the same capability.
+ final UpstreamNetworkState upstreamState2 = buildMobileIPv4UpstreamState();
+ initTetheringUpstream(upstreamState2);
+ stateMachine.chooseUpstreamType(true);
+ // Bug: duplicated upstream change event.
+ mTetheringEventCallback.expectUpstreamChanged(upstreamState2.network);
+ inOrder.verify(mNotificationUpdater)
+ .onUpstreamCapabilitiesChanged(upstreamState2.networkCapabilities);
+
+ // Set the upstream with the same network ID but different object and different capability.
+ final UpstreamNetworkState upstreamState3 = buildMobileIPv4UpstreamState();
+ assertFalse(upstreamState3.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
+ upstreamState3.networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
+ initTetheringUpstream(upstreamState3);
+ stateMachine.chooseUpstreamType(true);
+ // Bug: duplicated upstream change event.
+ mTetheringEventCallback.expectUpstreamChanged(upstreamState3.network);
+ inOrder.verify(mNotificationUpdater)
+ .onUpstreamCapabilitiesChanged(upstreamState3.networkCapabilities);
+
+ // Lose upstream.
+ initTetheringUpstream(null);
+ stateMachine.chooseUpstreamType(true);
+ mTetheringEventCallback.expectUpstreamChanged(NULL_NETWORK);
+ inOrder.verify(mNotificationUpdater).onUpstreamCapabilitiesChanged(null);
}
@Test
public void testUpstreamCapabilitiesChanged() {
final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
mTetheringDependencies.mUpstreamNetworkMonitorSM;
+ final InOrder inOrder = inOrder(mNotificationUpdater);
final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
initTetheringUpstream(upstreamState);
+
stateMachine.chooseUpstreamType(true);
+ inOrder.verify(mNotificationUpdater)
+ .onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
- // Should have two onUpstreamCapabilitiesChanged().
- // One is called by reportUpstreamChanged(). One is called by EVENT_ON_CAPABILITIES.
- verify(mNotificationUpdater, times(2)).onUpstreamCapabilitiesChanged(any());
- reset(mNotificationUpdater);
+ inOrder.verify(mNotificationUpdater)
+ .onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
+
+ // Verify that onUpstreamCapabilitiesChanged is called if current upstream network
+ // capabilities changed.
+ // Expect that capability is changed with new capability VALIDATED.
+ assertFalse(upstreamState.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
+ upstreamState.networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
+ stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState);
+ inOrder.verify(mNotificationUpdater)
+ .onUpstreamCapabilitiesChanged(upstreamState.networkCapabilities);
// Verify that onUpstreamCapabilitiesChanged won't be called if not current upstream network
// capabilities changed.
@@ -2691,7 +2736,28 @@
upstreamState.linkProperties, upstreamState.networkCapabilities,
new Network(WIFI_NETID));
stateMachine.handleUpstreamNetworkMonitorCallback(EVENT_ON_CAPABILITIES, upstreamState2);
- verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any());
+ inOrder.verify(mNotificationUpdater, never()).onUpstreamCapabilitiesChanged(any());
+ }
+
+ @Test
+ public void testUpstreamCapabilitiesChanged_startStopTethering() throws Exception {
+ final TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+
+ // Start USB tethering with no current upstream.
+ prepareUsbTethering();
+ sendUsbBroadcast(true, true, TETHER_USB_RNDIS_FUNCTION);
+
+ // Pretend wifi connected and expect the upstream to be set.
+ wifi.fakeConnect();
+ mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
+ mLooper.dispatchAll();
+ verify(mNotificationUpdater).onUpstreamCapabilitiesChanged(
+ wifi.networkCapabilities);
+
+ // Stop tethering.
+ // Expect that TetherModeAliveState#exit sends capabilities change notification to null.
+ runStopUSBTethering();
+ verify(mNotificationUpdater).onUpstreamCapabilitiesChanged(null);
}
@Test
@@ -3300,6 +3366,7 @@
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
any(), any());
verify(mTetheringMetrics).createBuilder(eq(TETHERING_NCM), anyString());
+ verify(mTetheringMetrics, times(1)).maybeUpdateUpstreamType(any());
// Change the USB tethering function to NCM. Because the USB tethering function was set to
// RNDIS (the default), tethering is stopped.
@@ -3316,6 +3383,7 @@
mLooper.dispatchAll();
ncmResult.assertHasResult();
verify(mTetheringMetrics, times(2)).createBuilder(eq(TETHERING_NCM), anyString());
+ verify(mTetheringMetrics, times(1)).maybeUpdateUpstreamType(any());
verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_NCM),
eq(TETHER_ERROR_SERVICE_UNAVAIL));
verify(mTetheringMetrics, times(2)).sendReport(eq(TETHERING_NCM));
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java
index 7fdde97..77950ac 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java
@@ -16,6 +16,12 @@
package com.android.networkstack.tethering.metrics;
+import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_LOWPAN;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_ETHERNET;
import static android.net.TetheringManager.TETHERING_NCM;
@@ -44,15 +50,17 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import android.net.NetworkCapabilities;
import android.stats.connectivity.DownstreamType;
import android.stats.connectivity.ErrorCode;
import android.stats.connectivity.UpstreamType;
import android.stats.connectivity.UserType;
-import android.util.Pair;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.networkstack.tethering.UpstreamNetworkState;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,138 +73,307 @@
private static final String SETTINGS_PKG = "com.android.settings";
private static final String SYSTEMUI_PKG = "com.android.systemui";
private static final String GMS_PKG = "com.google.android.gms";
- private TetheringMetrics mTetheringMetrics;
+ private static final long TEST_START_TIME = 1670395936033L;
+ private static final long SECOND_IN_MILLIS = 1_000L;
+ private TetheringMetrics mTetheringMetrics;
private final NetworkTetheringReported.Builder mStatsBuilder =
NetworkTetheringReported.newBuilder();
+ private long mElapsedRealtime;
+
private class MockTetheringMetrics extends TetheringMetrics {
@Override
- public void write(final NetworkTetheringReported reported) { }
+ public void write(final NetworkTetheringReported reported) {}
+ @Override
+ public long timeNow() {
+ return currentTimeMillis();
+ }
+ }
+
+ private long currentTimeMillis() {
+ return TEST_START_TIME + mElapsedRealtime;
+ }
+
+ private void incrementCurrentTime(final long duration) {
+ mElapsedRealtime += duration;
+ mTetheringMetrics.timeNow();
+ }
+
+ private long getElapsedRealtime() {
+ return mElapsedRealtime;
+ }
+
+ private void clearElapsedRealtime() {
+ mElapsedRealtime = 0;
}
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mTetheringMetrics = spy(new MockTetheringMetrics());
+ mElapsedRealtime = 0L;
}
- private void verifyReport(DownstreamType downstream, ErrorCode error, UserType user)
+ private void verifyReport(final DownstreamType downstream, final ErrorCode error,
+ final UserType user, final UpstreamEvents.Builder upstreamEvents, final long duration)
throws Exception {
final NetworkTetheringReported expectedReport =
mStatsBuilder.setDownstreamType(downstream)
.setUserType(user)
.setUpstreamType(UpstreamType.UT_UNKNOWN)
.setErrorCode(error)
- .setUpstreamEvents(UpstreamEvents.newBuilder())
- .setDurationMillis(0)
+ .setUpstreamEvents(upstreamEvents)
+ .setDurationMillis(duration)
.build();
verify(mTetheringMetrics).write(expectedReport);
}
- private void updateErrorAndSendReport(int downstream, int error) {
+ private void updateErrorAndSendReport(final int downstream, final int error) {
mTetheringMetrics.updateErrorCode(downstream, error);
mTetheringMetrics.sendReport(downstream);
}
- private void runDownstreamTypesTest(final Pair<Integer, DownstreamType>... testPairs)
- throws Exception {
- for (Pair<Integer, DownstreamType> testPair : testPairs) {
- final int type = testPair.first;
- final DownstreamType expectedResult = testPair.second;
-
- mTetheringMetrics.createBuilder(type, TEST_CALLER_PKG);
- updateErrorAndSendReport(type, TETHER_ERROR_NO_ERROR);
- verifyReport(expectedResult, ErrorCode.EC_NO_ERROR, UserType.USER_UNKNOWN);
- reset(mTetheringMetrics);
+ private static NetworkCapabilities buildUpstreamCapabilities(final int[] transports) {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+ for (int type: transports) {
+ nc.addTransportType(type);
}
+ return nc;
+ }
+
+ private static UpstreamNetworkState buildUpstreamState(final int... transports) {
+ return new UpstreamNetworkState(
+ null,
+ buildUpstreamCapabilities(transports),
+ null);
+ }
+
+ private void addUpstreamEvent(UpstreamEvents.Builder upstreamEvents,
+ final UpstreamType expectedResult, final long duration) {
+ UpstreamEvent.Builder upstreamEvent = UpstreamEvent.newBuilder()
+ .setUpstreamType(expectedResult)
+ .setDurationMillis(duration);
+ upstreamEvents.addUpstreamEvent(upstreamEvent);
+ }
+
+ private void runDownstreamTypesTest(final int type, final DownstreamType expectedResult)
+ throws Exception {
+ mTetheringMetrics.createBuilder(type, TEST_CALLER_PKG);
+ final long duration = 2 * SECOND_IN_MILLIS;
+ incrementCurrentTime(duration);
+ UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
+ // Set UpstreamType as NO_NETWORK because the upstream type has not been changed.
+ addUpstreamEvent(upstreamEvents, UpstreamType.UT_NO_NETWORK, duration);
+ updateErrorAndSendReport(type, TETHER_ERROR_NO_ERROR);
+
+ verifyReport(expectedResult, ErrorCode.EC_NO_ERROR, UserType.USER_UNKNOWN,
+ upstreamEvents, getElapsedRealtime());
+ reset(mTetheringMetrics);
+ clearElapsedRealtime();
+ mTetheringMetrics.cleanup();
}
@Test
public void testDownstreamTypes() throws Exception {
- runDownstreamTypesTest(new Pair<>(TETHERING_WIFI, DownstreamType.DS_TETHERING_WIFI),
- new Pair<>(TETHERING_WIFI_P2P, DownstreamType.DS_TETHERING_WIFI_P2P),
- new Pair<>(TETHERING_BLUETOOTH, DownstreamType.DS_TETHERING_BLUETOOTH),
- new Pair<>(TETHERING_USB, DownstreamType.DS_TETHERING_USB),
- new Pair<>(TETHERING_NCM, DownstreamType.DS_TETHERING_NCM),
- new Pair<>(TETHERING_ETHERNET, DownstreamType.DS_TETHERING_ETHERNET));
+ runDownstreamTypesTest(TETHERING_WIFI, DownstreamType.DS_TETHERING_WIFI);
+ runDownstreamTypesTest(TETHERING_WIFI_P2P, DownstreamType.DS_TETHERING_WIFI_P2P);
+ runDownstreamTypesTest(TETHERING_BLUETOOTH, DownstreamType.DS_TETHERING_BLUETOOTH);
+ runDownstreamTypesTest(TETHERING_USB, DownstreamType.DS_TETHERING_USB);
+ runDownstreamTypesTest(TETHERING_NCM, DownstreamType.DS_TETHERING_NCM);
+ runDownstreamTypesTest(TETHERING_ETHERNET, DownstreamType.DS_TETHERING_ETHERNET);
}
- private void runErrorCodesTest(final Pair<Integer, ErrorCode>... testPairs)
+ private void runErrorCodesTest(final int errorCode, final ErrorCode expectedResult)
throws Exception {
- for (Pair<Integer, ErrorCode> testPair : testPairs) {
- final int errorCode = testPair.first;
- final ErrorCode expectedResult = testPair.second;
+ mTetheringMetrics.createBuilder(TETHERING_WIFI, TEST_CALLER_PKG);
+ mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_WIFI));
+ final long duration = 2 * SECOND_IN_MILLIS;
+ incrementCurrentTime(duration);
+ updateErrorAndSendReport(TETHERING_WIFI, errorCode);
- mTetheringMetrics.createBuilder(TETHERING_WIFI, TEST_CALLER_PKG);
- updateErrorAndSendReport(TETHERING_WIFI, errorCode);
- verifyReport(DownstreamType.DS_TETHERING_WIFI, expectedResult, UserType.USER_UNKNOWN);
- reset(mTetheringMetrics);
- }
+ UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
+ addUpstreamEvent(upstreamEvents, UpstreamType.UT_WIFI, duration);
+ verifyReport(DownstreamType.DS_TETHERING_WIFI, expectedResult, UserType.USER_UNKNOWN,
+ upstreamEvents, getElapsedRealtime());
+ reset(mTetheringMetrics);
+ clearElapsedRealtime();
+ mTetheringMetrics.cleanup();
}
@Test
public void testErrorCodes() throws Exception {
- runErrorCodesTest(new Pair<>(TETHER_ERROR_NO_ERROR, ErrorCode.EC_NO_ERROR),
- new Pair<>(TETHER_ERROR_UNKNOWN_IFACE, ErrorCode.EC_UNKNOWN_IFACE),
- new Pair<>(TETHER_ERROR_SERVICE_UNAVAIL, ErrorCode.EC_SERVICE_UNAVAIL),
- new Pair<>(TETHER_ERROR_UNSUPPORTED, ErrorCode.EC_UNSUPPORTED),
- new Pair<>(TETHER_ERROR_UNAVAIL_IFACE, ErrorCode.EC_UNAVAIL_IFACE),
- new Pair<>(TETHER_ERROR_INTERNAL_ERROR, ErrorCode.EC_INTERNAL_ERROR),
- new Pair<>(TETHER_ERROR_TETHER_IFACE_ERROR, ErrorCode.EC_TETHER_IFACE_ERROR),
- new Pair<>(TETHER_ERROR_UNTETHER_IFACE_ERROR, ErrorCode.EC_UNTETHER_IFACE_ERROR),
- new Pair<>(TETHER_ERROR_ENABLE_FORWARDING_ERROR,
- ErrorCode.EC_ENABLE_FORWARDING_ERROR),
- new Pair<>(TETHER_ERROR_DISABLE_FORWARDING_ERROR,
- ErrorCode.EC_DISABLE_FORWARDING_ERROR),
- new Pair<>(TETHER_ERROR_IFACE_CFG_ERROR, ErrorCode.EC_IFACE_CFG_ERROR),
- new Pair<>(TETHER_ERROR_PROVISIONING_FAILED, ErrorCode.EC_PROVISIONING_FAILED),
- new Pair<>(TETHER_ERROR_DHCPSERVER_ERROR, ErrorCode.EC_DHCPSERVER_ERROR),
- new Pair<>(TETHER_ERROR_ENTITLEMENT_UNKNOWN, ErrorCode.EC_ENTITLEMENT_UNKNOWN),
- new Pair<>(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
- ErrorCode.EC_NO_CHANGE_TETHERING_PERMISSION),
- new Pair<>(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION,
- ErrorCode.EC_NO_ACCESS_TETHERING_PERMISSION),
- new Pair<>(TETHER_ERROR_UNKNOWN_TYPE, ErrorCode.EC_UNKNOWN_TYPE));
+ runErrorCodesTest(TETHER_ERROR_NO_ERROR, ErrorCode.EC_NO_ERROR);
+ runErrorCodesTest(TETHER_ERROR_UNKNOWN_IFACE, ErrorCode.EC_UNKNOWN_IFACE);
+ runErrorCodesTest(TETHER_ERROR_SERVICE_UNAVAIL, ErrorCode.EC_SERVICE_UNAVAIL);
+ runErrorCodesTest(TETHER_ERROR_UNSUPPORTED, ErrorCode.EC_UNSUPPORTED);
+ runErrorCodesTest(TETHER_ERROR_UNAVAIL_IFACE, ErrorCode.EC_UNAVAIL_IFACE);
+ runErrorCodesTest(TETHER_ERROR_INTERNAL_ERROR, ErrorCode.EC_INTERNAL_ERROR);
+ runErrorCodesTest(TETHER_ERROR_TETHER_IFACE_ERROR, ErrorCode.EC_TETHER_IFACE_ERROR);
+ runErrorCodesTest(TETHER_ERROR_UNTETHER_IFACE_ERROR, ErrorCode.EC_UNTETHER_IFACE_ERROR);
+ runErrorCodesTest(TETHER_ERROR_ENABLE_FORWARDING_ERROR,
+ ErrorCode.EC_ENABLE_FORWARDING_ERROR);
+ runErrorCodesTest(TETHER_ERROR_DISABLE_FORWARDING_ERROR,
+ ErrorCode.EC_DISABLE_FORWARDING_ERROR);
+ runErrorCodesTest(TETHER_ERROR_IFACE_CFG_ERROR, ErrorCode.EC_IFACE_CFG_ERROR);
+ runErrorCodesTest(TETHER_ERROR_PROVISIONING_FAILED, ErrorCode.EC_PROVISIONING_FAILED);
+ runErrorCodesTest(TETHER_ERROR_DHCPSERVER_ERROR, ErrorCode.EC_DHCPSERVER_ERROR);
+ runErrorCodesTest(TETHER_ERROR_ENTITLEMENT_UNKNOWN, ErrorCode.EC_ENTITLEMENT_UNKNOWN);
+ runErrorCodesTest(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
+ ErrorCode.EC_NO_CHANGE_TETHERING_PERMISSION);
+ runErrorCodesTest(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION,
+ ErrorCode.EC_NO_ACCESS_TETHERING_PERMISSION);
+ runErrorCodesTest(TETHER_ERROR_UNKNOWN_TYPE, ErrorCode.EC_UNKNOWN_TYPE);
}
- private void runUserTypesTest(final Pair<String, UserType>... testPairs)
+ private void runUserTypesTest(final String callerPkg, final UserType expectedResult)
throws Exception {
- for (Pair<String, UserType> testPair : testPairs) {
- final String callerPkg = testPair.first;
- final UserType expectedResult = testPair.second;
+ mTetheringMetrics.createBuilder(TETHERING_WIFI, callerPkg);
+ final long duration = 1 * SECOND_IN_MILLIS;
+ incrementCurrentTime(duration);
+ updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
- mTetheringMetrics.createBuilder(TETHERING_WIFI, callerPkg);
- updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
- verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR, expectedResult);
- reset(mTetheringMetrics);
- }
+ UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
+ // Set UpstreamType as NO_NETWORK because the upstream type has not been changed.
+ addUpstreamEvent(upstreamEvents, UpstreamType.UT_NO_NETWORK, duration);
+ verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR, expectedResult,
+ upstreamEvents, getElapsedRealtime());
+ reset(mTetheringMetrics);
+ clearElapsedRealtime();
+ mTetheringMetrics.cleanup();
}
@Test
public void testUserTypes() throws Exception {
- runUserTypesTest(new Pair<>(TEST_CALLER_PKG, UserType.USER_UNKNOWN),
- new Pair<>(SETTINGS_PKG, UserType.USER_SETTINGS),
- new Pair<>(SYSTEMUI_PKG, UserType.USER_SYSTEMUI),
- new Pair<>(GMS_PKG, UserType.USER_GMS));
+ runUserTypesTest(TEST_CALLER_PKG, UserType.USER_UNKNOWN);
+ runUserTypesTest(SETTINGS_PKG, UserType.USER_SETTINGS);
+ runUserTypesTest(SYSTEMUI_PKG, UserType.USER_SYSTEMUI);
+ runUserTypesTest(GMS_PKG, UserType.USER_GMS);
+ }
+
+ private void runUpstreamTypesTest(final UpstreamNetworkState ns,
+ final UpstreamType expectedResult) throws Exception {
+ mTetheringMetrics.createBuilder(TETHERING_WIFI, TEST_CALLER_PKG);
+ mTetheringMetrics.maybeUpdateUpstreamType(ns);
+ final long duration = 2 * SECOND_IN_MILLIS;
+ incrementCurrentTime(duration);
+ updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
+
+ UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
+ addUpstreamEvent(upstreamEvents, expectedResult, duration);
+ verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR,
+ UserType.USER_UNKNOWN, upstreamEvents, getElapsedRealtime());
+ reset(mTetheringMetrics);
+ clearElapsedRealtime();
+ mTetheringMetrics.cleanup();
+ }
+
+ @Test
+ public void testUpstreamTypes() throws Exception {
+ runUpstreamTypesTest(null , UpstreamType.UT_NO_NETWORK);
+ runUpstreamTypesTest(buildUpstreamState(TRANSPORT_CELLULAR), UpstreamType.UT_CELLULAR);
+ runUpstreamTypesTest(buildUpstreamState(TRANSPORT_WIFI), UpstreamType.UT_WIFI);
+ runUpstreamTypesTest(buildUpstreamState(TRANSPORT_BLUETOOTH), UpstreamType.UT_BLUETOOTH);
+ runUpstreamTypesTest(buildUpstreamState(TRANSPORT_ETHERNET), UpstreamType.UT_ETHERNET);
+ runUpstreamTypesTest(buildUpstreamState(TRANSPORT_WIFI_AWARE), UpstreamType.UT_WIFI_AWARE);
+ runUpstreamTypesTest(buildUpstreamState(TRANSPORT_LOWPAN), UpstreamType.UT_LOWPAN);
+ runUpstreamTypesTest(buildUpstreamState(TRANSPORT_CELLULAR, TRANSPORT_WIFI,
+ TRANSPORT_BLUETOOTH), UpstreamType.UT_UNKNOWN);
}
@Test
public void testMultiBuildersCreatedBeforeSendReport() throws Exception {
mTetheringMetrics.createBuilder(TETHERING_WIFI, SETTINGS_PKG);
+ final long wifiTetheringStartTime = currentTimeMillis();
+ incrementCurrentTime(1 * SECOND_IN_MILLIS);
mTetheringMetrics.createBuilder(TETHERING_USB, SYSTEMUI_PKG);
+ final long usbTetheringStartTime = currentTimeMillis();
+ incrementCurrentTime(2 * SECOND_IN_MILLIS);
mTetheringMetrics.createBuilder(TETHERING_BLUETOOTH, GMS_PKG);
-
+ final long bluetoothTetheringStartTime = currentTimeMillis();
+ incrementCurrentTime(3 * SECOND_IN_MILLIS);
updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_DHCPSERVER_ERROR);
+
+ UpstreamEvents.Builder wifiTetheringUpstreamEvents = UpstreamEvents.newBuilder();
+ addUpstreamEvent(wifiTetheringUpstreamEvents, UpstreamType.UT_NO_NETWORK,
+ currentTimeMillis() - wifiTetheringStartTime);
verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_DHCPSERVER_ERROR,
- UserType.USER_SETTINGS);
-
+ UserType.USER_SETTINGS, wifiTetheringUpstreamEvents,
+ currentTimeMillis() - wifiTetheringStartTime);
+ incrementCurrentTime(1 * SECOND_IN_MILLIS);
updateErrorAndSendReport(TETHERING_USB, TETHER_ERROR_ENABLE_FORWARDING_ERROR);
- verifyReport(DownstreamType.DS_TETHERING_USB, ErrorCode.EC_ENABLE_FORWARDING_ERROR,
- UserType.USER_SYSTEMUI);
+ UpstreamEvents.Builder usbTetheringUpstreamEvents = UpstreamEvents.newBuilder();
+ addUpstreamEvent(usbTetheringUpstreamEvents, UpstreamType.UT_NO_NETWORK,
+ currentTimeMillis() - usbTetheringStartTime);
+
+ verifyReport(DownstreamType.DS_TETHERING_USB, ErrorCode.EC_ENABLE_FORWARDING_ERROR,
+ UserType.USER_SYSTEMUI, usbTetheringUpstreamEvents,
+ currentTimeMillis() - usbTetheringStartTime);
+ incrementCurrentTime(1 * SECOND_IN_MILLIS);
updateErrorAndSendReport(TETHERING_BLUETOOTH, TETHER_ERROR_TETHER_IFACE_ERROR);
+
+ UpstreamEvents.Builder bluetoothTetheringUpstreamEvents = UpstreamEvents.newBuilder();
+ addUpstreamEvent(bluetoothTetheringUpstreamEvents, UpstreamType.UT_NO_NETWORK,
+ currentTimeMillis() - bluetoothTetheringStartTime);
verifyReport(DownstreamType.DS_TETHERING_BLUETOOTH, ErrorCode.EC_TETHER_IFACE_ERROR,
- UserType.USER_GMS);
+ UserType.USER_GMS, bluetoothTetheringUpstreamEvents,
+ currentTimeMillis() - bluetoothTetheringStartTime);
+ }
+
+ @Test
+ public void testUpstreamsWithMultipleDownstreams() throws Exception {
+ mTetheringMetrics.createBuilder(TETHERING_WIFI, SETTINGS_PKG);
+ final long wifiTetheringStartTime = currentTimeMillis();
+ incrementCurrentTime(1 * SECOND_IN_MILLIS);
+ mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_WIFI));
+ final long wifiUpstreamStartTime = currentTimeMillis();
+ incrementCurrentTime(5 * SECOND_IN_MILLIS);
+ mTetheringMetrics.createBuilder(TETHERING_USB, SYSTEMUI_PKG);
+ final long usbTetheringStartTime = currentTimeMillis();
+ incrementCurrentTime(5 * SECOND_IN_MILLIS);
+ updateErrorAndSendReport(TETHERING_USB, TETHER_ERROR_NO_ERROR);
+
+ UpstreamEvents.Builder usbTetheringUpstreamEvents = UpstreamEvents.newBuilder();
+ addUpstreamEvent(usbTetheringUpstreamEvents, UpstreamType.UT_WIFI,
+ currentTimeMillis() - usbTetheringStartTime);
+ verifyReport(DownstreamType.DS_TETHERING_USB, ErrorCode.EC_NO_ERROR,
+ UserType.USER_SYSTEMUI, usbTetheringUpstreamEvents,
+ currentTimeMillis() - usbTetheringStartTime);
+ incrementCurrentTime(7 * SECOND_IN_MILLIS);
+ updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
+
+ UpstreamEvents.Builder wifiTetheringUpstreamEvents = UpstreamEvents.newBuilder();
+ addUpstreamEvent(wifiTetheringUpstreamEvents, UpstreamType.UT_WIFI,
+ currentTimeMillis() - wifiUpstreamStartTime);
+ verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR,
+ UserType.USER_SETTINGS, wifiTetheringUpstreamEvents,
+ currentTimeMillis() - wifiTetheringStartTime);
+ }
+
+ @Test
+ public void testSwitchingMultiUpstreams() throws Exception {
+ mTetheringMetrics.createBuilder(TETHERING_WIFI, SETTINGS_PKG);
+ final long wifiTetheringStartTime = currentTimeMillis();
+ incrementCurrentTime(1 * SECOND_IN_MILLIS);
+ mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_WIFI));
+ final long wifiDuration = 5 * SECOND_IN_MILLIS;
+ incrementCurrentTime(wifiDuration);
+ mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_BLUETOOTH));
+ final long bluetoothDuration = 15 * SECOND_IN_MILLIS;
+ incrementCurrentTime(bluetoothDuration);
+ mTetheringMetrics.maybeUpdateUpstreamType(buildUpstreamState(TRANSPORT_CELLULAR));
+ final long celltoothDuration = 20 * SECOND_IN_MILLIS;
+ incrementCurrentTime(celltoothDuration);
+ updateErrorAndSendReport(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
+
+ UpstreamEvents.Builder upstreamEvents = UpstreamEvents.newBuilder();
+ addUpstreamEvent(upstreamEvents, UpstreamType.UT_WIFI, wifiDuration);
+ addUpstreamEvent(upstreamEvents, UpstreamType.UT_BLUETOOTH, bluetoothDuration);
+ addUpstreamEvent(upstreamEvents, UpstreamType.UT_CELLULAR, celltoothDuration);
+
+ verifyReport(DownstreamType.DS_TETHERING_WIFI, ErrorCode.EC_NO_ERROR,
+ UserType.USER_SETTINGS, upstreamEvents,
+ currentTimeMillis() - wifiTetheringStartTime);
}
}
diff --git a/bpf_progs/bpf_net_helpers.h b/bpf_progs/bpf_net_helpers.h
index b7ca3af..ed33cc9 100644
--- a/bpf_progs/bpf_net_helpers.h
+++ b/bpf_progs/bpf_net_helpers.h
@@ -86,3 +86,30 @@
if (len > skb->len) len = skb->len;
if (skb->data_end - skb->data < len) bpf_skb_pull_data(skb, len);
}
+
+// constants for passing in to 'bool egress'
+static const bool INGRESS = false;
+static const bool EGRESS = true;
+
+// constants for passing in to 'bool downstream'
+static const bool UPSTREAM = false;
+static const bool DOWNSTREAM = true;
+
+// constants for passing in to 'bool is_ethernet'
+static const bool RAWIP = false;
+static const bool ETHER = true;
+
+// constants for passing in to 'bool updatetime'
+static const bool NO_UPDATETIME = false;
+static const bool UPDATETIME = true;
+
+// constants for passing in to ignore_on_eng / ignore_on_user / ignore_on_userdebug
+// define's instead of static const due to tm-mainline-prod compiler static_assert limitations
+#define LOAD_ON_ENG false
+#define LOAD_ON_USER false
+#define LOAD_ON_USERDEBUG false
+#define IGNORE_ON_ENG true
+#define IGNORE_ON_USER true
+#define IGNORE_ON_USERDEBUG true
+
+#define KVER_4_14 KVER(4, 14, 0)
diff --git a/bpf_progs/clatd.c b/bpf_progs/clatd.c
index 7350209..f05b93e 100644
--- a/bpf_progs/clatd.c
+++ b/bpf_progs/clatd.c
@@ -52,12 +52,6 @@
__be32 identification;
};
-// constants for passing in to 'bool is_ethernet'
-static const bool RAWIP = false;
-static const bool ETHER = true;
-
-#define KVER_4_14 KVER(4, 14, 0)
-
DEFINE_BPF_MAP_GRW(clat_ingress6_map, HASH, ClatIngress6Key, ClatIngress6Value, 16, AID_SYSTEM)
static inline __always_inline int nat64(struct __sk_buff* skb,
@@ -91,6 +85,12 @@
if (ip6->version != 6) return TC_ACT_PIPE;
// Maximum IPv6 payload length that can be translated to IPv4
+ // Note: technically this check is too strict for an IPv6 fragment,
+ // which by virtue of stripping the extra 8 byte fragment extension header,
+ // could thus be 8 bytes larger and still fit in an ipv4 packet post
+ // translation. However... who ever heard of receiving ~64KB frags...
+ // fragments are kind of by definition smaller than ingress device mtu,
+ // and thus, on the internet, very very unlikely to exceed 1500 bytes.
if (ntohs(ip6->payload_len) > 0xFFFF - sizeof(struct iphdr)) return TC_ACT_PIPE;
ClatIngress6Key k = {
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index 84da79d..39dff7f 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -42,10 +42,6 @@
static const int BPF_NOMATCH = 0;
static const int BPF_MATCH = 1;
-// Used for 'bool egress'
-static const bool INGRESS = false;
-static const bool EGRESS = true;
-
// Used for 'bool enable_tracing'
static const bool TRACE_ON = true;
static const bool TRACE_OFF = false;
@@ -64,15 +60,15 @@
#define DEFINE_BPF_MAP_NO_NETD(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \
DEFINE_BPF_MAP_EXT(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, \
AID_ROOT, AID_NET_BW_ACCT, 0060, "fs_bpf_net_shared", "", false, \
- BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, /*ignore_on_eng*/false, \
- /*ignore_on_user*/false, /*ignore_on_userdebug*/false)
+ BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, LOAD_ON_ENG, \
+ LOAD_ON_USER, LOAD_ON_USERDEBUG)
// For maps netd only needs read only access to
#define DEFINE_BPF_MAP_RO_NETD(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \
DEFINE_BPF_MAP_EXT(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, \
AID_ROOT, AID_NET_BW_ACCT, 0460, "fs_bpf_netd_readonly", "", false, \
- BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, /*ignore_on_eng*/false, \
- /*ignore_on_user*/false, /*ignore_on_userdebug*/false)
+ BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, LOAD_ON_ENG, \
+ LOAD_ON_USER, LOAD_ON_USERDEBUG)
// For maps netd needs to be able to read and write
#define DEFINE_BPF_MAP_RW_NETD(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \
@@ -103,15 +99,15 @@
// A single-element configuration array, packet tracing is enabled when 'true'.
DEFINE_BPF_MAP_EXT(packet_trace_enabled_map, ARRAY, uint32_t, bool, 1,
AID_ROOT, AID_SYSTEM, 0060, "fs_bpf_net_shared", "", false,
- BPFLOADER_IGNORED_ON_VERSION, BPFLOADER_MAX_VER, /*ignore_on_eng*/false,
- /*ignore_on_user*/true, /*ignore_on_userdebug*/false)
+ BPFLOADER_IGNORED_ON_VERSION, BPFLOADER_MAX_VER, LOAD_ON_ENG,
+ IGNORE_ON_USER, LOAD_ON_USERDEBUG)
// A ring buffer on which packet information is pushed. This map will only be loaded
// on eng and userdebug devices. User devices won't load this to save memory.
DEFINE_BPF_RINGBUF_EXT(packet_trace_ringbuf, PacketTrace, PACKET_TRACE_BUF_SIZE,
AID_ROOT, AID_SYSTEM, 0060, "fs_bpf_net_shared", "", false,
- BPFLOADER_IGNORED_ON_VERSION, BPFLOADER_MAX_VER, /*ignore_on_eng*/false,
- /*ignore_on_user*/true, /*ignore_on_userdebug*/false);
+ BPFLOADER_IGNORED_ON_VERSION, BPFLOADER_MAX_VER, LOAD_ON_ENG,
+ IGNORE_ON_USER, LOAD_ON_USERDEBUG);
// iptables xt_bpf programs need to be usable by both netd and netutils_wrappers
// selinux contexts, because even non-xt_bpf iptables mutations are implemented as
@@ -176,36 +172,38 @@
* Especially since the number of packets is important for any future clat offload correction.
* (which adjusts upward by 20 bytes per packet to account for ipv4 -> ipv6 header conversion)
*/
-#define DEFINE_UPDATE_STATS(the_stats_map, TypeOfKey) \
- static __always_inline inline void update_##the_stats_map(struct __sk_buff* skb, \
- bool egress, TypeOfKey* key) { \
- StatsValue* value = bpf_##the_stats_map##_lookup_elem(key); \
- if (!value) { \
- StatsValue newValue = {}; \
- bpf_##the_stats_map##_update_elem(key, &newValue, BPF_NOEXIST); \
- value = bpf_##the_stats_map##_lookup_elem(key); \
- } \
- if (value) { \
- const int mtu = 1500; \
- uint64_t packets = 1; \
- uint64_t bytes = skb->len; \
- if (bytes > mtu) { \
- bool is_ipv6 = (skb->protocol == htons(ETH_P_IPV6)); \
- int ip_overhead = (is_ipv6 ? sizeof(struct ipv6hdr) : sizeof(struct iphdr)); \
- int tcp_overhead = ip_overhead + sizeof(struct tcphdr) + 12; \
- int mss = mtu - tcp_overhead; \
- uint64_t payload = bytes - tcp_overhead; \
- packets = (payload + mss - 1) / mss; \
- bytes = tcp_overhead * packets + payload; \
- } \
- if (egress) { \
- __sync_fetch_and_add(&value->txPackets, packets); \
- __sync_fetch_and_add(&value->txBytes, bytes); \
- } else { \
- __sync_fetch_and_add(&value->rxPackets, packets); \
- __sync_fetch_and_add(&value->rxBytes, bytes); \
- } \
- } \
+#define DEFINE_UPDATE_STATS(the_stats_map, TypeOfKey) \
+ static __always_inline inline void update_##the_stats_map(const struct __sk_buff* const skb, \
+ const TypeOfKey* const key, \
+ const bool egress, \
+ const unsigned kver) { \
+ StatsValue* value = bpf_##the_stats_map##_lookup_elem(key); \
+ if (!value) { \
+ StatsValue newValue = {}; \
+ bpf_##the_stats_map##_update_elem(key, &newValue, BPF_NOEXIST); \
+ value = bpf_##the_stats_map##_lookup_elem(key); \
+ } \
+ if (value) { \
+ const int mtu = 1500; \
+ uint64_t packets = 1; \
+ uint64_t bytes = skb->len; \
+ if (bytes > mtu) { \
+ bool is_ipv6 = (skb->protocol == htons(ETH_P_IPV6)); \
+ int ip_overhead = (is_ipv6 ? sizeof(struct ipv6hdr) : sizeof(struct iphdr)); \
+ int tcp_overhead = ip_overhead + sizeof(struct tcphdr) + 12; \
+ int mss = mtu - tcp_overhead; \
+ uint64_t payload = bytes - tcp_overhead; \
+ packets = (payload + mss - 1) / mss; \
+ bytes = tcp_overhead * packets + payload; \
+ } \
+ if (egress) { \
+ __sync_fetch_and_add(&value->txPackets, packets); \
+ __sync_fetch_and_add(&value->txBytes, bytes); \
+ } else { \
+ __sync_fetch_and_add(&value->rxPackets, packets); \
+ __sync_fetch_and_add(&value->rxBytes, bytes); \
+ } \
+ } \
}
DEFINE_UPDATE_STATS(app_uid_stats_map, uint32_t)
@@ -300,7 +298,8 @@
bpf_packet_trace_ringbuf_submit(pkt);
}
-static __always_inline inline bool skip_owner_match(struct __sk_buff* skb, const unsigned kver) {
+static __always_inline inline bool skip_owner_match(struct __sk_buff* skb, bool egress,
+ const unsigned kver) {
uint32_t flag = 0;
if (skb->protocol == htons(ETH_P_IP)) {
uint8_t proto;
@@ -330,7 +329,8 @@
} else {
return false;
}
- return flag & TCP_FLAG_RST; // false on read failure
+ // Always allow RST's, and additionally allow ingress FINs
+ return flag & (TCP_FLAG_RST | (egress ? 0 : TCP_FLAG_FIN)); // false on read failure
}
static __always_inline inline BpfConfig getConfig(uint32_t configKey) {
@@ -350,10 +350,10 @@
static __always_inline inline int bpf_owner_match(struct __sk_buff* skb, uint32_t uid,
bool egress, const unsigned kver) {
- if (skip_owner_match(skb, kver)) return PASS;
-
if (is_system_uid(uid)) return PASS;
+ if (skip_owner_match(skb, egress, kver)) return PASS;
+
BpfConfig enabledRules = getConfig(UID_RULES_CONFIGURATION_KEY);
UidOwnerValue* uidEntry = bpf_uid_owner_map_lookup_elem(&uid);
@@ -383,12 +383,15 @@
return PASS;
}
-static __always_inline inline void update_stats_with_config(struct __sk_buff* skb, bool egress,
- StatsKey* key, uint32_t selectedMap) {
+static __always_inline inline void update_stats_with_config(const uint32_t selectedMap,
+ const struct __sk_buff* const skb,
+ const StatsKey* const key,
+ const bool egress,
+ const unsigned kver) {
if (selectedMap == SELECT_MAP_A) {
- update_stats_map_A(skb, egress, key);
+ update_stats_map_A(skb, key, egress, kver);
} else {
- update_stats_map_B(skb, egress, key);
+ update_stats_map_B(skb, key, egress, kver);
}
}
@@ -415,11 +418,6 @@
}
int match = bpf_owner_match(skb, sock_uid, egress, kver);
- if (egress && (match == DROP)) {
- // If an outbound packet is going to be dropped, we do not count that
- // traffic.
- return match;
- }
// Workaround for secureVPN with VpnIsolation enabled, refer to b/159994981 for details.
// Keep TAG_SYSTEM_DNS in sync with DnsResolver/include/netd_resolv/resolv.h
@@ -432,6 +430,9 @@
if (match == DROP_UNLESS_DNS) match = DROP;
}
+ // If an outbound packet is going to be dropped, we do not count that traffic.
+ if (egress && (match == DROP)) return DROP;
+
StatsKey key = {.uid = uid, .tag = tag, .counterSet = 0, .ifaceIndex = skb->ifindex};
uint8_t* counterSet = bpf_uid_counterset_map_lookup_elem(&uid);
@@ -448,14 +449,9 @@
return match;
}
- if (key.tag) {
- update_stats_with_config(skb, egress, &key, *selectedMap);
- key.tag = 0;
- }
-
do_packet_tracing(skb, egress, uid, tag, enable_tracing, kver);
- update_stats_with_config(skb, egress, &key, *selectedMap);
- update_app_uid_stats_map(skb, egress, &uid);
+ update_stats_with_config(*selectedMap, skb, &key, egress, kver);
+ update_app_uid_stats_map(skb, &uid, egress, kver);
asm("%0 &= 1" : "+r"(match));
return match;
}
@@ -516,7 +512,7 @@
}
uint32_t key = skb->ifindex;
- update_iface_stats_map(skb, EGRESS, &key);
+ update_iface_stats_map(skb, &key, EGRESS, KVER_NONE);
return BPF_MATCH;
}
@@ -529,7 +525,7 @@
// Keep that in mind when moving this out of iptables xt_bpf and into tc ingress (or xdp).
uint32_t key = skb->ifindex;
- update_iface_stats_map(skb, INGRESS, &key);
+ update_iface_stats_map(skb, &key, INGRESS, KVER_NONE);
return BPF_MATCH;
}
@@ -539,7 +535,7 @@
if (is_received_skb(skb)) {
// Account for ingress traffic before tc drops it.
uint32_t key = skb->ifindex;
- update_iface_stats_map(skb, INGRESS, &key);
+ update_iface_stats_map(skb, &key, INGRESS, KVER_NONE);
}
return TC_ACT_UNSPEC;
}
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index a8612df..f4d4254 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -131,7 +131,7 @@
TETHERING_GID)
static inline __always_inline int do_forward6(struct __sk_buff* skb, const bool is_ethernet,
- const bool downstream) {
+ const bool downstream, const unsigned kver) {
// Must be meta-ethernet IPv6 frame
if (skb->protocol != htons(ETH_P_IPV6)) return TC_ACT_PIPE;
@@ -232,13 +232,13 @@
// This would require a much newer kernel with newer ebpf accessors.
// (This is also blindly assuming 12 bytes of tcp timestamp option in tcp header)
uint64_t packets = 1;
- uint64_t bytes = skb->len;
- if (bytes > v->pmtu) {
- const int tcp_overhead = sizeof(struct ipv6hdr) + sizeof(struct tcphdr) + 12;
- const int mss = v->pmtu - tcp_overhead;
- const uint64_t payload = bytes - tcp_overhead;
+ uint64_t L3_bytes = skb->len - l2_header_size;
+ if (L3_bytes > v->pmtu) {
+ const int tcp6_overhead = sizeof(struct ipv6hdr) + sizeof(struct tcphdr) + 12;
+ const int mss = v->pmtu - tcp6_overhead;
+ const uint64_t payload = L3_bytes - tcp6_overhead;
packets = (payload + mss - 1) / mss;
- bytes = tcp_overhead * packets + payload;
+ L3_bytes = tcp6_overhead * packets + payload;
}
// Are we past the limit? If so, then abort...
@@ -247,7 +247,7 @@
// a packet we let the core stack deal with things.
// (The core stack needs to handle limits correctly anyway,
// since we don't offload all traffic in both directions)
- if (stat_v->rxBytes + stat_v->txBytes + bytes > *limit_v) TC_PUNT(LIMIT_REACHED);
+ if (stat_v->rxBytes + stat_v->txBytes + L3_bytes > *limit_v) TC_PUNT(LIMIT_REACHED);
if (!is_ethernet) {
// Try to inject an ethernet header, and simply return if we fail.
@@ -287,7 +287,7 @@
bpf_csum_update(skb, 0xFFFF - ntohs(old_hl) + ntohs(new_hl));
__sync_fetch_and_add(downstream ? &stat_v->rxPackets : &stat_v->txPackets, packets);
- __sync_fetch_and_add(downstream ? &stat_v->rxBytes : &stat_v->txBytes, bytes);
+ __sync_fetch_and_add(downstream ? &stat_v->rxBytes : &stat_v->txBytes, L3_bytes);
// Overwrite any mac header with the new one
// For a rawip tx interface it will simply be a bunch of zeroes and later stripped.
@@ -305,13 +305,13 @@
DEFINE_BPF_PROG("schedcls/tether_downstream6_ether", TETHERING_UID, TETHERING_GID,
sched_cls_tether_downstream6_ether)
(struct __sk_buff* skb) {
- return do_forward6(skb, /* is_ethernet */ true, /* downstream */ true);
+ return do_forward6(skb, ETHER, DOWNSTREAM, KVER_NONE);
}
DEFINE_BPF_PROG("schedcls/tether_upstream6_ether", TETHERING_UID, TETHERING_GID,
sched_cls_tether_upstream6_ether)
(struct __sk_buff* skb) {
- return do_forward6(skb, /* is_ethernet */ true, /* downstream */ false);
+ return do_forward6(skb, ETHER, UPSTREAM, KVER_NONE);
}
// Note: section names must be unique to prevent programs from appending to each other,
@@ -331,13 +331,13 @@
DEFINE_BPF_PROG_KVER("schedcls/tether_downstream6_rawip$4_14", TETHERING_UID, TETHERING_GID,
sched_cls_tether_downstream6_rawip_4_14, KVER(4, 14, 0))
(struct __sk_buff* skb) {
- return do_forward6(skb, /* is_ethernet */ false, /* downstream */ true);
+ return do_forward6(skb, RAWIP, DOWNSTREAM, KVER(4, 14, 0));
}
DEFINE_BPF_PROG_KVER("schedcls/tether_upstream6_rawip$4_14", TETHERING_UID, TETHERING_GID,
sched_cls_tether_upstream6_rawip_4_14, KVER(4, 14, 0))
(struct __sk_buff* skb) {
- return do_forward6(skb, /* is_ethernet */ false, /* downstream */ false);
+ return do_forward6(skb, RAWIP, UPSTREAM, KVER(4, 14, 0));
}
// and define no-op stubs for pre-4.14 kernels.
@@ -362,7 +362,8 @@
static inline __always_inline int do_forward4_bottom(struct __sk_buff* skb,
const int l2_header_size, void* data, const void* data_end,
struct ethhdr* eth, struct iphdr* ip, const bool is_ethernet,
- const bool downstream, const bool updatetime, const bool is_tcp) {
+ const bool downstream, const bool updatetime, const bool is_tcp,
+ const unsigned kver) {
struct tcphdr* tcph = is_tcp ? (void*)(ip + 1) : NULL;
struct udphdr* udph = is_tcp ? NULL : (void*)(ip + 1);
@@ -449,13 +450,13 @@
// This would require a much newer kernel with newer ebpf accessors.
// (This is also blindly assuming 12 bytes of tcp timestamp option in tcp header)
uint64_t packets = 1;
- uint64_t bytes = skb->len;
- if (bytes > v->pmtu) {
- const int tcp_overhead = sizeof(struct iphdr) + sizeof(struct tcphdr) + 12;
- const int mss = v->pmtu - tcp_overhead;
- const uint64_t payload = bytes - tcp_overhead;
+ uint64_t L3_bytes = skb->len - l2_header_size;
+ if (L3_bytes > v->pmtu) {
+ const int tcp4_overhead = sizeof(struct iphdr) + sizeof(struct tcphdr) + 12;
+ const int mss = v->pmtu - tcp4_overhead;
+ const uint64_t payload = L3_bytes - tcp4_overhead;
packets = (payload + mss - 1) / mss;
- bytes = tcp_overhead * packets + payload;
+ L3_bytes = tcp4_overhead * packets + payload;
}
// Are we past the limit? If so, then abort...
@@ -464,7 +465,7 @@
// a packet we let the core stack deal with things.
// (The core stack needs to handle limits correctly anyway,
// since we don't offload all traffic in both directions)
- if (stat_v->rxBytes + stat_v->txBytes + bytes > *limit_v) TC_PUNT(LIMIT_REACHED);
+ if (stat_v->rxBytes + stat_v->txBytes + L3_bytes > *limit_v) TC_PUNT(LIMIT_REACHED);
if (!is_ethernet) {
// Try to inject an ethernet header, and simply return if we fail.
@@ -540,7 +541,7 @@
if (updatetime) v->last_used = bpf_ktime_get_boot_ns();
__sync_fetch_and_add(downstream ? &stat_v->rxPackets : &stat_v->txPackets, packets);
- __sync_fetch_and_add(downstream ? &stat_v->rxBytes : &stat_v->txBytes, bytes);
+ __sync_fetch_and_add(downstream ? &stat_v->rxBytes : &stat_v->txBytes, L3_bytes);
// Redirect to forwarded interface.
//
@@ -552,7 +553,7 @@
}
static inline __always_inline int do_forward4(struct __sk_buff* skb, const bool is_ethernet,
- const bool downstream, const bool updatetime) {
+ const bool downstream, const bool updatetime, const unsigned kver) {
// Require ethernet dst mac address to be our unicast address.
if (is_ethernet && (skb->pkt_type != PACKET_HOST)) return TC_ACT_PIPE;
@@ -640,10 +641,10 @@
// if the underlying requisite kernel support (bpf_ktime_get_boot_ns) was backported.
if (is_tcp) {
return do_forward4_bottom(skb, l2_header_size, data, data_end, eth, ip,
- is_ethernet, downstream, updatetime, /* is_tcp */ true);
+ is_ethernet, downstream, updatetime, /* is_tcp */ true, kver);
} else {
return do_forward4_bottom(skb, l2_header_size, data, data_end, eth, ip,
- is_ethernet, downstream, updatetime, /* is_tcp */ false);
+ is_ethernet, downstream, updatetime, /* is_tcp */ false, kver);
}
}
@@ -652,25 +653,25 @@
DEFINE_BPF_PROG_KVER("schedcls/tether_downstream4_rawip$5_8", TETHERING_UID, TETHERING_GID,
sched_cls_tether_downstream4_rawip_5_8, KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ false, /* downstream */ true, /* updatetime */ true);
+ return do_forward4(skb, RAWIP, DOWNSTREAM, UPDATETIME, KVER(5, 8, 0));
}
DEFINE_BPF_PROG_KVER("schedcls/tether_upstream4_rawip$5_8", TETHERING_UID, TETHERING_GID,
sched_cls_tether_upstream4_rawip_5_8, KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ false, /* downstream */ false, /* updatetime */ true);
+ return do_forward4(skb, RAWIP, UPSTREAM, UPDATETIME, KVER(5, 8, 0));
}
DEFINE_BPF_PROG_KVER("schedcls/tether_downstream4_ether$5_8", TETHERING_UID, TETHERING_GID,
sched_cls_tether_downstream4_ether_5_8, KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ true, /* downstream */ true, /* updatetime */ true);
+ return do_forward4(skb, ETHER, DOWNSTREAM, UPDATETIME, KVER(5, 8, 0));
}
DEFINE_BPF_PROG_KVER("schedcls/tether_upstream4_ether$5_8", TETHERING_UID, TETHERING_GID,
sched_cls_tether_upstream4_ether_5_8, KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ true, /* downstream */ false, /* updatetime */ true);
+ return do_forward4(skb, ETHER, UPSTREAM, UPDATETIME, KVER(5, 8, 0));
}
// Full featured (optional) implementations for 4.14-S, 4.19-S & 5.4-S kernels
@@ -681,7 +682,7 @@
sched_cls_tether_downstream4_rawip_opt,
KVER(4, 14, 0), KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ false, /* downstream */ true, /* updatetime */ true);
+ return do_forward4(skb, RAWIP, DOWNSTREAM, UPDATETIME, KVER(4, 14, 0));
}
DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_rawip$opt",
@@ -689,7 +690,7 @@
sched_cls_tether_upstream4_rawip_opt,
KVER(4, 14, 0), KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ false, /* downstream */ false, /* updatetime */ true);
+ return do_forward4(skb, RAWIP, UPSTREAM, UPDATETIME, KVER(4, 14, 0));
}
DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_ether$opt",
@@ -697,7 +698,7 @@
sched_cls_tether_downstream4_ether_opt,
KVER(4, 14, 0), KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ true, /* downstream */ true, /* updatetime */ true);
+ return do_forward4(skb, ETHER, DOWNSTREAM, UPDATETIME, KVER(4, 14, 0));
}
DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_ether$opt",
@@ -705,7 +706,7 @@
sched_cls_tether_upstream4_ether_opt,
KVER(4, 14, 0), KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ true, /* downstream */ false, /* updatetime */ true);
+ return do_forward4(skb, ETHER, UPSTREAM, UPDATETIME, KVER(4, 14, 0));
}
// Partial (TCP-only: will not update 'last_used' field) implementations for 4.14+ kernels.
@@ -725,13 +726,13 @@
DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_rawip$5_4", TETHERING_UID, TETHERING_GID,
sched_cls_tether_downstream4_rawip_5_4, KVER(5, 4, 0), KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ false, /* downstream */ true, /* updatetime */ false);
+ return do_forward4(skb, RAWIP, DOWNSTREAM, NO_UPDATETIME, KVER(5, 4, 0));
}
DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_rawip$5_4", TETHERING_UID, TETHERING_GID,
sched_cls_tether_upstream4_rawip_5_4, KVER(5, 4, 0), KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ false, /* downstream */ false, /* updatetime */ false);
+ return do_forward4(skb, RAWIP, UPSTREAM, NO_UPDATETIME, KVER(5, 4, 0));
}
// RAWIP: Optional for 4.14/4.19 (R) kernels -- which support bpf_skb_change_head().
@@ -742,7 +743,7 @@
sched_cls_tether_downstream4_rawip_4_14,
KVER(4, 14, 0), KVER(5, 4, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ false, /* downstream */ true, /* updatetime */ false);
+ return do_forward4(skb, RAWIP, DOWNSTREAM, NO_UPDATETIME, KVER(4, 14, 0));
}
DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_rawip$4_14",
@@ -750,7 +751,7 @@
sched_cls_tether_upstream4_rawip_4_14,
KVER(4, 14, 0), KVER(5, 4, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ false, /* downstream */ false, /* updatetime */ false);
+ return do_forward4(skb, RAWIP, UPSTREAM, NO_UPDATETIME, KVER(4, 14, 0));
}
// ETHER: Required for 4.14-Q/R, 4.19-Q/R & 5.4-R kernels.
@@ -758,13 +759,13 @@
DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_downstream4_ether$4_14", TETHERING_UID, TETHERING_GID,
sched_cls_tether_downstream4_ether_4_14, KVER(4, 14, 0), KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ true, /* downstream */ true, /* updatetime */ false);
+ return do_forward4(skb, ETHER, DOWNSTREAM, NO_UPDATETIME, KVER(4, 14, 0));
}
DEFINE_BPF_PROG_KVER_RANGE("schedcls/tether_upstream4_ether$4_14", TETHERING_UID, TETHERING_GID,
sched_cls_tether_upstream4_ether_4_14, KVER(4, 14, 0), KVER(5, 8, 0))
(struct __sk_buff* skb) {
- return do_forward4(skb, /* is_ethernet */ true, /* downstream */ false, /* updatetime */ false);
+ return do_forward4(skb, ETHER, UPSTREAM, NO_UPDATETIME, KVER(4, 14, 0));
}
// Placeholder (no-op) implementations for older Q kernels
@@ -820,9 +821,9 @@
if ((void*)(eth + 1) > data_end) return XDP_PASS;
if (eth->h_proto == htons(ETH_P_IPV6))
- return do_xdp_forward6(ctx, /* is_ethernet */ true, downstream);
+ return do_xdp_forward6(ctx, ETHER, downstream);
if (eth->h_proto == htons(ETH_P_IP))
- return do_xdp_forward4(ctx, /* is_ethernet */ true, downstream);
+ return do_xdp_forward4(ctx, ETHER, downstream);
// Anything else we don't know how to handle...
return XDP_PASS;
@@ -836,8 +837,8 @@
if (data_end - data < 1) return XDP_PASS;
const uint8_t v = (*(uint8_t*)data) >> 4;
- if (v == 6) return do_xdp_forward6(ctx, /* is_ethernet */ false, downstream);
- if (v == 4) return do_xdp_forward4(ctx, /* is_ethernet */ false, downstream);
+ if (v == 6) return do_xdp_forward6(ctx, RAWIP, downstream);
+ if (v == 4) return do_xdp_forward4(ctx, RAWIP, downstream);
// Anything else we don't know how to handle...
return XDP_PASS;
@@ -848,22 +849,22 @@
DEFINE_XDP_PROG("xdp/tether_downstream_ether",
xdp_tether_downstream_ether) {
- return do_xdp_forward_ether(ctx, /* downstream */ true);
+ return do_xdp_forward_ether(ctx, DOWNSTREAM);
}
DEFINE_XDP_PROG("xdp/tether_downstream_rawip",
xdp_tether_downstream_rawip) {
- return do_xdp_forward_rawip(ctx, /* downstream */ true);
+ return do_xdp_forward_rawip(ctx, DOWNSTREAM);
}
DEFINE_XDP_PROG("xdp/tether_upstream_ether",
xdp_tether_upstream_ether) {
- return do_xdp_forward_ether(ctx, /* downstream */ false);
+ return do_xdp_forward_ether(ctx, UPSTREAM);
}
DEFINE_XDP_PROG("xdp/tether_upstream_rawip",
xdp_tether_upstream_rawip) {
- return do_xdp_forward_rawip(ctx, /* downstream */ false);
+ return do_xdp_forward_rawip(ctx, UPSTREAM);
}
LICENSE("Apache 2.0");
diff --git a/framework-t/Android.bp b/framework-t/Android.bp
index d40fad9..ffa2857 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -46,6 +46,7 @@
libs: [
"unsupportedappusage",
"app-compat-annotations",
+ "androidx.annotation_annotation",
],
impl_only_libs: [
// The build system will use framework-bluetooth module_current stubs, because
@@ -139,7 +140,7 @@
"//packages/modules/Connectivity/apex",
"//packages/modules/Connectivity/service", // For R8 only
"//packages/modules/Connectivity/service-t",
- "//packages/modules/Connectivity/nearby/service",
+ "//packages/modules/Connectivity/nearby:__subpackages__",
"//frameworks/base",
// Tests using hidden APIs
@@ -156,7 +157,6 @@
"//frameworks/opt/telephony/tests/telephonytests",
"//packages/modules/CaptivePortalLogin/tests",
"//packages/modules/Connectivity/Tethering/tests:__subpackages__",
- "//packages/modules/Connectivity/nearby/tests:__subpackages__",
"//packages/modules/Connectivity/tests:__subpackages__",
"//packages/modules/IPsec/tests/iketests",
"//packages/modules/NetworkStack/tests:__subpackages__",
@@ -164,6 +164,7 @@
],
}
+// This rule is not used anymore(b/268440216).
platform_compat_config {
name: "connectivity-t-platform-compat-config",
src: ":framework-connectivity-t",
diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp
index 391a562..b8eb1f6 100644
--- a/framework-t/Sources.bp
+++ b/framework-t/Sources.bp
@@ -16,15 +16,13 @@
filegroup {
name: "framework-connectivity-tiramisu-updatable-sources",
+ defaults: ["framework-sources-module-defaults"],
srcs: [
"src/**/*.java",
"src/**/*.aidl",
],
path: "src",
- visibility: [
- "//frameworks/base",
- "//packages/modules/Connectivity:__subpackages__",
- ],
+ visibility: ["//packages/modules/Connectivity:__subpackages__"],
}
cc_library_shared {
diff --git a/framework-t/api/current.txt b/framework-t/api/current.txt
index 5532853..86745d4 100644
--- a/framework-t/api/current.txt
+++ b/framework-t/api/current.txt
@@ -228,8 +228,8 @@
}
public static interface NsdManager.ResolveListener {
+ method public default void onResolutionStopped(@NonNull android.net.nsd.NsdServiceInfo);
method public void onResolveFailed(android.net.nsd.NsdServiceInfo, int);
- method public default void onResolveStopped(@NonNull android.net.nsd.NsdServiceInfo);
method public void onServiceResolved(android.net.nsd.NsdServiceInfo);
method public default void onStopResolutionFailed(@NonNull android.net.nsd.NsdServiceInfo, int);
}
diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java
index edfd21c..947a092 100644
--- a/framework-t/src/android/net/NetworkIdentity.java
+++ b/framework-t/src/android/net/NetworkIdentity.java
@@ -32,6 +32,7 @@
import android.net.wifi.WifiInfo;
import android.service.NetworkIdentityProto;
import android.telephony.TelephonyManager;
+import android.util.Log;
import android.util.proto.ProtoOutputStream;
import com.android.net.module.util.BitUtils;
@@ -406,10 +407,18 @@
setOemManaged(getOemBitfield(snapshot.getNetworkCapabilities()));
if (mType == TYPE_WIFI) {
- final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
- .getTransportInfo();
+ final NetworkCapabilities nc = snapshot.getNetworkCapabilities();
+ final TransportInfo transportInfo = nc.getTransportInfo();
if (transportInfo instanceof WifiInfo) {
final WifiInfo info = (WifiInfo) transportInfo;
+ // Log.wtf to catch trying to set a null wifiNetworkKey into NetworkIdentity.
+ // See b/266598304. The problematic data that has null wifi network key is
+ // thrown out when storing data, which is handled by the service.
+ if (info.getNetworkKey() == null) {
+ Log.wtf(TAG, "WifiInfo contains a null wifiNetworkKey and it will"
+ + " be set into NetworkIdentity, netId=" + snapshot.getNetwork()
+ + "NetworkCapabilities=" + nc);
+ }
setWifiNetworkKey(info.getNetworkKey());
}
} else if (mType == TYPE_TEST) {
diff --git a/framework-t/src/android/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java
index b64fbdb..23902dc 100644
--- a/framework-t/src/android/net/NetworkStatsAccess.java
+++ b/framework-t/src/android/net/NetworkStatsAccess.java
@@ -17,7 +17,6 @@
package android.net;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
@@ -33,6 +32,8 @@
import android.os.UserHandle;
import android.telephony.TelephonyManager;
+import com.android.net.module.util.PermissionUtils;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -100,6 +101,7 @@
* <li>Device owners.
* <li>Carrier-privileged applications.
* <li>The system UID.
+ * <li>NetworkStack application.
* </ul>
*/
int DEVICE = 3;
@@ -111,22 +113,23 @@
final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class);
final TelephonyManager tm = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
- boolean hasCarrierPrivileges;
- final long token = Binder.clearCallingIdentity();
+ final boolean hasCarrierPrivileges;
+ final boolean isDeviceOwner;
+ long token = Binder.clearCallingIdentity();
try {
hasCarrierPrivileges = tm != null
&& tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage);
} finally {
Binder.restoreCallingIdentity(token);
}
- final boolean isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage);
final int appId = UserHandle.getAppId(callingUid);
- final boolean isNetworkStack = context.checkPermission(
- android.Manifest.permission.NETWORK_STACK, callingPid, callingUid)
- == PERMISSION_GRANTED;
+ final boolean isNetworkStack = PermissionUtils.checkAnyPermissionOf(
+ context, callingPid, callingUid, android.Manifest.permission.NETWORK_STACK,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
if (hasCarrierPrivileges || isDeviceOwner
|| appId == Process.SYSTEM_UID || isNetworkStack) {
@@ -135,15 +138,20 @@
return NetworkStatsAccess.Level.DEVICE;
}
- boolean hasAppOpsPermission = hasAppOpsPermission(context, callingUid, callingPackage);
+ final boolean hasAppOpsPermission =
+ hasAppOpsPermission(context, callingUid, callingPackage);
if (hasAppOpsPermission || context.checkCallingOrSelfPermission(
READ_NETWORK_USAGE_HISTORY) == PackageManager.PERMISSION_GRANTED) {
return NetworkStatsAccess.Level.DEVICESUMMARY;
}
- //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode.
- boolean isProfileOwner = mDpm != null && (mDpm.isProfileOwnerApp(callingPackage)
- || mDpm.isDeviceOwnerApp(callingPackage));
+ final boolean isProfileOwner;
+ token = Binder.clearCallingIdentity();
+ try {
+ isProfileOwner = mDpm != null && mDpm.isProfileOwnerApp(callingPackage);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
if (isProfileOwner) {
// Apps with the AppOps permission, profile owners, and apps with the privileged
// permission can access data usage for all apps in this user/profile.
diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
index f633a8f..33bd884 100644
--- a/framework-t/src/android/net/NetworkTemplate.java
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -47,16 +47,22 @@
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkIdentityUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
@@ -70,6 +76,8 @@
*/
@SystemApi(client = MODULE_LIBRARIES)
public final class NetworkTemplate implements Parcelable {
+ private static final String TAG = NetworkTemplate.class.getSimpleName();
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "MATCH_" }, value = {
@@ -176,6 +184,23 @@
}
}
+ private static Set<String> setOf(@Nullable final String item) {
+ if (item == null) {
+ // Set.of will throw if item is null
+ final Set<String> set = new HashSet<>();
+ set.add(null);
+ return Collections.unmodifiableSet(set);
+ } else {
+ return Set.of(item);
+ }
+ }
+
+ private static void throwAtLeastU() {
+ if (SdkLevel.isAtLeastU()) {
+ throw new UnsupportedOperationException("Method not supported on Android U or above");
+ }
+ }
+
/**
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
* the given IMSI.
@@ -188,7 +213,7 @@
publicAlternatives = "Use {@code Builder} instead.")
public static NetworkTemplate buildTemplateMobileAll(@NonNull String subscriberId) {
return new NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES)
- .setSubscriberIds(Set.of(subscriberId)).build();
+ .setSubscriberIds(setOf(subscriberId)).build();
}
/**
@@ -243,6 +268,121 @@
return new NetworkTemplate.Builder(MATCH_ETHERNET).build();
}
+ /**
+ * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style
+ * networks together.
+ *
+ * @hide
+ */
+ // TODO(b/270089918): Remove this method. This can only be done after there are no more callers,
+ // including in OEM code which can access this by linking against the framework.
+ public static NetworkTemplate buildTemplateBluetooth() {
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
+ return new NetworkTemplate.Builder(MATCH_BLUETOOTH).build();
+ }
+
+ /**
+ * Template to combine all {@link ConnectivityManager#TYPE_PROXY} style
+ * networks together.
+ *
+ * @hide
+ */
+ // TODO(b/270089918): Remove this method. This can only be done after there are no more callers,
+ // including in OEM code which can access this by linking against the framework.
+ public static NetworkTemplate buildTemplateProxy() {
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
+ return new NetworkTemplate(MATCH_PROXY, null, null);
+ }
+
+ /**
+ * Template to match all metered carrier networks with the given IMSI.
+ *
+ * @hide
+ */
+ // TODO(b/273963543): Remove this method. This can only be done after there are no more callers,
+ // including in OEM code which can access this by linking against the framework.
+ public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
+ throwAtLeastU();
+ return new NetworkTemplate.Builder(MATCH_CARRIER)
+ // Set.of will throw if subscriberId is null, which is the historical
+ // behavior and should be preserved.
+ .setSubscriberIds(Set.of(subscriberId))
+ .setMeteredness(METERED_YES)
+ .build();
+ }
+
+ /**
+ * Template to match cellular networks with the given IMSI, {@code ratType} and
+ * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when
+ * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}.
+ *
+ * @hide
+ */
+ // TODO(b/273963543): Remove this method. This can only be done after there are no more callers,
+ // including in OEM code which can access this by linking against the framework.
+ public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
+ int ratType, int metered) {
+ throwAtLeastU();
+ return new NetworkTemplate.Builder(MATCH_MOBILE)
+ .setSubscriberIds(TextUtils.isEmpty(subscriberId)
+ ? Collections.emptySet()
+ : Set.of(subscriberId))
+ .setMeteredness(metered)
+ .setRatType(ratType)
+ .build();
+ }
+
+ /**
+ * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
+ * given key of the wifi network.
+ *
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
+ * to know details about the key.
+ * @hide
+ */
+ // TODO(b/273963543): Remove this method. This can only be done after there are no more callers,
+ // including in OEM code which can access this by linking against the framework.
+ public static NetworkTemplate buildTemplateWifi(@NonNull String wifiNetworkKey) {
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
+ return new NetworkTemplate.Builder(MATCH_WIFI)
+ // Set.of will throw if wifiNetworkKey is null, which is the historical
+ // behavior and should be preserved.
+ .setWifiNetworkKeys(Set.of(wifiNetworkKey))
+ .build();
+ }
+
+ /**
+ * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given
+ * key of the wifi network and IMSI.
+ *
+ * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code wifiNetworkKey} to get result regardless
+ * of key of the wifi network.
+ *
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
+ * to know details about the key.
+ * @param subscriberId the IMSI associated to this wifi network.
+ *
+ * @hide
+ */
+ // TODO(b/273963543): Remove this method. This can only be done after there are no more callers,
+ // including in OEM code which can access this by linking against the framework.
+ public static NetworkTemplate buildTemplateWifi(@Nullable String wifiNetworkKey,
+ @Nullable String subscriberId) {
+ throwAtLeastU();
+ return new NetworkTemplate.Builder(MATCH_WIFI)
+ .setSubscriberIds(setOf(subscriberId))
+ .setWifiNetworkKeys(wifiNetworkKey == null
+ ? Collections.emptySet()
+ : Set.of(wifiNetworkKey))
+ .build();
+ }
+
private final int mMatchRule;
/**
@@ -270,12 +410,25 @@
private static void checkValidMatchSubscriberIds(int matchRule, String[] matchSubscriberIds) {
switch (matchRule) {
+ // CARRIER templates must always specify a valid subscriber ID.
+ // MOBILE templates can have empty matchSubscriberIds but it must not contain a null
+ // subscriber ID.
case MATCH_CARRIER:
- // CARRIER templates must always specify a valid subscriber ID.
if (matchSubscriberIds.length == 0) {
- throw new IllegalArgumentException("checkValidMatchSubscriberIds with empty"
- + " list of ids for rule" + getMatchRuleName(matchRule));
- } else if (CollectionUtils.contains(matchSubscriberIds, null)) {
+ throw new IllegalArgumentException("matchSubscriberIds may not contain"
+ + " null for rule " + getMatchRuleName(matchRule));
+ }
+ if (CollectionUtils.contains(matchSubscriberIds, null)) {
+ throw new IllegalArgumentException("matchSubscriberIds may not contain"
+ + " null for rule " + getMatchRuleName(matchRule));
+ }
+ break;
+ case MATCH_MOBILE:
+ // Prevent from crash for b/273963543, where the OEMs still call into unsupported
+ // buildTemplateMobileAll with null subscriberId and get crashed.
+ final int firstSdk = Build.VERSION.DEVICE_INITIAL_SDK_INT;
+ if (firstSdk > Build.VERSION_CODES.TIRAMISU
+ && CollectionUtils.contains(matchSubscriberIds, null)) {
throw new IllegalArgumentException("checkValidMatchSubscriberIds list of ids"
+ " may not contain null for rule " + getMatchRuleName(matchRule));
}
@@ -296,12 +449,69 @@
// Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
// to metered networks. It is now possible to match mobile with any meteredness, but
// in order to preserve backward compatibility of @UnsupportedAppUsage methods, this
- //constructor passes METERED_YES for these types.
- this(matchRule, new String[] { subscriberId },
+ // constructor passes METERED_YES for these types.
+ // For backwards compatibility, still accept old wildcard match rules (6 and 7 for
+ // MATCH_{MOBILE,WIFI}_WILDCARD) but convert into functionally equivalent non-wildcard
+ // ones.
+ this(getBackwardsCompatibleMatchRule(matchRule),
+ subscriberId != null ? new String[] { subscriberId } : new String[0],
wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
- (matchRule == MATCH_MOBILE || matchRule == MATCH_CARRIER)
- ? METERED_YES : METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
- NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
+ getMeterednessForBackwardsCompatibility(matchRule), ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
+ if (matchRule == 6 || matchRule == 7) {
+ Log.e(TAG, "Use MATCH_MOBILE with empty subscriberIds or MATCH_WIFI with empty "
+ + "wifiNetworkKeys instead of template with matchRule=" + matchRule);
+ }
+ }
+
+ private static int getBackwardsCompatibleMatchRule(int matchRule) {
+ // Backwards compatibility old constants
+ // Old MATCH_MOBILE_WILDCARD
+ if (6 == matchRule) return MATCH_MOBILE;
+ // Old MATCH_WIFI_WILDCARD
+ if (7 == matchRule) return MATCH_WIFI;
+ return matchRule;
+ }
+
+ private static int getMeterednessForBackwardsCompatibility(int matchRule) {
+ if (getBackwardsCompatibleMatchRule(matchRule) == MATCH_MOBILE
+ || matchRule == MATCH_CARRIER) {
+ return METERED_YES;
+ }
+ return METERED_ALL;
+ }
+
+ /** @hide */
+ // TODO(b/270089918): Remove this method after no callers.
+ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
+ String wifiNetworkKey) {
+ // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
+ // to metered networks. It is now possible to match mobile with any meteredness, but
+ // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this
+ // constructor passes METERED_YES for these types.
+ this(getBackwardsCompatibleMatchRule(matchRule), matchSubscriberIds,
+ wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
+ getMeterednessForBackwardsCompatibility(matchRule),
+ ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL);
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
+ }
+
+ /** @hide */
+ // TODO(b/269974916): Remove this method after Android U is released.
+ // This is only used by CTS of Android T.
+ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
+ String[] matchWifiNetworkKeys, int metered, int roaming,
+ int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule) {
+ // subscriberId and subscriberIdMatchRule aren't used since they are replaced by
+ // matchSubscriberIds, which could be null to indicate the intention of matching any
+ // subscriberIds.
+ this(getBackwardsCompatibleMatchRule(matchRule),
+ matchSubscriberIds == null ? new String[]{} : matchSubscriberIds,
+ matchWifiNetworkKeys, metered, roaming, defaultNetwork, ratType, oemManaged);
+ throwAtLeastU();
}
/** @hide */
@@ -383,8 +593,9 @@
@Override
public int hashCode() {
- return Objects.hash(mMatchRule, Arrays.hashCode(mMatchWifiNetworkKeys),
- mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged);
+ return Objects.hash(mMatchRule, Arrays.hashCode(mMatchSubscriberIds),
+ Arrays.hashCode(mMatchWifiNetworkKeys), mMetered, mRoaming, mDefaultNetwork,
+ mRatType, mOemManaged);
}
@Override
@@ -397,11 +608,29 @@
&& mDefaultNetwork == other.mDefaultNetwork
&& mRatType == other.mRatType
&& mOemManaged == other.mOemManaged
+ && Arrays.equals(mMatchSubscriberIds, other.mMatchSubscriberIds)
&& Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys);
}
return false;
}
+ // TODO(b/270089918): Remove this method. This can only be done after there are no more callers,
+ // including in OEM code which can access this by linking against the framework.
+ /** @hide */
+ public boolean isMatchRuleMobile() {
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
+ switch (mMatchRule) {
+ case MATCH_MOBILE:
+ // Old MATCH_MOBILE_WILDCARD
+ case 6:
+ return true;
+ default:
+ return false;
+ }
+ }
+
/**
* Get match rule of the template. See {@code MATCH_*}.
*/
@@ -574,7 +803,15 @@
* to know details about the key.
*/
private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) {
- Objects.requireNonNull(wifiNetworkKey);
+ // Note that this code accepts null wifi network keys because of a past bug where wifi
+ // code was sending a null network key for some connected networks, which isn't expected
+ // and ended up stored in the data on many devices.
+ // A null network key in the data matches a wildcard template (one where
+ // {@code mMatchWifiNetworkKeys} is empty), but not one where {@code MatchWifiNetworkKeys}
+ // contains null. See b/266598304.
+ if (wifiNetworkKey == null) {
+ return CollectionUtils.isEmpty(mMatchWifiNetworkKeys);
+ }
return CollectionUtils.isEmpty(mMatchWifiNetworkKeys)
|| CollectionUtils.contains(mMatchWifiNetworkKeys, wifiNetworkKey);
}
@@ -696,8 +933,7 @@
* subscribers.
* <p>
* For example, given an incoming template matching B, and the currently
- * active merge set [A,B], we'd return a new template that primarily matches
- * A, but also matches B.
+ * active merge set [A,B], we'd return a new template that matches both A and B.
*
* @hide
*/
@@ -706,6 +942,46 @@
+ "Callers should have their own logic to merge template for"
+ " different IMSIs and stop calling this function.")
public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
+ return normalizeImpl(template, Collections.singletonList(merged));
+ }
+
+ /**
+ * Examine the given template and normalize it.
+ * We pick the "lowest" merged subscriber as the primary
+ * for key purposes, and expand the template to match all other merged
+ * subscribers.
+ *
+ * There can be multiple merged subscriberIds for multi-SIM devices.
+ *
+ * <p>
+ * For example, given an incoming template matching B, and the currently
+ * active merge set [A,B], we'd return a new template that matches both A and B.
+ *
+ * @hide
+ */
+ // TODO(b/273963543): Remove this method. This can only be done after there are no more callers,
+ // including in OEM code which can access this by linking against the framework.
+ public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
+ throwAtLeastU();
+ return normalizeImpl(template, mergedList);
+ }
+
+ /**
+ * Examine the given template and normalize it.
+ * We pick the "lowest" merged subscriber as the primary
+ * for key purposes, and expand the template to match all other merged
+ * subscribers.
+ *
+ * There can be multiple merged subscriberIds for multi-SIM devices.
+ *
+ * <p>
+ * For example, given an incoming template matching B, and the currently
+ * active merge set [A,B], we'd return a new template that matches both A and B.
+ *
+ * @hide
+ */
+ private static NetworkTemplate normalizeImpl(NetworkTemplate template,
+ List<String[]> mergedList) {
// Now there are several types of network which uses SubscriberId to store network
// information. For instances:
// The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network.
@@ -713,18 +989,21 @@
if (CollectionUtils.isEmpty(template.mMatchSubscriberIds)) return template;
- if (CollectionUtils.contains(merged, template.mMatchSubscriberIds[0])) {
- // Requested template subscriber is part of the merge group; return
- // a template that matches all merged subscribers.
- final String[] matchWifiNetworkKeys = template.mMatchWifiNetworkKeys;
- // TODO: Use NetworkTemplate.Builder to build a template after NetworkTemplate
- // could handle incompatible subscriberIds. See b/217805241.
- return new NetworkTemplate(template.mMatchRule, merged,
- CollectionUtils.isEmpty(matchWifiNetworkKeys)
- ? new String[0] : new String[] { matchWifiNetworkKeys[0] },
- (template.mMatchRule == MATCH_MOBILE || template.mMatchRule == MATCH_CARRIER)
- ? METERED_YES : METERED_ALL,
- ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
+ for (String[] merged : mergedList) {
+ if (CollectionUtils.contains(merged, template.mMatchSubscriberIds[0])) {
+ // Requested template subscriber is part of the merge group; return
+ // a template that matches all merged subscribers.
+ final String[] matchWifiNetworkKeys = template.mMatchWifiNetworkKeys;
+ // TODO: Use NetworkTemplate.Builder to build a template after NetworkTemplate
+ // could handle incompatible subscriberIds. See b/217805241.
+ return new NetworkTemplate(template.mMatchRule, merged,
+ CollectionUtils.isEmpty(matchWifiNetworkKeys)
+ ? new String[0] : new String[] { matchWifiNetworkKeys[0] },
+ (template.mMatchRule == MATCH_MOBILE
+ || template.mMatchRule == MATCH_CARRIER)
+ ? METERED_YES : METERED_ALL,
+ ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
+ }
}
return template;
diff --git a/framework-t/src/android/net/nsd/INsdManager.aidl b/framework-t/src/android/net/nsd/INsdManager.aidl
index 89e9cdb..9d14b1a 100644
--- a/framework-t/src/android/net/nsd/INsdManager.aidl
+++ b/framework-t/src/android/net/nsd/INsdManager.aidl
@@ -26,5 +26,5 @@
* {@hide}
*/
interface INsdManager {
- INsdServiceConnector connect(INsdManagerCallback cb);
+ INsdServiceConnector connect(INsdManagerCallback cb, boolean useJavaBackend);
}
diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java
index 122e3a0..d119db6 100644
--- a/framework-t/src/android/net/nsd/NsdManager.java
+++ b/framework-t/src/android/net/nsd/NsdManager.java
@@ -16,6 +16,9 @@
package android.net.nsd;
+import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_PLATFORM_MDNS_BACKEND;
+import static android.net.connectivity.ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -24,8 +27,6 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
@@ -137,28 +138,6 @@
private static final boolean DBG = false;
/**
- * When enabled, apps targeting < Android 12 are considered legacy for
- * the NSD native daemon.
- * The platform will only keep the daemon running as long as there are
- * any legacy apps connected.
- *
- * After Android 12, direct communication with the native daemon might not work since the native
- * daemon won't always stay alive. Using the NSD APIs from NsdManager as the replacement is
- * recommended.
- * Another alternative could be bundling your own mdns solutions instead of
- * depending on the system mdns native daemon.
- *
- * This compatibility change applies to Android 13 and later only. To toggle behavior on
- * Android 12 and Android 12L, use RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS.
- *
- * @hide
- */
- @ChangeId
- @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
- // This was a platform change ID with value 191844585L before T
- public static final long RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER = 235355681L;
-
- /**
* Broadcast intent action to indicate whether network service discovery is
* enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state
* information as int.
@@ -302,6 +281,9 @@
EVENT_NAMES.put(UNREGISTER_SERVICE_CALLBACK, "UNREGISTER_SERVICE_CALLBACK");
EVENT_NAMES.put(UNREGISTER_SERVICE_CALLBACK_SUCCEEDED,
"UNREGISTER_SERVICE_CALLBACK_SUCCEEDED");
+ EVENT_NAMES.put(MDNS_DISCOVERY_MANAGER_EVENT, "MDNS_DISCOVERY_MANAGER_EVENT");
+ EVENT_NAMES.put(REGISTER_CLIENT, "REGISTER_CLIENT");
+ EVENT_NAMES.put(UNREGISTER_CLIENT, "UNREGISTER_CLIENT");
}
/** @hide */
@@ -532,7 +514,8 @@
mHandler = new ServiceHandler(t.getLooper());
try {
- mService = service.connect(new NsdCallbackImpl(mHandler));
+ mService = service.connect(new NsdCallbackImpl(mHandler), CompatChanges.isChangeEnabled(
+ ENABLE_PLATFORM_MDNS_BACKEND));
} catch (RemoteException e) {
throw new RuntimeException("Failed to connect to NsdService");
}
@@ -767,18 +750,18 @@
* Called on the internal thread or with an executor passed to
* {@link NsdManager#resolveService} to report the resolution was stopped.
*
- * A stop resolution operation would call either onResolveStopped or onStopResolutionFailed
- * once based on the result.
+ * A stop resolution operation would call either onResolutionStopped or
+ * onStopResolutionFailed once based on the result.
*/
- default void onResolveStopped(@NonNull NsdServiceInfo serviceInfo) { }
+ default void onResolutionStopped(@NonNull NsdServiceInfo serviceInfo) { }
/**
* Called once on the internal thread or with an executor passed to
* {@link NsdManager#resolveService} to report that stopping resolution failed with an
* error.
*
- * A stop resolution operation would call either onResolveStopped or onStopResolutionFailed
- * once based on the result.
+ * A stop resolution operation would call either onResolutionStopped or
+ * onStopResolutionFailed once based on the result.
*/
default void onStopResolutionFailed(@NonNull NsdServiceInfo serviceInfo,
@StopOperationFailureCode int errorCode) { }
@@ -929,7 +912,7 @@
break;
case STOP_RESOLUTION_SUCCEEDED:
removeListener(key);
- executor.execute(() -> ((ResolveListener) listener).onResolveStopped(
+ executor.execute(() -> ((ResolveListener) listener).onResolutionStopped(
ns));
break;
case REGISTER_SERVICE_CALLBACK_FAILED:
@@ -1301,7 +1284,7 @@
/**
* Stop service resolution initiated with {@link #resolveService}.
*
- * A successful stop is notified with a call to {@link ResolveListener#onResolveStopped}.
+ * A successful stop is notified with a call to {@link ResolveListener#onResolutionStopped}.
*
* <p> Upon failure to stop service resolution for example if resolution is done or the
* requester stops resolution repeatedly, the application is notified
@@ -1334,7 +1317,7 @@
* before registering other callbacks. Upon failure to register a callback for example if
* it's a duplicated registration, the application is notified through
* {@link ServiceInfoCallback#onServiceInfoCallbackRegistrationFailed} with
- * {@link #FAILURE_BAD_PARAMETERS} or {@link #FAILURE_ALREADY_ACTIVE}.
+ * {@link #FAILURE_BAD_PARAMETERS}.
*
* @param serviceInfo the service to receive updates for
* @param executor Executor to run callbacks with
diff --git a/framework/Android.bp b/framework/Android.bp
index 3950dba..d7eaf9b 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -45,14 +45,12 @@
// TODO: use a java_library in the bootclasspath instead
filegroup {
name: "framework-connectivity-sources",
+ defaults: ["framework-sources-module-defaults"],
srcs: [
":framework-connectivity-internal-sources",
":framework-connectivity-aidl-export-sources",
],
- visibility: [
- "//frameworks/base",
- "//packages/modules/Connectivity:__subpackages__",
- ],
+ visibility: ["//packages/modules/Connectivity:__subpackages__"],
}
java_defaults {
@@ -107,7 +105,10 @@
java_library {
name: "framework-connectivity-pre-jarjar",
- defaults: ["framework-connectivity-defaults"],
+ defaults: [
+ "framework-connectivity-defaults",
+ "CronetJavaPrejarjarDefaults",
+ ],
libs: [
// This cannot be in the defaults clause above because if it were, it would be used
// to generate the connectivity stubs. That would create a circular dependency
@@ -121,7 +122,10 @@
java_sdk_library {
name: "framework-connectivity",
- defaults: ["framework-connectivity-defaults"],
+ defaults: [
+ "framework-connectivity-defaults",
+ "CronetJavaDefaults",
+ ],
installable: true,
jarjar_rules: ":framework-connectivity-jarjar-rules",
permitted_packages: ["android.net"],
@@ -149,6 +153,7 @@
"//frameworks/opt/net/ethernet/tests:__subpackages__",
"//frameworks/opt/telephony/tests/telephonytests",
"//packages/modules/CaptivePortalLogin/tests",
+ "//packages/modules/Connectivity/Cronet/tests:__subpackages__",
"//packages/modules/Connectivity/Tethering/tests:__subpackages__",
"//packages/modules/Connectivity/tests:__subpackages__",
"//packages/modules/IPsec/tests/iketests",
@@ -185,6 +190,7 @@
"libnativehelper",
],
header_libs: [
+ "bpf_headers",
"dnsproxyd_protocol_headers",
],
stl: "none",
diff --git a/framework/api/current.txt b/framework/api/current.txt
index 547b7e2..6860c3c 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -360,6 +360,7 @@
field public static final int TRANSPORT_CELLULAR = 0; // 0x0
field public static final int TRANSPORT_ETHERNET = 3; // 0x3
field public static final int TRANSPORT_LOWPAN = 6; // 0x6
+ field public static final int TRANSPORT_THREAD = 9; // 0x9
field public static final int TRANSPORT_USB = 8; // 0x8
field public static final int TRANSPORT_VPN = 4; // 0x4
field public static final int TRANSPORT_WIFI = 1; // 0x1
@@ -524,3 +525,292 @@
}
+package android.net.http {
+
+ public abstract class BidirectionalStream {
+ ctor public BidirectionalStream();
+ method public abstract void cancel();
+ method public abstract void flush();
+ method @NonNull public abstract android.net.http.HeaderBlock getHeaders();
+ method @NonNull public abstract String getHttpMethod();
+ method public abstract int getPriority();
+ method public abstract int getTrafficStatsTag();
+ method public abstract int getTrafficStatsUid();
+ method public abstract boolean hasTrafficStatsTag();
+ method public abstract boolean hasTrafficStatsUid();
+ method public abstract boolean isDelayRequestHeadersUntilFirstFlushEnabled();
+ method public abstract boolean isDone();
+ method public abstract void read(@NonNull java.nio.ByteBuffer);
+ method public abstract void start();
+ method public abstract void write(@NonNull java.nio.ByteBuffer, boolean);
+ field public static final int STREAM_PRIORITY_HIGHEST = 4; // 0x4
+ field public static final int STREAM_PRIORITY_IDLE = 0; // 0x0
+ field public static final int STREAM_PRIORITY_LOW = 2; // 0x2
+ field public static final int STREAM_PRIORITY_LOWEST = 1; // 0x1
+ field public static final int STREAM_PRIORITY_MEDIUM = 3; // 0x3
+ }
+
+ public abstract static class BidirectionalStream.Builder {
+ ctor public BidirectionalStream.Builder();
+ method @NonNull public abstract android.net.http.BidirectionalStream.Builder addHeader(@NonNull String, @NonNull String);
+ method @NonNull public abstract android.net.http.BidirectionalStream build();
+ method @NonNull public abstract android.net.http.BidirectionalStream.Builder setDelayRequestHeadersUntilFirstFlushEnabled(boolean);
+ method @NonNull public abstract android.net.http.BidirectionalStream.Builder setHttpMethod(@NonNull String);
+ method @NonNull public abstract android.net.http.BidirectionalStream.Builder setPriority(int);
+ method @NonNull public abstract android.net.http.BidirectionalStream.Builder setTrafficStatsTag(int);
+ method @NonNull public abstract android.net.http.BidirectionalStream.Builder setTrafficStatsUid(int);
+ }
+
+ public static interface BidirectionalStream.Callback {
+ method public void onCanceled(@NonNull android.net.http.BidirectionalStream, @Nullable android.net.http.UrlResponseInfo);
+ method public void onFailed(@NonNull android.net.http.BidirectionalStream, @Nullable android.net.http.UrlResponseInfo, @NonNull android.net.http.HttpException);
+ method public void onReadCompleted(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo, @NonNull java.nio.ByteBuffer, boolean);
+ method public void onResponseHeadersReceived(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo);
+ method public void onResponseTrailersReceived(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo, @NonNull android.net.http.HeaderBlock);
+ method public void onStreamReady(@NonNull android.net.http.BidirectionalStream);
+ method public void onSucceeded(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo);
+ method public void onWriteCompleted(@NonNull android.net.http.BidirectionalStream, @NonNull android.net.http.UrlResponseInfo, @NonNull java.nio.ByteBuffer, boolean);
+ }
+
+ public abstract class CallbackException extends android.net.http.HttpException {
+ ctor protected CallbackException(@Nullable String, @Nullable Throwable);
+ }
+
+ public class ConnectionMigrationOptions {
+ method public int getAllowNonDefaultNetworkUsage();
+ method public int getDefaultNetworkMigration();
+ method public int getPathDegradationMigration();
+ field public static final int MIGRATION_OPTION_DISABLED = 2; // 0x2
+ field public static final int MIGRATION_OPTION_ENABLED = 1; // 0x1
+ field public static final int MIGRATION_OPTION_UNSPECIFIED = 0; // 0x0
+ }
+
+ public static final class ConnectionMigrationOptions.Builder {
+ ctor public ConnectionMigrationOptions.Builder();
+ method @NonNull public android.net.http.ConnectionMigrationOptions build();
+ method @NonNull public android.net.http.ConnectionMigrationOptions.Builder setAllowNonDefaultNetworkUsage(int);
+ method @NonNull public android.net.http.ConnectionMigrationOptions.Builder setDefaultNetworkMigration(int);
+ method @NonNull public android.net.http.ConnectionMigrationOptions.Builder setPathDegradationMigration(int);
+ }
+
+ public final class DnsOptions {
+ method public int getPersistHostCache();
+ method @Nullable public java.time.Duration getPersistHostCachePeriod();
+ method public int getPreestablishConnectionsToStaleDnsResults();
+ method public int getStaleDns();
+ method @Nullable public android.net.http.DnsOptions.StaleDnsOptions getStaleDnsOptions();
+ method public int getUseHttpStackDnsResolver();
+ field public static final int DNS_OPTION_DISABLED = 2; // 0x2
+ field public static final int DNS_OPTION_ENABLED = 1; // 0x1
+ field public static final int DNS_OPTION_UNSPECIFIED = 0; // 0x0
+ }
+
+ public static final class DnsOptions.Builder {
+ ctor public DnsOptions.Builder();
+ method @NonNull public android.net.http.DnsOptions build();
+ method @NonNull public android.net.http.DnsOptions.Builder setPersistHostCache(int);
+ method @NonNull public android.net.http.DnsOptions.Builder setPersistHostCachePeriod(@NonNull java.time.Duration);
+ method @NonNull public android.net.http.DnsOptions.Builder setPreestablishConnectionsToStaleDnsResults(int);
+ method @NonNull public android.net.http.DnsOptions.Builder setStaleDns(int);
+ method @NonNull public android.net.http.DnsOptions.Builder setStaleDnsOptions(@NonNull android.net.http.DnsOptions.StaleDnsOptions);
+ method @NonNull public android.net.http.DnsOptions.Builder setUseHttpStackDnsResolver(int);
+ }
+
+ public static class DnsOptions.StaleDnsOptions {
+ method public int getAllowCrossNetworkUsage();
+ method @Nullable public java.time.Duration getFreshLookupTimeout();
+ method @Nullable public java.time.Duration getMaxExpiredDelay();
+ method public int getUseStaleOnNameNotResolved();
+ }
+
+ public static final class DnsOptions.StaleDnsOptions.Builder {
+ ctor public DnsOptions.StaleDnsOptions.Builder();
+ method @NonNull public android.net.http.DnsOptions.StaleDnsOptions build();
+ method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setAllowCrossNetworkUsage(int);
+ method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setFreshLookupTimeout(@NonNull java.time.Duration);
+ method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setMaxExpiredDelay(@NonNull java.time.Duration);
+ method @NonNull public android.net.http.DnsOptions.StaleDnsOptions.Builder setUseStaleOnNameNotResolved(int);
+ }
+
+ public abstract class HeaderBlock {
+ ctor public HeaderBlock();
+ method @NonNull public abstract java.util.List<java.util.Map.Entry<java.lang.String,java.lang.String>> getAsList();
+ method @NonNull public abstract java.util.Map<java.lang.String,java.util.List<java.lang.String>> getAsMap();
+ }
+
+ public abstract class HttpEngine {
+ method public void bindToNetwork(@Nullable android.net.Network);
+ method @NonNull public abstract java.net.URLStreamHandlerFactory createUrlStreamHandlerFactory();
+ method @NonNull public static String getVersionString();
+ method @NonNull public abstract android.net.http.BidirectionalStream.Builder newBidirectionalStreamBuilder(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.http.BidirectionalStream.Callback);
+ method @NonNull public abstract android.net.http.UrlRequest.Builder newUrlRequestBuilder(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.http.UrlRequest.Callback);
+ method @NonNull public abstract java.net.URLConnection openConnection(@NonNull java.net.URL) throws java.io.IOException;
+ method public abstract void shutdown();
+ }
+
+ public static class HttpEngine.Builder {
+ ctor public HttpEngine.Builder(@NonNull android.content.Context);
+ method @NonNull public android.net.http.HttpEngine.Builder addPublicKeyPins(@NonNull String, @NonNull java.util.Set<byte[]>, boolean, @NonNull java.time.Instant);
+ method @NonNull public android.net.http.HttpEngine.Builder addQuicHint(@NonNull String, int, int);
+ method @NonNull public android.net.http.HttpEngine build();
+ method @NonNull public String getDefaultUserAgent();
+ method @NonNull public android.net.http.HttpEngine.Builder setConnectionMigrationOptions(@NonNull android.net.http.ConnectionMigrationOptions);
+ method @NonNull public android.net.http.HttpEngine.Builder setDnsOptions(@NonNull android.net.http.DnsOptions);
+ method @NonNull public android.net.http.HttpEngine.Builder setEnableBrotli(boolean);
+ method @NonNull public android.net.http.HttpEngine.Builder setEnableHttp2(boolean);
+ method @NonNull public android.net.http.HttpEngine.Builder setEnableHttpCache(int, long);
+ method @NonNull public android.net.http.HttpEngine.Builder setEnablePublicKeyPinningBypassForLocalTrustAnchors(boolean);
+ method @NonNull public android.net.http.HttpEngine.Builder setEnableQuic(boolean);
+ method @NonNull public android.net.http.HttpEngine.Builder setQuicOptions(@NonNull android.net.http.QuicOptions);
+ method @NonNull public android.net.http.HttpEngine.Builder setStoragePath(@NonNull String);
+ method @NonNull public android.net.http.HttpEngine.Builder setUserAgent(@NonNull String);
+ field public static final int HTTP_CACHE_DISABLED = 0; // 0x0
+ field public static final int HTTP_CACHE_DISK = 3; // 0x3
+ field public static final int HTTP_CACHE_DISK_NO_HTTP = 2; // 0x2
+ field public static final int HTTP_CACHE_IN_MEMORY = 1; // 0x1
+ }
+
+ public class HttpException extends java.io.IOException {
+ ctor public HttpException(@Nullable String, @Nullable Throwable);
+ }
+
+ public final class InlineExecutionProhibitedException extends java.util.concurrent.RejectedExecutionException {
+ ctor public InlineExecutionProhibitedException();
+ }
+
+ public abstract class NetworkException extends android.net.http.HttpException {
+ ctor public NetworkException(@Nullable String, @Nullable Throwable);
+ method public abstract int getErrorCode();
+ method public abstract boolean isImmediatelyRetryable();
+ field public static final int ERROR_ADDRESS_UNREACHABLE = 9; // 0x9
+ field public static final int ERROR_CONNECTION_CLOSED = 5; // 0x5
+ field public static final int ERROR_CONNECTION_REFUSED = 7; // 0x7
+ field public static final int ERROR_CONNECTION_RESET = 8; // 0x8
+ field public static final int ERROR_CONNECTION_TIMED_OUT = 6; // 0x6
+ field public static final int ERROR_HOSTNAME_NOT_RESOLVED = 1; // 0x1
+ field public static final int ERROR_INTERNET_DISCONNECTED = 2; // 0x2
+ field public static final int ERROR_NETWORK_CHANGED = 3; // 0x3
+ field public static final int ERROR_OTHER = 11; // 0xb
+ field public static final int ERROR_QUIC_PROTOCOL_FAILED = 10; // 0xa
+ field public static final int ERROR_TIMED_OUT = 4; // 0x4
+ }
+
+ public abstract class QuicException extends android.net.http.NetworkException {
+ ctor protected QuicException(@Nullable String, @Nullable Throwable);
+ }
+
+ public class QuicOptions {
+ method @NonNull public java.util.Set<java.lang.String> getAllowedQuicHosts();
+ method @Nullable public String getHandshakeUserAgent();
+ method @Nullable public java.time.Duration getIdleConnectionTimeout();
+ method public int getInMemoryServerConfigsCacheSize();
+ method public boolean hasInMemoryServerConfigsCacheSize();
+ }
+
+ public static final class QuicOptions.Builder {
+ ctor public QuicOptions.Builder();
+ method @NonNull public android.net.http.QuicOptions.Builder addAllowedQuicHost(@NonNull String);
+ method @NonNull public android.net.http.QuicOptions build();
+ method @NonNull public android.net.http.QuicOptions.Builder setHandshakeUserAgent(@NonNull String);
+ method @NonNull public android.net.http.QuicOptions.Builder setIdleConnectionTimeout(@NonNull java.time.Duration);
+ method @NonNull public android.net.http.QuicOptions.Builder setInMemoryServerConfigsCacheSize(int);
+ }
+
+ public abstract class UploadDataProvider implements java.io.Closeable {
+ ctor public UploadDataProvider();
+ method public void close() throws java.io.IOException;
+ method public abstract long getLength() throws java.io.IOException;
+ method public abstract void read(@NonNull android.net.http.UploadDataSink, @NonNull java.nio.ByteBuffer) throws java.io.IOException;
+ method public abstract void rewind(@NonNull android.net.http.UploadDataSink) throws java.io.IOException;
+ }
+
+ public abstract class UploadDataSink {
+ ctor public UploadDataSink();
+ method public abstract void onReadError(@NonNull Exception);
+ method public abstract void onReadSucceeded(boolean);
+ method public abstract void onRewindError(@NonNull Exception);
+ method public abstract void onRewindSucceeded();
+ }
+
+ public abstract class UrlRequest {
+ method public abstract void cancel();
+ method public abstract void followRedirect();
+ method @NonNull public abstract android.net.http.HeaderBlock getHeaders();
+ method @Nullable public abstract String getHttpMethod();
+ method public abstract int getPriority();
+ method public abstract void getStatus(@NonNull android.net.http.UrlRequest.StatusListener);
+ method public abstract int getTrafficStatsTag();
+ method public abstract int getTrafficStatsUid();
+ method public abstract boolean hasTrafficStatsTag();
+ method public abstract boolean hasTrafficStatsUid();
+ method public abstract boolean isCacheDisabled();
+ method public abstract boolean isDirectExecutorAllowed();
+ method public abstract boolean isDone();
+ method public abstract void read(@NonNull java.nio.ByteBuffer);
+ method public abstract void start();
+ field public static final int REQUEST_PRIORITY_HIGHEST = 4; // 0x4
+ field public static final int REQUEST_PRIORITY_IDLE = 0; // 0x0
+ field public static final int REQUEST_PRIORITY_LOW = 2; // 0x2
+ field public static final int REQUEST_PRIORITY_LOWEST = 1; // 0x1
+ field public static final int REQUEST_PRIORITY_MEDIUM = 3; // 0x3
+ }
+
+ public abstract static class UrlRequest.Builder {
+ method @NonNull public abstract android.net.http.UrlRequest.Builder addHeader(@NonNull String, @NonNull String);
+ method @NonNull public abstract android.net.http.UrlRequest.Builder bindToNetwork(@Nullable android.net.Network);
+ method @NonNull public abstract android.net.http.UrlRequest build();
+ method @NonNull public abstract android.net.http.UrlRequest.Builder setCacheDisabled(boolean);
+ method @NonNull public abstract android.net.http.UrlRequest.Builder setDirectExecutorAllowed(boolean);
+ method @NonNull public abstract android.net.http.UrlRequest.Builder setHttpMethod(@NonNull String);
+ method @NonNull public abstract android.net.http.UrlRequest.Builder setPriority(int);
+ method @NonNull public abstract android.net.http.UrlRequest.Builder setTrafficStatsTag(int);
+ method @NonNull public abstract android.net.http.UrlRequest.Builder setTrafficStatsUid(int);
+ method @NonNull public abstract android.net.http.UrlRequest.Builder setUploadDataProvider(@NonNull android.net.http.UploadDataProvider, @NonNull java.util.concurrent.Executor);
+ }
+
+ public static interface UrlRequest.Callback {
+ method public void onCanceled(@NonNull android.net.http.UrlRequest, @Nullable android.net.http.UrlResponseInfo);
+ method public void onFailed(@NonNull android.net.http.UrlRequest, @Nullable android.net.http.UrlResponseInfo, @NonNull android.net.http.HttpException);
+ method public void onReadCompleted(@NonNull android.net.http.UrlRequest, @NonNull android.net.http.UrlResponseInfo, @NonNull java.nio.ByteBuffer) throws java.lang.Exception;
+ method public void onRedirectReceived(@NonNull android.net.http.UrlRequest, @NonNull android.net.http.UrlResponseInfo, @NonNull String) throws java.lang.Exception;
+ method public void onResponseStarted(@NonNull android.net.http.UrlRequest, @NonNull android.net.http.UrlResponseInfo) throws java.lang.Exception;
+ method public void onSucceeded(@NonNull android.net.http.UrlRequest, @NonNull android.net.http.UrlResponseInfo);
+ }
+
+ public static class UrlRequest.Status {
+ field public static final int CONNECTING = 10; // 0xa
+ field public static final int DOWNLOADING_PAC_FILE = 5; // 0x5
+ field public static final int ESTABLISHING_PROXY_TUNNEL = 8; // 0x8
+ field public static final int IDLE = 0; // 0x0
+ field public static final int INVALID = -1; // 0xffffffff
+ field public static final int READING_RESPONSE = 14; // 0xe
+ field public static final int RESOLVING_HOST = 9; // 0x9
+ field public static final int RESOLVING_HOST_IN_PAC_FILE = 7; // 0x7
+ field public static final int RESOLVING_PROXY_FOR_URL = 6; // 0x6
+ field public static final int SENDING_REQUEST = 12; // 0xc
+ field public static final int SSL_HANDSHAKE = 11; // 0xb
+ field public static final int WAITING_FOR_AVAILABLE_SOCKET = 2; // 0x2
+ field public static final int WAITING_FOR_CACHE = 4; // 0x4
+ field public static final int WAITING_FOR_DELEGATE = 3; // 0x3
+ field public static final int WAITING_FOR_RESPONSE = 13; // 0xd
+ field public static final int WAITING_FOR_STALLED_SOCKET_POOL = 1; // 0x1
+ }
+
+ public static interface UrlRequest.StatusListener {
+ method public void onStatus(int);
+ }
+
+ public abstract class UrlResponseInfo {
+ ctor public UrlResponseInfo();
+ method @NonNull public abstract android.net.http.HeaderBlock getHeaders();
+ method public abstract int getHttpStatusCode();
+ method @NonNull public abstract String getHttpStatusText();
+ method @NonNull public abstract String getNegotiatedProtocol();
+ method public abstract long getReceivedByteCount();
+ method @NonNull public abstract String getUrl();
+ method @NonNull public abstract java.util.List<java.lang.String> getUrlChain();
+ method public abstract boolean wasCached();
+ }
+
+}
+
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index f623b05..193bd92 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -15,7 +15,7 @@
method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.LinkProperties getRedactedLinkPropertiesForPackage(@NonNull android.net.LinkProperties, int, @NonNull String);
method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.NetworkCapabilities getRedactedNetworkCapabilitiesForPackage(@NonNull android.net.NetworkCapabilities, int, @NonNull String);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackForUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
- method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void removeUidFromMeteredNetworkAllowList(int);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void removeUidFromMeteredNetworkDenyList(int);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void replaceFirewallChain(int, @NonNull int[]);
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index 0b03983..4a2ed8a 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -470,7 +470,7 @@
}
public abstract class SocketKeepalive implements java.lang.AutoCloseable {
- method public final void start(@IntRange(from=0xa, to=0xe10) int, int);
+ method public final void start(@IntRange(from=0xa, to=0xe10) int, int, @Nullable android.net.Network);
field public static final int ERROR_NO_SUCH_SLOT = -33; // 0xffffffdf
field public static final int FLAG_AUTOMATIC_ON_OFF = 1; // 0x1
field public static final int SUCCESS = 0; // 0x0
diff --git a/framework/cronet_disabled/api/current.txt b/framework/cronet_disabled/api/current.txt
new file mode 100644
index 0000000..672e3e2
--- /dev/null
+++ b/framework/cronet_disabled/api/current.txt
@@ -0,0 +1,527 @@
+// Signature format: 2.0
+package android.net {
+
+ public class CaptivePortal implements android.os.Parcelable {
+ method public int describeContents();
+ method public void ignoreNetwork();
+ method public void reportCaptivePortalDismissed();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortal> CREATOR;
+ }
+
+ public class ConnectivityDiagnosticsManager {
+ method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+ method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+ }
+
+ public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback {
+ ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback();
+ method public void onConnectivityReportAvailable(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport);
+ method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport);
+ method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean);
+ }
+
+ public static final class ConnectivityDiagnosticsManager.ConnectivityReport implements android.os.Parcelable {
+ ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
+ method public int describeContents();
+ method @NonNull public android.os.PersistableBundle getAdditionalInfo();
+ method @NonNull public android.net.LinkProperties getLinkProperties();
+ method @NonNull public android.net.Network getNetwork();
+ method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
+ method public long getReportTimestamp();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.ConnectivityDiagnosticsManager.ConnectivityReport> CREATOR;
+ field public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = "networkProbesAttempted";
+ field public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = "networkProbesSucceeded";
+ field public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult";
+ field public static final int NETWORK_PROBE_DNS = 4; // 0x4
+ field public static final int NETWORK_PROBE_FALLBACK = 32; // 0x20
+ field public static final int NETWORK_PROBE_HTTP = 8; // 0x8
+ field public static final int NETWORK_PROBE_HTTPS = 16; // 0x10
+ field public static final int NETWORK_PROBE_PRIVATE_DNS = 64; // 0x40
+ field public static final int NETWORK_VALIDATION_RESULT_INVALID = 0; // 0x0
+ field public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2; // 0x2
+ field public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3; // 0x3
+ field public static final int NETWORK_VALIDATION_RESULT_VALID = 1; // 0x1
+ }
+
+ public static final class ConnectivityDiagnosticsManager.DataStallReport implements android.os.Parcelable {
+ ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
+ method public int describeContents();
+ method public int getDetectionMethod();
+ method @NonNull public android.net.LinkProperties getLinkProperties();
+ method @NonNull public android.net.Network getNetwork();
+ method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
+ method public long getReportTimestamp();
+ method @NonNull public android.os.PersistableBundle getStallDetails();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.ConnectivityDiagnosticsManager.DataStallReport> CREATOR;
+ field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1
+ field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2
+ field public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts";
+ field public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS = "tcpMetricsCollectionPeriodMillis";
+ field public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate";
+ }
+
+ public class ConnectivityManager {
+ method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
+ method public boolean bindProcessToNetwork(@Nullable android.net.Network);
+ method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork();
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo();
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo();
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks();
+ method @Deprecated public boolean getBackgroundDataSetting();
+ method @Nullable public android.net.Network getBoundNetworkForProcess();
+ method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress);
+ method @Nullable public android.net.ProxyInfo getDefaultProxy();
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getMultipathPreference(@Nullable android.net.Network);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network);
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(int);
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(@Nullable android.net.Network);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference();
+ method @Nullable public byte[] getNetworkWatchlistConfigHash();
+ method @Deprecated @Nullable public static android.net.Network getProcessDefaultNetwork();
+ method public int getRestrictBackgroundStatus();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered();
+ method public boolean isDefaultNetworkActive();
+ method @Deprecated public static boolean isNetworkTypeValid(int);
+ method public void registerBestMatchingNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent);
+ method public void releaseNetworkRequest(@NonNull android.app.PendingIntent);
+ method public void removeDefaultNetworkActiveListener(@NonNull android.net.ConnectivityManager.OnNetworkActiveListener);
+ method @Deprecated public void reportBadNetwork(@Nullable android.net.Network);
+ method public void reportNetworkConnectivity(@Nullable android.net.Network, boolean);
+ method public boolean requestBandwidthUpdate(@NonNull android.net.Network);
+ method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback);
+ method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+ method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, int);
+ method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler, int);
+ method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent);
+ method @Deprecated public void setNetworkPreference(int);
+ method @Deprecated public static boolean setProcessDefaultNetwork(@Nullable android.net.Network);
+ method public void unregisterNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback);
+ method public void unregisterNetworkCallback(@NonNull android.app.PendingIntent);
+ field @Deprecated public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
+ field public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL";
+ field public static final String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED";
+ field @Deprecated public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
+ field @Deprecated public static final int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
+ field public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
+ field public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
+ field @Deprecated public static final String EXTRA_EXTRA_INFO = "extraInfo";
+ field @Deprecated public static final String EXTRA_IS_FAILOVER = "isFailover";
+ field public static final String EXTRA_NETWORK = "android.net.extra.NETWORK";
+ field @Deprecated public static final String EXTRA_NETWORK_INFO = "networkInfo";
+ field public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST";
+ field @Deprecated public static final String EXTRA_NETWORK_TYPE = "networkType";
+ field public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity";
+ field @Deprecated public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
+ field public static final String EXTRA_REASON = "reason";
+ field public static final int MULTIPATH_PREFERENCE_HANDOVER = 1; // 0x1
+ field public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 4; // 0x4
+ field public static final int MULTIPATH_PREFERENCE_RELIABILITY = 2; // 0x2
+ field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
+ field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
+ field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
+ field @Deprecated public static final int TYPE_BLUETOOTH = 7; // 0x7
+ field @Deprecated public static final int TYPE_DUMMY = 8; // 0x8
+ field @Deprecated public static final int TYPE_ETHERNET = 9; // 0x9
+ field @Deprecated public static final int TYPE_MOBILE = 0; // 0x0
+ field @Deprecated public static final int TYPE_MOBILE_DUN = 4; // 0x4
+ field @Deprecated public static final int TYPE_MOBILE_HIPRI = 5; // 0x5
+ field @Deprecated public static final int TYPE_MOBILE_MMS = 2; // 0x2
+ field @Deprecated public static final int TYPE_MOBILE_SUPL = 3; // 0x3
+ field @Deprecated public static final int TYPE_VPN = 17; // 0x11
+ field @Deprecated public static final int TYPE_WIFI = 1; // 0x1
+ field @Deprecated public static final int TYPE_WIMAX = 6; // 0x6
+ }
+
+ public static class ConnectivityManager.NetworkCallback {
+ ctor public ConnectivityManager.NetworkCallback();
+ ctor public ConnectivityManager.NetworkCallback(int);
+ method public void onAvailable(@NonNull android.net.Network);
+ method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean);
+ method public void onCapabilitiesChanged(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities);
+ method public void onLinkPropertiesChanged(@NonNull android.net.Network, @NonNull android.net.LinkProperties);
+ method public void onLosing(@NonNull android.net.Network, int);
+ method public void onLost(@NonNull android.net.Network);
+ method public void onUnavailable();
+ field public static final int FLAG_INCLUDE_LOCATION_INFO = 1; // 0x1
+ }
+
+ public static interface ConnectivityManager.OnNetworkActiveListener {
+ method public void onNetworkActive();
+ }
+
+ public class DhcpInfo implements android.os.Parcelable {
+ ctor public DhcpInfo();
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.DhcpInfo> CREATOR;
+ field public int dns1;
+ field public int dns2;
+ field public int gateway;
+ field public int ipAddress;
+ field public int leaseDuration;
+ field public int netmask;
+ field public int serverAddress;
+ }
+
+ public final class DnsResolver {
+ method @NonNull public static android.net.DnsResolver getInstance();
+ method public void query(@Nullable android.net.Network, @NonNull String, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super java.util.List<java.net.InetAddress>>);
+ method public void query(@Nullable android.net.Network, @NonNull String, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super java.util.List<java.net.InetAddress>>);
+ method public void rawQuery(@Nullable android.net.Network, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super byte[]>);
+ method public void rawQuery(@Nullable android.net.Network, @NonNull String, int, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback<? super byte[]>);
+ field public static final int CLASS_IN = 1; // 0x1
+ field public static final int ERROR_PARSE = 0; // 0x0
+ field public static final int ERROR_SYSTEM = 1; // 0x1
+ field public static final int FLAG_EMPTY = 0; // 0x0
+ field public static final int FLAG_NO_CACHE_LOOKUP = 4; // 0x4
+ field public static final int FLAG_NO_CACHE_STORE = 2; // 0x2
+ field public static final int FLAG_NO_RETRY = 1; // 0x1
+ field public static final int TYPE_A = 1; // 0x1
+ field public static final int TYPE_AAAA = 28; // 0x1c
+ }
+
+ public static interface DnsResolver.Callback<T> {
+ method public void onAnswer(@NonNull T, int);
+ method public void onError(@NonNull android.net.DnsResolver.DnsException);
+ }
+
+ public static class DnsResolver.DnsException extends java.lang.Exception {
+ ctor public DnsResolver.DnsException(int, @Nullable Throwable);
+ field public final int code;
+ }
+
+ public class InetAddresses {
+ method public static boolean isNumericAddress(@NonNull String);
+ method @NonNull public static java.net.InetAddress parseNumericAddress(@NonNull String);
+ }
+
+ public final class IpConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.net.ProxyInfo getHttpProxy();
+ method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.IpConfiguration> CREATOR;
+ }
+
+ public static final class IpConfiguration.Builder {
+ ctor public IpConfiguration.Builder();
+ method @NonNull public android.net.IpConfiguration build();
+ method @NonNull public android.net.IpConfiguration.Builder setHttpProxy(@Nullable android.net.ProxyInfo);
+ method @NonNull public android.net.IpConfiguration.Builder setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+ }
+
+ public final class IpPrefix implements android.os.Parcelable {
+ ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
+ method public boolean contains(@NonNull java.net.InetAddress);
+ method public int describeContents();
+ method @NonNull public java.net.InetAddress getAddress();
+ method @IntRange(from=0, to=128) public int getPrefixLength();
+ method @NonNull public byte[] getRawAddress();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.IpPrefix> CREATOR;
+ }
+
+ public class LinkAddress implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.net.InetAddress getAddress();
+ method public int getFlags();
+ method @IntRange(from=0, to=128) public int getPrefixLength();
+ method public int getScope();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.LinkAddress> CREATOR;
+ }
+
+ public final class LinkProperties implements android.os.Parcelable {
+ ctor public LinkProperties();
+ method public boolean addRoute(@NonNull android.net.RouteInfo);
+ method public void clear();
+ method public int describeContents();
+ method @Nullable public java.net.Inet4Address getDhcpServerAddress();
+ method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
+ method @Nullable public String getDomains();
+ method @Nullable public android.net.ProxyInfo getHttpProxy();
+ method @Nullable public String getInterfaceName();
+ method @NonNull public java.util.List<android.net.LinkAddress> getLinkAddresses();
+ method public int getMtu();
+ method @Nullable public android.net.IpPrefix getNat64Prefix();
+ method @Nullable public String getPrivateDnsServerName();
+ method @NonNull public java.util.List<android.net.RouteInfo> getRoutes();
+ method public boolean isPrivateDnsActive();
+ method public boolean isWakeOnLanSupported();
+ method public void setDhcpServerAddress(@Nullable java.net.Inet4Address);
+ method public void setDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
+ method public void setDomains(@Nullable String);
+ method public void setHttpProxy(@Nullable android.net.ProxyInfo);
+ method public void setInterfaceName(@Nullable String);
+ method public void setLinkAddresses(@NonNull java.util.Collection<android.net.LinkAddress>);
+ method public void setMtu(int);
+ method public void setNat64Prefix(@Nullable android.net.IpPrefix);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.LinkProperties> CREATOR;
+ }
+
+ public final class MacAddress implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public static android.net.MacAddress fromBytes(@NonNull byte[]);
+ method @NonNull public static android.net.MacAddress fromString(@NonNull String);
+ method public int getAddressType();
+ method @Nullable public java.net.Inet6Address getLinkLocalIpv6FromEui48Mac();
+ method public boolean isLocallyAssigned();
+ method public boolean matches(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
+ method @NonNull public byte[] toByteArray();
+ method @NonNull public String toOuiString();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.net.MacAddress BROADCAST_ADDRESS;
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.MacAddress> CREATOR;
+ field public static final int TYPE_BROADCAST = 3; // 0x3
+ field public static final int TYPE_MULTICAST = 2; // 0x2
+ field public static final int TYPE_UNICAST = 1; // 0x1
+ }
+
+ public class Network implements android.os.Parcelable {
+ method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException;
+ method public void bindSocket(java.net.Socket) throws java.io.IOException;
+ method public void bindSocket(java.io.FileDescriptor) throws java.io.IOException;
+ method public int describeContents();
+ method public static android.net.Network fromNetworkHandle(long);
+ method public java.net.InetAddress[] getAllByName(String) throws java.net.UnknownHostException;
+ method public java.net.InetAddress getByName(String) throws java.net.UnknownHostException;
+ method public long getNetworkHandle();
+ method public javax.net.SocketFactory getSocketFactory();
+ method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException;
+ method public java.net.URLConnection openConnection(java.net.URL, java.net.Proxy) throws java.io.IOException;
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.Network> CREATOR;
+ }
+
+ public final class NetworkCapabilities implements android.os.Parcelable {
+ ctor public NetworkCapabilities();
+ ctor public NetworkCapabilities(android.net.NetworkCapabilities);
+ method public int describeContents();
+ method @NonNull public int[] getCapabilities();
+ method @NonNull public int[] getEnterpriseIds();
+ method public int getLinkDownstreamBandwidthKbps();
+ method public int getLinkUpstreamBandwidthKbps();
+ method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
+ method public int getOwnerUid();
+ method public int getSignalStrength();
+ method @Nullable public android.net.TransportInfo getTransportInfo();
+ method public boolean hasCapability(int);
+ method public boolean hasEnterpriseId(int);
+ method public boolean hasTransport(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
+ field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11
+ field public static final int NET_CAPABILITY_CBS = 5; // 0x5
+ field public static final int NET_CAPABILITY_DUN = 2; // 0x2
+ field public static final int NET_CAPABILITY_EIMS = 10; // 0xa
+ field public static final int NET_CAPABILITY_ENTERPRISE = 29; // 0x1d
+ field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13
+ field public static final int NET_CAPABILITY_FOTA = 3; // 0x3
+ field public static final int NET_CAPABILITY_HEAD_UNIT = 32; // 0x20
+ field public static final int NET_CAPABILITY_IA = 7; // 0x7
+ field public static final int NET_CAPABILITY_IMS = 4; // 0x4
+ field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc
+ field public static final int NET_CAPABILITY_MCX = 23; // 0x17
+ field public static final int NET_CAPABILITY_MMS = 0; // 0x0
+ field public static final int NET_CAPABILITY_MMTEL = 33; // 0x21
+ field public static final int NET_CAPABILITY_NOT_CONGESTED = 20; // 0x14
+ field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
+ field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd
+ field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12
+ field public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; // 0x15
+ field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf
+ field public static final int NET_CAPABILITY_PRIORITIZE_BANDWIDTH = 35; // 0x23
+ field public static final int NET_CAPABILITY_PRIORITIZE_LATENCY = 34; // 0x22
+ field public static final int NET_CAPABILITY_RCS = 8; // 0x8
+ field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
+ field public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; // 0x19
+ field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe
+ field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10
+ field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6
+ field public static final int NET_CAPABILITY_XCAP = 9; // 0x9
+ field public static final int NET_ENTERPRISE_ID_1 = 1; // 0x1
+ field public static final int NET_ENTERPRISE_ID_2 = 2; // 0x2
+ field public static final int NET_ENTERPRISE_ID_3 = 3; // 0x3
+ field public static final int NET_ENTERPRISE_ID_4 = 4; // 0x4
+ field public static final int NET_ENTERPRISE_ID_5 = 5; // 0x5
+ field public static final int SIGNAL_STRENGTH_UNSPECIFIED = -2147483648; // 0x80000000
+ field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2
+ field public static final int TRANSPORT_CELLULAR = 0; // 0x0
+ field public static final int TRANSPORT_ETHERNET = 3; // 0x3
+ field public static final int TRANSPORT_LOWPAN = 6; // 0x6
+ field public static final int TRANSPORT_THREAD = 9; // 0x9
+ field public static final int TRANSPORT_USB = 8; // 0x8
+ field public static final int TRANSPORT_VPN = 4; // 0x4
+ field public static final int TRANSPORT_WIFI = 1; // 0x1
+ field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5
+ }
+
+ @Deprecated public class NetworkInfo implements android.os.Parcelable {
+ ctor @Deprecated public NetworkInfo(int, int, @Nullable String, @Nullable String);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public android.net.NetworkInfo.DetailedState getDetailedState();
+ method @Deprecated public String getExtraInfo();
+ method @Deprecated public String getReason();
+ method @Deprecated public android.net.NetworkInfo.State getState();
+ method @Deprecated public int getSubtype();
+ method @Deprecated public String getSubtypeName();
+ method @Deprecated public int getType();
+ method @Deprecated public String getTypeName();
+ method @Deprecated public boolean isAvailable();
+ method @Deprecated public boolean isConnected();
+ method @Deprecated public boolean isConnectedOrConnecting();
+ method @Deprecated public boolean isFailover();
+ method @Deprecated public boolean isRoaming();
+ method @Deprecated public void setDetailedState(@NonNull android.net.NetworkInfo.DetailedState, @Nullable String, @Nullable String);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
+ }
+
+ @Deprecated public enum NetworkInfo.DetailedState {
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState BLOCKED;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CAPTIVE_PORTAL_CHECK;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTED;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTING;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTED;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTING;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState FAILED;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState IDLE;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState OBTAINING_IPADDR;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SCANNING;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SUSPENDED;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState VERIFYING_POOR_LINK;
+ }
+
+ @Deprecated public enum NetworkInfo.State {
+ enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTED;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTING;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTED;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTING;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.State SUSPENDED;
+ enum_constant @Deprecated public static final android.net.NetworkInfo.State UNKNOWN;
+ }
+
+ public class NetworkRequest implements android.os.Parcelable {
+ method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkCapabilities);
+ method public int describeContents();
+ method @NonNull public int[] getCapabilities();
+ method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
+ method @NonNull public int[] getTransportTypes();
+ method public boolean hasCapability(int);
+ method public boolean hasTransport(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkRequest> CREATOR;
+ }
+
+ public static class NetworkRequest.Builder {
+ ctor public NetworkRequest.Builder();
+ ctor public NetworkRequest.Builder(@NonNull android.net.NetworkRequest);
+ method public android.net.NetworkRequest.Builder addCapability(int);
+ method public android.net.NetworkRequest.Builder addTransportType(int);
+ method public android.net.NetworkRequest build();
+ method @NonNull public android.net.NetworkRequest.Builder clearCapabilities();
+ method public android.net.NetworkRequest.Builder removeCapability(int);
+ method public android.net.NetworkRequest.Builder removeTransportType(int);
+ method @NonNull public android.net.NetworkRequest.Builder setIncludeOtherUidNetworks(boolean);
+ method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
+ method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
+ }
+
+ public class ParseException extends java.lang.RuntimeException {
+ ctor public ParseException(@NonNull String);
+ ctor public ParseException(@NonNull String, @NonNull Throwable);
+ field public String response;
+ }
+
+ public class ProxyInfo implements android.os.Parcelable {
+ ctor public ProxyInfo(@Nullable android.net.ProxyInfo);
+ method public static android.net.ProxyInfo buildDirectProxy(String, int);
+ method public static android.net.ProxyInfo buildDirectProxy(String, int, java.util.List<java.lang.String>);
+ method public static android.net.ProxyInfo buildPacProxy(android.net.Uri);
+ method @NonNull public static android.net.ProxyInfo buildPacProxy(@NonNull android.net.Uri, int);
+ method public int describeContents();
+ method public String[] getExclusionList();
+ method public String getHost();
+ method public android.net.Uri getPacFileUrl();
+ method public int getPort();
+ method public boolean isValid();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.ProxyInfo> CREATOR;
+ }
+
+ public final class RouteInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.net.IpPrefix getDestination();
+ method @Nullable public java.net.InetAddress getGateway();
+ method @Nullable public String getInterface();
+ method public int getType();
+ method public boolean hasGateway();
+ method public boolean isDefaultRoute();
+ method public boolean matches(java.net.InetAddress);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.RouteInfo> CREATOR;
+ field public static final int RTN_THROW = 9; // 0x9
+ field public static final int RTN_UNICAST = 1; // 0x1
+ field public static final int RTN_UNREACHABLE = 7; // 0x7
+ }
+
+ public abstract class SocketKeepalive implements java.lang.AutoCloseable {
+ method public final void close();
+ method public final void start(@IntRange(from=0xa, to=0xe10) int);
+ method public final void stop();
+ field public static final int ERROR_HARDWARE_ERROR = -31; // 0xffffffe1
+ field public static final int ERROR_INSUFFICIENT_RESOURCES = -32; // 0xffffffe0
+ field public static final int ERROR_INVALID_INTERVAL = -24; // 0xffffffe8
+ field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb
+ field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9
+ field public static final int ERROR_INVALID_NETWORK = -20; // 0xffffffec
+ field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea
+ field public static final int ERROR_INVALID_SOCKET = -25; // 0xffffffe7
+ field public static final int ERROR_SOCKET_NOT_IDLE = -26; // 0xffffffe6
+ field public static final int ERROR_UNSUPPORTED = -30; // 0xffffffe2
+ }
+
+ public static class SocketKeepalive.Callback {
+ ctor public SocketKeepalive.Callback();
+ method public void onDataReceived();
+ method public void onError(int);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ public final class StaticIpConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
+ method @Nullable public String getDomains();
+ method @Nullable public java.net.InetAddress getGateway();
+ method @NonNull public android.net.LinkAddress getIpAddress();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
+ }
+
+ public static final class StaticIpConfiguration.Builder {
+ ctor public StaticIpConfiguration.Builder();
+ method @NonNull public android.net.StaticIpConfiguration build();
+ method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable<java.net.InetAddress>);
+ method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String);
+ method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress);
+ method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@NonNull android.net.LinkAddress);
+ }
+
+ public interface TransportInfo {
+ }
+
+}
+
diff --git a/framework/cronet_disabled/api/lint-baseline.txt b/framework/cronet_disabled/api/lint-baseline.txt
new file mode 100644
index 0000000..2f4004a
--- /dev/null
+++ b/framework/cronet_disabled/api/lint-baseline.txt
@@ -0,0 +1,4 @@
+// Baseline format: 1.0
+VisiblySynchronized: android.net.NetworkInfo#toString():
+ Internal locks must not be exposed (synchronizing on this or class is still
+ externally observable): method android.net.NetworkInfo.toString()
diff --git a/framework/cronet_disabled/api/module-lib-current.txt b/framework/cronet_disabled/api/module-lib-current.txt
new file mode 100644
index 0000000..193bd92
--- /dev/null
+++ b/framework/cronet_disabled/api/module-lib-current.txt
@@ -0,0 +1,239 @@
+// Signature format: 2.0
+package android.net {
+
+ public final class ConnectivityFrameworkInitializer {
+ method public static void registerServiceWrappers();
+ }
+
+ public class ConnectivityManager {
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void addUidToMeteredNetworkAllowList(int);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void addUidToMeteredNetworkDenyList(int);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset();
+ method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshots();
+ method @Nullable public android.net.ProxyInfo getGlobalProxy();
+ method @NonNull public static android.util.Range<java.lang.Integer> getIpSecNetIdRange();
+ method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.LinkProperties getRedactedLinkPropertiesForPackage(@NonNull android.net.LinkProperties, int, @NonNull String);
+ method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.NetworkCapabilities getRedactedNetworkCapabilitiesForPackage(@NonNull android.net.NetworkCapabilities, int, @NonNull String);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackForUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void removeUidFromMeteredNetworkAllowList(int);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void removeUidFromMeteredNetworkDenyList(int);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void replaceFirewallChain(int, @NonNull int[]);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
+ method @Deprecated public boolean requestRouteToHostAddress(int, java.net.InetAddress);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptPartialConnectivity(@NonNull android.net.Network, boolean, boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptUnvalidated(@NonNull android.net.Network, boolean, boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAvoidUnvalidated(@NonNull android.net.Network);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setFirewallChainEnabled(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setLegacyLockdownVpnEnabled(boolean);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreferences(@NonNull android.os.UserHandle, @NonNull java.util.List<android.net.ProfileNetworkPreference>, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setRequireVpnForUids(boolean, @NonNull java.util.Collection<android.util.Range<java.lang.Integer>>);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setUidFirewallRule(int, int, int);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setVpnDefaultForUids(@NonNull String, @NonNull java.util.Collection<android.util.Range<java.lang.Integer>>);
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network);
+ method public void systemReady();
+ field public static final String ACTION_CLEAR_DNS_CACHE = "android.net.action.CLEAR_DNS_CACHE";
+ field public static final String ACTION_PROMPT_LOST_VALIDATION = "android.net.action.PROMPT_LOST_VALIDATION";
+ field public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = "android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
+ field public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED";
+ field public static final int BLOCKED_METERED_REASON_ADMIN_DISABLED = 262144; // 0x40000
+ field public static final int BLOCKED_METERED_REASON_DATA_SAVER = 65536; // 0x10000
+ field public static final int BLOCKED_METERED_REASON_MASK = -65536; // 0xffff0000
+ field public static final int BLOCKED_METERED_REASON_USER_RESTRICTED = 131072; // 0x20000
+ field public static final int BLOCKED_REASON_APP_STANDBY = 4; // 0x4
+ field public static final int BLOCKED_REASON_BATTERY_SAVER = 1; // 0x1
+ field public static final int BLOCKED_REASON_DOZE = 2; // 0x2
+ field public static final int BLOCKED_REASON_LOCKDOWN_VPN = 16; // 0x10
+ field public static final int BLOCKED_REASON_LOW_POWER_STANDBY = 32; // 0x20
+ field public static final int BLOCKED_REASON_NONE = 0; // 0x0
+ field public static final int BLOCKED_REASON_RESTRICTED_MODE = 8; // 0x8
+ field public static final int FIREWALL_CHAIN_DOZABLE = 1; // 0x1
+ field public static final int FIREWALL_CHAIN_LOW_POWER_STANDBY = 5; // 0x5
+ field public static final int FIREWALL_CHAIN_OEM_DENY_1 = 7; // 0x7
+ field public static final int FIREWALL_CHAIN_OEM_DENY_2 = 8; // 0x8
+ field public static final int FIREWALL_CHAIN_OEM_DENY_3 = 9; // 0x9
+ field public static final int FIREWALL_CHAIN_POWERSAVE = 3; // 0x3
+ field public static final int FIREWALL_CHAIN_RESTRICTED = 4; // 0x4
+ field public static final int FIREWALL_CHAIN_STANDBY = 2; // 0x2
+ field public static final int FIREWALL_RULE_ALLOW = 1; // 0x1
+ field public static final int FIREWALL_RULE_DEFAULT = 0; // 0x0
+ field public static final int FIREWALL_RULE_DENY = 2; // 0x2
+ field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0
+ field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1
+ field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE_BLOCKING = 3; // 0x3
+ field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK = 2; // 0x2
+ }
+
+ public static class ConnectivityManager.NetworkCallback {
+ method public void onBlockedStatusChanged(@NonNull android.net.Network, int);
+ }
+
+ public class ConnectivitySettingsManager {
+ method public static void clearGlobalProxy(@NonNull android.content.Context);
+ method @Nullable public static String getCaptivePortalHttpUrl(@NonNull android.content.Context);
+ method public static int getCaptivePortalMode(@NonNull android.content.Context, int);
+ method @NonNull public static java.time.Duration getConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method @NonNull public static android.util.Range<java.lang.Integer> getDnsResolverSampleRanges(@NonNull android.content.Context);
+ method @NonNull public static java.time.Duration getDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method public static int getDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, int);
+ method @Nullable public static android.net.ProxyInfo getGlobalProxy(@NonNull android.content.Context);
+ method public static long getIngressRateLimitInBytesPerSecond(@NonNull android.content.Context);
+ method @NonNull public static java.time.Duration getMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method public static boolean getMobileDataAlwaysOn(@NonNull android.content.Context, boolean);
+ method @NonNull public static java.util.Set<java.lang.Integer> getMobileDataPreferredUids(@NonNull android.content.Context);
+ method public static int getNetworkAvoidBadWifi(@NonNull android.content.Context);
+ method @Nullable public static String getNetworkMeteredMultipathPreference(@NonNull android.content.Context);
+ method public static int getNetworkSwitchNotificationMaximumDailyCount(@NonNull android.content.Context, int);
+ method @NonNull public static java.time.Duration getNetworkSwitchNotificationRateDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method @NonNull public static String getPrivateDnsDefaultMode(@NonNull android.content.Context);
+ method @Nullable public static String getPrivateDnsHostname(@NonNull android.content.Context);
+ method public static int getPrivateDnsMode(@NonNull android.content.Context);
+ method @NonNull public static java.util.Set<java.lang.Integer> getUidsAllowedOnRestrictedNetworks(@NonNull android.content.Context);
+ method public static boolean getWifiAlwaysRequested(@NonNull android.content.Context, boolean);
+ method @NonNull public static java.time.Duration getWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method public static void setCaptivePortalHttpUrl(@NonNull android.content.Context, @Nullable String);
+ method public static void setCaptivePortalMode(@NonNull android.content.Context, int);
+ method public static void setConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method public static void setDnsResolverSampleRanges(@NonNull android.content.Context, @NonNull android.util.Range<java.lang.Integer>);
+ method public static void setDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method public static void setDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, @IntRange(from=0, to=100) int);
+ method public static void setGlobalProxy(@NonNull android.content.Context, @NonNull android.net.ProxyInfo);
+ method public static void setIngressRateLimitInBytesPerSecond(@NonNull android.content.Context, @IntRange(from=-1L, to=4294967295L) long);
+ method public static void setMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method public static void setMobileDataAlwaysOn(@NonNull android.content.Context, boolean);
+ method public static void setMobileDataPreferredUids(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.Integer>);
+ method public static void setNetworkAvoidBadWifi(@NonNull android.content.Context, int);
+ method public static void setNetworkMeteredMultipathPreference(@NonNull android.content.Context, @NonNull String);
+ method public static void setNetworkSwitchNotificationMaximumDailyCount(@NonNull android.content.Context, @IntRange(from=0) int);
+ method public static void setNetworkSwitchNotificationRateDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method public static void setPrivateDnsDefaultMode(@NonNull android.content.Context, @NonNull int);
+ method public static void setPrivateDnsHostname(@NonNull android.content.Context, @Nullable String);
+ method public static void setPrivateDnsMode(@NonNull android.content.Context, int);
+ method public static void setUidsAllowedOnRestrictedNetworks(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.Integer>);
+ method public static void setWifiAlwaysRequested(@NonNull android.content.Context, boolean);
+ method public static void setWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
+ field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
+ field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0
+ field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1
+ field public static final int NETWORK_AVOID_BAD_WIFI_AVOID = 2; // 0x2
+ field public static final int NETWORK_AVOID_BAD_WIFI_IGNORE = 0; // 0x0
+ field public static final int NETWORK_AVOID_BAD_WIFI_PROMPT = 1; // 0x1
+ field public static final int PRIVATE_DNS_MODE_OFF = 1; // 0x1
+ field public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; // 0x2
+ field public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; // 0x3
+ }
+
+ public final class DhcpOption implements android.os.Parcelable {
+ ctor public DhcpOption(byte, @Nullable byte[]);
+ method public int describeContents();
+ method public byte getType();
+ method @Nullable public byte[] getValue();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.DhcpOption> CREATOR;
+ }
+
+ public final class NetworkAgentConfig implements android.os.Parcelable {
+ method @Nullable public String getSubscriberId();
+ method public boolean isBypassableVpn();
+ method public boolean isVpnValidationRequired();
+ }
+
+ public static final class NetworkAgentConfig.Builder {
+ method @NonNull public android.net.NetworkAgentConfig.Builder setBypassableVpn(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setLocalRoutesExcludedForVpn(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setVpnRequiresValidation(boolean);
+ }
+
+ public final class NetworkCapabilities implements android.os.Parcelable {
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public java.util.Set<java.lang.Integer> getAllowedUids();
+ method @Nullable public java.util.Set<android.util.Range<java.lang.Integer>> getUids();
+ method public boolean hasForbiddenCapability(int);
+ field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL
+ field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L
+ field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L
+ field public static final long REDACT_FOR_NETWORK_SETTINGS = 4L; // 0x4L
+ field public static final long REDACT_NONE = 0L; // 0x0L
+ field public static final int TRANSPORT_TEST = 7; // 0x7
+ }
+
+ public static final class NetworkCapabilities.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAllowedUids(@NonNull java.util.Set<java.lang.Integer>);
+ method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
+ }
+
+ public class NetworkRequest implements android.os.Parcelable {
+ method @NonNull public int[] getEnterpriseIds();
+ method @NonNull public int[] getForbiddenCapabilities();
+ method public boolean hasEnterpriseId(int);
+ method public boolean hasForbiddenCapability(int);
+ }
+
+ public static class NetworkRequest.Builder {
+ method @NonNull public android.net.NetworkRequest.Builder addForbiddenCapability(int);
+ method @NonNull public android.net.NetworkRequest.Builder removeForbiddenCapability(int);
+ method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
+ }
+
+ public final class ProfileNetworkPreference implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public int[] getExcludedUids();
+ method @NonNull public int[] getIncludedUids();
+ method public int getPreference();
+ method public int getPreferenceEnterpriseId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.ProfileNetworkPreference> CREATOR;
+ }
+
+ public static final class ProfileNetworkPreference.Builder {
+ ctor public ProfileNetworkPreference.Builder();
+ method @NonNull public android.net.ProfileNetworkPreference build();
+ method @NonNull public android.net.ProfileNetworkPreference.Builder setExcludedUids(@NonNull int[]);
+ method @NonNull public android.net.ProfileNetworkPreference.Builder setIncludedUids(@NonNull int[]);
+ method @NonNull public android.net.ProfileNetworkPreference.Builder setPreference(int);
+ method @NonNull public android.net.ProfileNetworkPreference.Builder setPreferenceEnterpriseId(int);
+ }
+
+ public final class TestNetworkInterface implements android.os.Parcelable {
+ ctor public TestNetworkInterface(@NonNull android.os.ParcelFileDescriptor, @NonNull String);
+ method public int describeContents();
+ method @NonNull public android.os.ParcelFileDescriptor getFileDescriptor();
+ method @NonNull public String getInterfaceName();
+ method @Nullable public android.net.MacAddress getMacAddress();
+ method public int getMtu();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.TestNetworkInterface> CREATOR;
+ }
+
+ public class TestNetworkManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public android.net.TestNetworkInterface createTapInterface();
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection<android.net.LinkAddress>);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public void teardownTestNetwork(@NonNull android.net.Network);
+ field public static final String TEST_TAP_PREFIX = "testtap";
+ }
+
+ public final class TestNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ ctor public TestNetworkSpecifier(@NonNull String);
+ method public int describeContents();
+ method @Nullable public String getInterfaceName();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.TestNetworkSpecifier> CREATOR;
+ }
+
+ public interface TransportInfo {
+ method public default long getApplicableRedactions();
+ method @NonNull public default android.net.TransportInfo makeCopy(long);
+ }
+
+ public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
+ ctor @Deprecated public VpnTransportInfo(int, @Nullable String);
+ method @Nullable public String getSessionId();
+ method @NonNull public android.net.VpnTransportInfo makeCopy(long);
+ }
+
+}
+
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/module-lib-removed.txt b/framework/cronet_disabled/api/module-lib-removed.txt
similarity index 100%
rename from Tethering/common/TetheringLib/cronet_enabled/api/module-lib-removed.txt
rename to framework/cronet_disabled/api/module-lib-removed.txt
diff --git a/framework/cronet_disabled/api/removed.txt b/framework/cronet_disabled/api/removed.txt
new file mode 100644
index 0000000..303a1e6
--- /dev/null
+++ b/framework/cronet_disabled/api/removed.txt
@@ -0,0 +1,11 @@
+// Signature format: 2.0
+package android.net {
+
+ public class ConnectivityManager {
+ method @Deprecated public boolean requestRouteToHost(int, int);
+ method @Deprecated public int startUsingNetworkFeature(int, String);
+ method @Deprecated public int stopUsingNetworkFeature(int, String);
+ }
+
+}
+
diff --git a/framework/cronet_disabled/api/system-current.txt b/framework/cronet_disabled/api/system-current.txt
new file mode 100644
index 0000000..4a2ed8a
--- /dev/null
+++ b/framework/cronet_disabled/api/system-current.txt
@@ -0,0 +1,544 @@
+// Signature format: 2.0
+package android.net {
+
+ public class CaptivePortal implements android.os.Parcelable {
+ method @Deprecated public void logEvent(int, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork();
+ method public void useNetwork();
+ field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64
+ field public static final int APP_RETURN_DISMISSED = 0; // 0x0
+ field public static final int APP_RETURN_UNWANTED = 1; // 0x1
+ field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
+ }
+
+ public final class CaptivePortalData implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getByteLimit();
+ method public long getExpiryTimeMillis();
+ method public long getRefreshTimeMillis();
+ method @Nullable public android.net.Uri getUserPortalUrl();
+ method public int getUserPortalUrlSource();
+ method @Nullable public CharSequence getVenueFriendlyName();
+ method @Nullable public android.net.Uri getVenueInfoUrl();
+ method public int getVenueInfoUrlSource();
+ method public boolean isCaptive();
+ method public boolean isSessionExtendable();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; // 0x0
+ field public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; // 0x1
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
+ }
+
+ public static class CaptivePortalData.Builder {
+ ctor public CaptivePortalData.Builder();
+ ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
+ method @NonNull public android.net.CaptivePortalData build();
+ method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
+ method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
+ method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
+ method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
+ method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
+ method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
+ method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int);
+ method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable CharSequence);
+ method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
+ method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int);
+ }
+
+ public class ConnectivityManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
+ method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCaptivePortalServerUrl();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkProvider(@NonNull android.net.NetworkProvider);
+ method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull java.util.concurrent.Executor, @NonNull android.net.QosCallback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
+ method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean);
+ method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi();
+ method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider);
+ method public void unregisterQosCallback(@NonNull android.net.QosCallback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
+ field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
+ field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
+ field public static final int TETHERING_BLUETOOTH = 2; // 0x2
+ field public static final int TETHERING_USB = 1; // 0x1
+ field public static final int TETHERING_WIFI = 0; // 0x0
+ field @Deprecated public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
+ field @Deprecated public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
+ field @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
+ field public static final int TYPE_NONE = -1; // 0xffffffff
+ field @Deprecated public static final int TYPE_PROXY = 16; // 0x10
+ field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd
+ }
+
+ @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback {
+ ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback();
+ method @Deprecated public void onTetheringFailed();
+ method @Deprecated public void onTetheringStarted();
+ }
+
+ @Deprecated public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
+ method @Deprecated public void onTetheringEntitlementResult(int);
+ }
+
+ @Deprecated public abstract static class ConnectivityManager.OnTetheringEventCallback {
+ ctor @Deprecated public ConnectivityManager.OnTetheringEventCallback();
+ method @Deprecated public void onUpstreamChanged(@Nullable android.net.Network);
+ }
+
+ public final class DscpPolicy implements android.os.Parcelable {
+ method @Nullable public java.net.InetAddress getDestinationAddress();
+ method @Nullable public android.util.Range<java.lang.Integer> getDestinationPortRange();
+ method public int getDscpValue();
+ method public int getPolicyId();
+ method public int getProtocol();
+ method @Nullable public java.net.InetAddress getSourceAddress();
+ method public int getSourcePort();
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.DscpPolicy> CREATOR;
+ field public static final int PROTOCOL_ANY = -1; // 0xffffffff
+ field public static final int SOURCE_PORT_ANY = -1; // 0xffffffff
+ }
+
+ public static final class DscpPolicy.Builder {
+ ctor public DscpPolicy.Builder(int, int);
+ method @NonNull public android.net.DscpPolicy build();
+ method @NonNull public android.net.DscpPolicy.Builder setDestinationAddress(@NonNull java.net.InetAddress);
+ method @NonNull public android.net.DscpPolicy.Builder setDestinationPortRange(@NonNull android.util.Range<java.lang.Integer>);
+ method @NonNull public android.net.DscpPolicy.Builder setProtocol(int);
+ method @NonNull public android.net.DscpPolicy.Builder setSourceAddress(@NonNull java.net.InetAddress);
+ method @NonNull public android.net.DscpPolicy.Builder setSourcePort(int);
+ }
+
+ public final class InvalidPacketException extends java.lang.Exception {
+ ctor public InvalidPacketException(int);
+ method public int getError();
+ field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb
+ field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9
+ field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea
+ }
+
+ public final class IpConfiguration implements android.os.Parcelable {
+ ctor public IpConfiguration();
+ ctor public IpConfiguration(@NonNull android.net.IpConfiguration);
+ method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment();
+ method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings();
+ method public void setHttpProxy(@Nullable android.net.ProxyInfo);
+ method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment);
+ method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings);
+ method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+ }
+
+ public enum IpConfiguration.IpAssignment {
+ enum_constant public static final android.net.IpConfiguration.IpAssignment DHCP;
+ enum_constant public static final android.net.IpConfiguration.IpAssignment STATIC;
+ enum_constant public static final android.net.IpConfiguration.IpAssignment UNASSIGNED;
+ }
+
+ public enum IpConfiguration.ProxySettings {
+ enum_constant public static final android.net.IpConfiguration.ProxySettings NONE;
+ enum_constant public static final android.net.IpConfiguration.ProxySettings PAC;
+ enum_constant public static final android.net.IpConfiguration.ProxySettings STATIC;
+ enum_constant public static final android.net.IpConfiguration.ProxySettings UNASSIGNED;
+ }
+
+ public final class IpPrefix implements android.os.Parcelable {
+ ctor public IpPrefix(@NonNull String);
+ }
+
+ public class KeepalivePacketData {
+ ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull byte[]) throws android.net.InvalidPacketException;
+ method @NonNull public java.net.InetAddress getDstAddress();
+ method public int getDstPort();
+ method @NonNull public byte[] getPacket();
+ method @NonNull public java.net.InetAddress getSrcAddress();
+ method public int getSrcPort();
+ }
+
+ public class LinkAddress implements android.os.Parcelable {
+ ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
+ ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long);
+ ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
+ ctor public LinkAddress(@NonNull String);
+ ctor public LinkAddress(@NonNull String, int, int);
+ method public long getDeprecationTime();
+ method public long getExpirationTime();
+ method public boolean isGlobalPreferred();
+ method public boolean isIpv4();
+ method public boolean isIpv6();
+ method public boolean isSameAddressAs(@Nullable android.net.LinkAddress);
+ field public static final long LIFETIME_PERMANENT = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final long LIFETIME_UNKNOWN = -1L; // 0xffffffffffffffffL
+ }
+
+ public final class LinkProperties implements android.os.Parcelable {
+ ctor public LinkProperties(@Nullable android.net.LinkProperties);
+ ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean);
+ method public boolean addDnsServer(@NonNull java.net.InetAddress);
+ method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
+ method public boolean addPcscfServer(@NonNull java.net.InetAddress);
+ method @NonNull public java.util.List<java.net.InetAddress> getAddresses();
+ method @NonNull public java.util.List<java.lang.String> getAllInterfaceNames();
+ method @NonNull public java.util.List<android.net.LinkAddress> getAllLinkAddresses();
+ method @NonNull public java.util.List<android.net.RouteInfo> getAllRoutes();
+ method @Nullable public android.net.Uri getCaptivePortalApiUrl();
+ method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
+ method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
+ method @Nullable public String getTcpBufferSizes();
+ method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
+ method public boolean hasGlobalIpv6Address();
+ method public boolean hasIpv4Address();
+ method public boolean hasIpv4DefaultRoute();
+ method public boolean hasIpv4DnsServer();
+ method public boolean hasIpv6DefaultRoute();
+ method public boolean hasIpv6DnsServer();
+ method public boolean isIpv4Provisioned();
+ method public boolean isIpv6Provisioned();
+ method public boolean isProvisioned();
+ method public boolean isReachable(@NonNull java.net.InetAddress);
+ method public boolean removeDnsServer(@NonNull java.net.InetAddress);
+ method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
+ method public boolean removeRoute(@NonNull android.net.RouteInfo);
+ method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
+ method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
+ method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
+ method public void setPrivateDnsServerName(@Nullable String);
+ method public void setTcpBufferSizes(@Nullable String);
+ method public void setUsePrivateDns(boolean);
+ method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
+ }
+
+ public final class NattKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
+ ctor public NattKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException;
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NattKeepalivePacketData> CREATOR;
+ }
+
+ public class Network implements android.os.Parcelable {
+ ctor public Network(@NonNull android.net.Network);
+ method public int getNetId();
+ method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
+ }
+
+ public abstract class NetworkAgent {
+ ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider);
+ ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkScore, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider);
+ method @Nullable public android.net.Network getNetwork();
+ method public void markConnected();
+ method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData);
+ method public void onAutomaticReconnectDisabled();
+ method public void onBandwidthUpdateRequested();
+ method public void onDscpPolicyStatusUpdated(int, int);
+ method public void onNetworkCreated();
+ method public void onNetworkDestroyed();
+ method public void onNetworkUnwanted();
+ method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter);
+ method public void onQosCallbackUnregistered(int);
+ method public void onRemoveKeepalivePacketFilter(int);
+ method public void onSaveAcceptUnvalidated(boolean);
+ method public void onSignalStrengthThresholdsUpdated(@NonNull int[]);
+ method public void onStartSocketKeepalive(int, @NonNull java.time.Duration, @NonNull android.net.KeepalivePacketData);
+ method public void onStopSocketKeepalive(int);
+ method public void onValidationStatus(int, @Nullable android.net.Uri);
+ method @NonNull public android.net.Network register();
+ method public void sendAddDscpPolicy(@NonNull android.net.DscpPolicy);
+ method public void sendLinkProperties(@NonNull android.net.LinkProperties);
+ method public void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
+ method public void sendNetworkScore(@NonNull android.net.NetworkScore);
+ method public void sendNetworkScore(@IntRange(from=0, to=99) int);
+ method public final void sendQosCallbackError(int, int);
+ method public final void sendQosSessionAvailable(int, int, @NonNull android.net.QosSessionAttributes);
+ method public final void sendQosSessionLost(int, int, int);
+ method public void sendRemoveAllDscpPolicies();
+ method public void sendRemoveDscpPolicy(int);
+ method public final void sendSocketKeepaliveEvent(int, int);
+ method @Deprecated public void setLegacySubtype(int, @NonNull String);
+ method public void setLingerDuration(@NonNull java.time.Duration);
+ method public void setTeardownDelayMillis(@IntRange(from=0, to=0x1388) int);
+ method public void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
+ method public void unregister();
+ method public void unregisterAfterReplacement(@IntRange(from=0, to=0x1388) int);
+ field public static final int DSCP_POLICY_STATUS_DELETED = 4; // 0x4
+ field public static final int DSCP_POLICY_STATUS_INSUFFICIENT_PROCESSING_RESOURCES = 3; // 0x3
+ field public static final int DSCP_POLICY_STATUS_POLICY_NOT_FOUND = 5; // 0x5
+ field public static final int DSCP_POLICY_STATUS_REQUESTED_CLASSIFIER_NOT_SUPPORTED = 2; // 0x2
+ field public static final int DSCP_POLICY_STATUS_REQUEST_DECLINED = 1; // 0x1
+ field public static final int DSCP_POLICY_STATUS_SUCCESS = 0; // 0x0
+ field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
+ field public static final int VALIDATION_STATUS_VALID = 1; // 0x1
+ }
+
+ public final class NetworkAgentConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getLegacyType();
+ method @NonNull public String getLegacyTypeName();
+ method public boolean isExplicitlySelected();
+ method public boolean isPartialConnectivityAcceptable();
+ method public boolean isUnvalidatedConnectivityAcceptable();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkAgentConfig> CREATOR;
+ }
+
+ public static final class NetworkAgentConfig.Builder {
+ ctor public NetworkAgentConfig.Builder();
+ method @NonNull public android.net.NetworkAgentConfig build();
+ method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyExtraInfo(@NonNull String);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubType(int);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubTypeName(@NonNull String);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setNat64DetectionEnabled(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setProvisioningNotificationEnabled(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setUnvalidatedConnectivityAcceptable(boolean);
+ }
+
+ public final class NetworkCapabilities implements android.os.Parcelable {
+ method @NonNull public int[] getAdministratorUids();
+ method @Nullable public static String getCapabilityCarrierName(int);
+ method @Nullable public String getSsid();
+ method @NonNull public java.util.Set<java.lang.Integer> getSubscriptionIds();
+ method @NonNull public int[] getTransportTypes();
+ method @Nullable public java.util.List<android.net.Network> getUnderlyingNetworks();
+ method public boolean isPrivateDnsBroken();
+ method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
+ field public static final int NET_CAPABILITY_BIP = 31; // 0x1f
+ field public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; // 0x1c
+ field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
+ field public static final int NET_CAPABILITY_OEM_PRIVATE = 26; // 0x1a
+ field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18
+ field public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; // 0x1b
+ field public static final int NET_CAPABILITY_VSIM = 30; // 0x1e
+ }
+
+ public static final class NetworkCapabilities.Builder {
+ ctor public NetworkCapabilities.Builder();
+ ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities);
+ method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int);
+ method @NonNull public android.net.NetworkCapabilities.Builder addEnterpriseId(int);
+ method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int);
+ method @NonNull public android.net.NetworkCapabilities build();
+ method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int);
+ method @NonNull public android.net.NetworkCapabilities.Builder removeEnterpriseId(int);
+ method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]);
+ method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int);
+ method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int);
+ method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String);
+ method @NonNull public android.net.NetworkCapabilities.Builder setSubscriptionIds(@NonNull java.util.Set<java.lang.Integer>);
+ method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
+ method @NonNull public static android.net.NetworkCapabilities.Builder withoutDefaultCapabilities();
+ }
+
+ public class NetworkProvider {
+ ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest);
+ method public int getProviderId();
+ method public void onNetworkRequestWithdrawn(@NonNull android.net.NetworkRequest);
+ method public void onNetworkRequested(@NonNull android.net.NetworkRequest, @IntRange(from=0, to=99) int, int);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void registerNetworkOffer(@NonNull android.net.NetworkScore, @NonNull android.net.NetworkCapabilities, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkProvider.NetworkOfferCallback);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void unregisterNetworkOffer(@NonNull android.net.NetworkProvider.NetworkOfferCallback);
+ field public static final int ID_NONE = -1; // 0xffffffff
+ }
+
+ public static interface NetworkProvider.NetworkOfferCallback {
+ method public void onNetworkNeeded(@NonNull android.net.NetworkRequest);
+ method public void onNetworkUnneeded(@NonNull android.net.NetworkRequest);
+ }
+
+ public class NetworkReleasedException extends java.lang.Exception {
+ ctor public NetworkReleasedException();
+ }
+
+ public class NetworkRequest implements android.os.Parcelable {
+ method @Nullable public String getRequestorPackageName();
+ method public int getRequestorUid();
+ }
+
+ public static class NetworkRequest.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int);
+ method @NonNull public android.net.NetworkRequest.Builder setSubscriptionIds(@NonNull java.util.Set<java.lang.Integer>);
+ }
+
+ public final class NetworkScore implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getKeepConnectedReason();
+ method public int getLegacyInt();
+ method public boolean isExiting();
+ method public boolean isTransportPrimary();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkScore> CREATOR;
+ field public static final int KEEP_CONNECTED_FOR_HANDOVER = 1; // 0x1
+ field public static final int KEEP_CONNECTED_NONE = 0; // 0x0
+ }
+
+ public static final class NetworkScore.Builder {
+ ctor public NetworkScore.Builder();
+ method @NonNull public android.net.NetworkScore build();
+ method @NonNull public android.net.NetworkScore.Builder setExiting(boolean);
+ method @NonNull public android.net.NetworkScore.Builder setKeepConnectedReason(int);
+ method @NonNull public android.net.NetworkScore.Builder setLegacyInt(int);
+ method @NonNull public android.net.NetworkScore.Builder setTransportPrimary(boolean);
+ }
+
+ public final class OemNetworkPreferences implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getNetworkPreferences();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.OemNetworkPreferences> CREATOR;
+ field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID = 1; // 0x1
+ field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK = 2; // 0x2
+ field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY = 3; // 0x3
+ field public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4; // 0x4
+ field public static final int OEM_NETWORK_PREFERENCE_UNINITIALIZED = 0; // 0x0
+ }
+
+ public static final class OemNetworkPreferences.Builder {
+ ctor public OemNetworkPreferences.Builder();
+ ctor public OemNetworkPreferences.Builder(@NonNull android.net.OemNetworkPreferences);
+ method @NonNull public android.net.OemNetworkPreferences.Builder addNetworkPreference(@NonNull String, int);
+ method @NonNull public android.net.OemNetworkPreferences build();
+ method @NonNull public android.net.OemNetworkPreferences.Builder clearNetworkPreference(@NonNull String);
+ }
+
+ public abstract class QosCallback {
+ ctor public QosCallback();
+ method public void onError(@NonNull android.net.QosCallbackException);
+ method public void onQosSessionAvailable(@NonNull android.net.QosSession, @NonNull android.net.QosSessionAttributes);
+ method public void onQosSessionLost(@NonNull android.net.QosSession);
+ }
+
+ public static class QosCallback.QosCallbackRegistrationException extends java.lang.RuntimeException {
+ }
+
+ public final class QosCallbackException extends java.lang.Exception {
+ ctor public QosCallbackException(@NonNull String);
+ ctor public QosCallbackException(@NonNull Throwable);
+ }
+
+ public abstract class QosFilter {
+ method @NonNull public abstract android.net.Network getNetwork();
+ method public abstract boolean matchesLocalAddress(@NonNull java.net.InetAddress, int, int);
+ method public boolean matchesProtocol(int);
+ method public abstract boolean matchesRemoteAddress(@NonNull java.net.InetAddress, int, int);
+ }
+
+ public final class QosSession implements android.os.Parcelable {
+ ctor public QosSession(int, int);
+ method public int describeContents();
+ method public int getSessionId();
+ method public int getSessionType();
+ method public long getUniqueId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.QosSession> CREATOR;
+ field public static final int TYPE_EPS_BEARER = 1; // 0x1
+ field public static final int TYPE_NR_BEARER = 2; // 0x2
+ }
+
+ public interface QosSessionAttributes {
+ }
+
+ public final class QosSocketInfo implements android.os.Parcelable {
+ ctor public QosSocketInfo(@NonNull android.net.Network, @NonNull java.net.Socket) throws java.io.IOException;
+ ctor public QosSocketInfo(@NonNull android.net.Network, @NonNull java.net.DatagramSocket) throws java.io.IOException;
+ method public int describeContents();
+ method @NonNull public java.net.InetSocketAddress getLocalSocketAddress();
+ method @NonNull public android.net.Network getNetwork();
+ method @Nullable public java.net.InetSocketAddress getRemoteSocketAddress();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.QosSocketInfo> CREATOR;
+ }
+
+ public final class RouteInfo implements android.os.Parcelable {
+ ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int);
+ ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int, int);
+ method public int getMtu();
+ }
+
+ public abstract class SocketKeepalive implements java.lang.AutoCloseable {
+ method public final void start(@IntRange(from=0xa, to=0xe10) int, int, @Nullable android.net.Network);
+ field public static final int ERROR_NO_SUCH_SLOT = -33; // 0xffffffdf
+ field public static final int FLAG_AUTOMATIC_ON_OFF = 1; // 0x1
+ field public static final int SUCCESS = 0; // 0x0
+ }
+
+ public class SocketLocalAddressChangedException extends java.lang.Exception {
+ ctor public SocketLocalAddressChangedException();
+ }
+
+ public class SocketNotBoundException extends java.lang.Exception {
+ ctor public SocketNotBoundException();
+ }
+
+ public class SocketNotConnectedException extends java.lang.Exception {
+ ctor public SocketNotConnectedException();
+ }
+
+ public class SocketRemoteAddressChangedException extends java.lang.Exception {
+ ctor public SocketRemoteAddressChangedException();
+ }
+
+ public final class StaticIpConfiguration implements android.os.Parcelable {
+ ctor public StaticIpConfiguration();
+ ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+ method public void addDnsServer(@NonNull java.net.InetAddress);
+ method public void clear();
+ method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(@Nullable String);
+ }
+
+ public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
+ ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException;
+ method public int describeContents();
+ method public int getIpTos();
+ method public int getIpTtl();
+ method public int getTcpAck();
+ method public int getTcpSeq();
+ method public int getTcpWindow();
+ method public int getTcpWindowScale();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.TcpKeepalivePacketData> CREATOR;
+ }
+
+ public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
+ ctor public VpnTransportInfo(int, @Nullable String, boolean, boolean);
+ method public boolean areLongLivedTcpConnectionsExpensive();
+ method public int describeContents();
+ method public int getType();
+ method public boolean isBypassable();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR;
+ }
+
+}
+
+package android.net.apf {
+
+ public final class ApfCapabilities implements android.os.Parcelable {
+ ctor public ApfCapabilities(int, int, int);
+ method public int describeContents();
+ method public static boolean getApfDrop8023Frames();
+ method @NonNull public static int[] getApfEtherTypeBlackList();
+ method public boolean hasDataAccess();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.apf.ApfCapabilities> CREATOR;
+ field public final int apfPacketFormat;
+ field public final int apfVersionSupported;
+ field public final int maximumApfProgramSize;
+ }
+
+}
+
diff --git a/framework/cronet_disabled/api/system-lint-baseline.txt b/framework/cronet_disabled/api/system-lint-baseline.txt
new file mode 100644
index 0000000..9a97707
--- /dev/null
+++ b/framework/cronet_disabled/api/system-lint-baseline.txt
@@ -0,0 +1 @@
+// Baseline format: 1.0
diff --git a/Tethering/common/TetheringLib/cronet_enabled/api/system-removed.txt b/framework/cronet_disabled/api/system-removed.txt
similarity index 100%
rename from Tethering/common/TetheringLib/cronet_enabled/api/system-removed.txt
rename to framework/cronet_disabled/api/system-removed.txt
diff --git a/framework/jarjar-excludes.txt b/framework/jarjar-excludes.txt
index 1311765..9b48d57 100644
--- a/framework/jarjar-excludes.txt
+++ b/framework/jarjar-excludes.txt
@@ -23,3 +23,8 @@
# TODO (b/217115866): add jarjar rules for Nearby
android\.nearby\..+
+
+# Don't touch anything that's already under android.net.http (cronet)
+# This is required since android.net.http contains api classes and hidden classes.
+# TODO: Remove this after hidden classes are moved to different package
+android\.net\.http\..+
\ No newline at end of file
diff --git a/framework/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp
index 38e0059..ca297e5 100644
--- a/framework/jni/android_net_NetworkUtils.cpp
+++ b/framework/jni/android_net_NetworkUtils.cpp
@@ -23,6 +23,7 @@
#include <netinet/in.h>
#include <string.h>
+#include <bpf/BpfClassic.h>
#include <DnsProxydProtocol.h> // NETID_USE_LOCAL_NAMESERVERS
#include <nativehelper/JNIPlatformHelp.h>
#include <utils/Log.h>
@@ -55,11 +56,10 @@
static void android_net_utils_attachDropAllBPFFilter(JNIEnv *env, jclass clazz, jobject javaFd)
{
- struct sock_filter filter_code[] = {
- // Reject all.
- BPF_STMT(BPF_RET | BPF_K, 0)
+ static struct sock_filter filter_code[] = {
+ BPF_REJECT,
};
- struct sock_fprog filter = {
+ static const struct sock_fprog filter = {
sizeof(filter_code) / sizeof(filter_code[0]),
filter_code,
};
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 40defd4..381a18a 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -1502,6 +1502,22 @@
}
/**
+ * Temporarily set automaticOnOff keeplaive TCP polling alarm timer to 1 second.
+ *
+ * TODO: Remove this when the TCP polling design is replaced with callback.
+ * @param timeMs The time of expiry, with System.currentTimeMillis() base. The value should be
+ * set no more than 5 minutes in the future.
+ * @hide
+ */
+ public void setTestLowTcpPollingTimerForKeepalive(long timeMs) {
+ try {
+ mService.setTestLowTcpPollingTimerForKeepalive(timeMs);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Informs ConnectivityService of whether the legacy lockdown VPN, as implemented by
* LockdownVpnTracker, is in use. This is deprecated for new devices starting from Android 12
* but is still supported for backwards compatibility.
@@ -2213,9 +2229,13 @@
/** The requested keepalive was successfully started. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void onStarted() {}
+ /** The keepalive was resumed after being paused by the system. */
+ public void onResumed() {}
/** The keepalive was successfully stopped. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void onStopped() {}
+ /** The keepalive was paused automatically by the system. */
+ public void onPaused() {}
/** An error occurred. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void onError(int error) {}
@@ -2279,16 +2299,12 @@
private final ISocketKeepaliveCallback mCallback;
private final ExecutorService mExecutor;
- private volatile Integer mSlot;
-
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void stop() {
try {
mExecutor.execute(() -> {
try {
- if (mSlot != null) {
- mService.stopKeepalive(mNetwork, mSlot);
- }
+ mService.stopKeepalive(mCallback);
} catch (RemoteException e) {
Log.e(TAG, "Error stopping packet keepalive: ", e);
throw e.rethrowFromSystemServer();
@@ -2306,11 +2322,10 @@
mExecutor = Executors.newSingleThreadExecutor();
mCallback = new ISocketKeepaliveCallback.Stub() {
@Override
- public void onStarted(int slot) {
+ public void onStarted() {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> {
- mSlot = slot;
callback.onStarted();
});
} finally {
@@ -2319,11 +2334,22 @@
}
@Override
+ public void onResumed() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ callback.onResumed();
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
public void onStopped() {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> {
- mSlot = null;
callback.onStopped();
});
} finally {
@@ -2333,11 +2359,23 @@
}
@Override
+ public void onPaused() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ callback.onPaused();
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ mExecutor.shutdown();
+ }
+
+ @Override
public void onError(int error) {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> {
- mSlot = null;
callback.onError(error);
});
} finally {
@@ -2483,7 +2521,7 @@
@RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD)
public @NonNull SocketKeepalive createSocketKeepalive(@NonNull Network network,
@NonNull Socket socket,
- @NonNull Executor executor,
+ @NonNull @CallbackExecutor Executor executor,
@NonNull Callback callback) {
ParcelFileDescriptor dup;
try {
@@ -4863,6 +4901,7 @@
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS})
public void registerSystemDefaultNetworkCallback(@NonNull NetworkCallback networkCallback,
@NonNull Handler handler) {
@@ -5455,9 +5494,9 @@
* @return {@code uid} if the connection is found and the app has permission to observe it
* (e.g., if it is associated with the calling VPN app's VpnService tunnel) or {@link
* android.os.Process#INVALID_UID} if the connection is not found.
- * @throws {@link SecurityException} if the caller is not the active VpnService for the current
+ * @throws SecurityException if the caller is not the active VpnService for the current
* user.
- * @throws {@link IllegalArgumentException} if an unsupported protocol is requested.
+ * @throws IllegalArgumentException if an unsupported protocol is requested.
*/
public int getConnectionOwnerUid(
int protocol, @NonNull InetSocketAddress local, @NonNull InetSocketAddress remote) {
@@ -5997,6 +6036,30 @@
}
/**
+ * Get firewall rule of specified firewall chain on specified uid.
+ *
+ * @param chain target chain.
+ * @param uid target uid
+ * @return either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
+ * @throws UnsupportedOperationException if called on pre-T devices.
+ * @throws ServiceSpecificException in case of failure, with an error code indicating the
+ * cause of the failure.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_STACK,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+ })
+ public int getUidFirewallRule(@FirewallChain final int chain, final int uid) {
+ try {
+ return mService.getUidFirewallRule(chain, uid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Enables or disables the specified firewall chain.
*
* @param chain target chain.
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index 7db231e..1372e9a 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -188,12 +188,12 @@
void startNattKeepaliveWithFd(in Network network, in ParcelFileDescriptor pfd, int resourceId,
int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr,
- String dstAddr, boolean automaticOnOffKeepalives);
+ String dstAddr, boolean automaticOnOffKeepalives, in Network underpinnedNetwork);
void startTcpKeepalive(in Network network, in ParcelFileDescriptor pfd, int intervalSeconds,
in ISocketKeepaliveCallback cb);
- void stopKeepalive(in Network network, int slot);
+ void stopKeepalive(in ISocketKeepaliveCallback cb);
String getCaptivePortalServerUrl();
@@ -242,6 +242,8 @@
void setUidFirewallRule(int chain, int uid, int rule);
+ int getUidFirewallRule(int chain, int uid);
+
void setFirewallChainEnabled(int chain, boolean enable);
boolean getFirewallChainEnabled(int chain);
@@ -251,4 +253,6 @@
IBinder getCompanionDeviceManagerProxyService();
void setVpnNetworkPreference(String session, in UidRange[] ranges);
+
+ void setTestLowTcpPollingTimerForKeepalive(long timeMs);
}
diff --git a/framework/src/android/net/ISocketKeepaliveCallback.aidl b/framework/src/android/net/ISocketKeepaliveCallback.aidl
index 020fbca..0a1de6c 100644
--- a/framework/src/android/net/ISocketKeepaliveCallback.aidl
+++ b/framework/src/android/net/ISocketKeepaliveCallback.aidl
@@ -24,11 +24,15 @@
oneway interface ISocketKeepaliveCallback
{
/** The keepalive was successfully started. */
- void onStarted(int slot);
+ void onStarted();
/** The keepalive was successfully stopped. */
void onStopped();
/** The keepalive was stopped because of an error. */
void onError(int error);
/** The keepalive on a TCP socket was stopped because the socket received data. */
void onDataReceived();
+ /** The keepalive was paused by the system because it's not necessary right now. */
+ void onPaused();
+ /** The keepalive was resumed by the system after being suspended. */
+ void onResumed();
}
diff --git a/framework/src/android/net/LinkAddress.java b/framework/src/android/net/LinkAddress.java
index d48b8c7..90f55b3 100644
--- a/framework/src/android/net/LinkAddress.java
+++ b/framework/src/android/net/LinkAddress.java
@@ -487,17 +487,23 @@
*/
@SystemApi
public boolean isGlobalPreferred() {
- /**
- * Note that addresses flagged as IFA_F_OPTIMISTIC are
- * simultaneously flagged as IFA_F_TENTATIVE (when the tentative
- * state has cleared either DAD has succeeded or failed, and both
- * flags are cleared regardless).
- */
- int flags = getFlags();
return (scope == RT_SCOPE_UNIVERSE
&& !isIpv6ULA()
- && (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L
- && ((flags & IFA_F_TENTATIVE) == 0L || (flags & IFA_F_OPTIMISTIC) != 0L));
+ && isPreferred());
+ }
+
+ /**
+ * Checks if the address is a preferred address.
+ *
+ * @hide
+ */
+ public boolean isPreferred() {
+ // Note that addresses flagged as IFA_F_OPTIMISTIC are simultaneously flagged as
+ // IFA_F_TENTATIVE (when the tentative state has cleared either DAD has succeeded or
+ // failed, and both flags are cleared regardless).
+ int flags = getFlags();
+ return (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L
+ && ((flags & IFA_F_TENTATIVE) == 0L || (flags & IFA_F_OPTIMISTIC) != 0L);
}
/**
diff --git a/framework/src/android/net/LinkProperties.java b/framework/src/android/net/LinkProperties.java
index b7ee846..e0926e9 100644
--- a/framework/src/android/net/LinkProperties.java
+++ b/framework/src/android/net/LinkProperties.java
@@ -16,19 +16,18 @@
package android.net;
+import static android.net.connectivity.ConnectivityCompatChanges.EXCLUDED_ROUTES;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.LinkPropertiesUtils;
@@ -58,17 +57,6 @@
*
*/
public final class LinkProperties implements Parcelable {
- /**
- * The {@link #getRoutes()} now can contain excluded as well as included routes. Use
- * {@link RouteInfo#getType()} to determine route type.
- *
- * @hide
- */
- @ChangeId
- @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
- @VisibleForTesting
- public static final long EXCLUDED_ROUTES = 186082280;
-
// The interface described by the network link.
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private String mIfaceName;
diff --git a/framework/src/android/net/NattSocketKeepalive.java b/framework/src/android/net/NattSocketKeepalive.java
index 4d45e70..a83b5b4 100644
--- a/framework/src/android/net/NattSocketKeepalive.java
+++ b/framework/src/android/net/NattSocketKeepalive.java
@@ -66,10 +66,12 @@
* the supplied {@link Callback} will see a call to
* {@link Callback#onError(int)} with {@link #ERROR_INVALID_INTERVAL}.
* @param flags Flags to enable/disable available options on this keepalive.
+ * @param underpinnedNetwork The underpinned network of this keepalive.
+ *
* @hide
*/
@Override
- protected void startImpl(int intervalSec, int flags) {
+ protected void startImpl(int intervalSec, int flags, Network underpinnedNetwork) {
if (0 != (flags & ~FLAG_AUTOMATIC_ON_OFF)) {
throw new IllegalArgumentException("Illegal flag value for "
+ this.getClass().getSimpleName() + " : " + flags);
@@ -79,7 +81,8 @@
try {
mService.startNattKeepaliveWithFd(mNetwork, mPfd, mResourceId,
intervalSec, mCallback, mSource.getHostAddress(),
- mDestination.getHostAddress(), automaticOnOffKeepalives);
+ mDestination.getHostAddress(), automaticOnOffKeepalives,
+ underpinnedNetwork);
} catch (RemoteException e) {
Log.e(TAG, "Error starting socket keepalive: ", e);
throw e.rethrowFromSystemServer();
@@ -91,9 +94,7 @@
protected void stopImpl() {
mExecutor.execute(() -> {
try {
- if (mSlot != null) {
- mService.stopKeepalive(mNetwork, mSlot);
- }
+ mService.stopKeepalive(mCallback);
} catch (RemoteException e) {
Log.e(TAG, "Error stopping socket keepalive: ", e);
throw e.rethrowFromSystemServer();
diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java
index 732bd87..177f7e3 100644
--- a/framework/src/android/net/NetworkAgent.java
+++ b/framework/src/android/net/NetworkAgent.java
@@ -283,7 +283,6 @@
* arg2 = interval in seconds
* obj = KeepalivePacketData object describing the data to be sent
*
- * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
* @hide
*/
public static final int CMD_START_SOCKET_KEEPALIVE = BASE + 11;
@@ -291,7 +290,9 @@
/**
* Requests that the specified keepalive packet be stopped.
*
- * arg1 = hardware slot number of the keepalive to stop.
+ * arg1 = unused
+ * arg2 = error code (SUCCESS)
+ * obj = callback to identify the keepalive
*
* Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
* @hide
@@ -434,6 +435,14 @@
public static final int CMD_DSCP_POLICY_STATUS = BASE + 28;
/**
+ * Sent by the NetworkAgent to ConnectivityService to notify that this network is expected to be
+ * replaced within the specified time by a similar network.
+ * arg1 = timeout in milliseconds
+ * @hide
+ */
+ public static final int EVENT_UNREGISTER_AFTER_REPLACEMENT = BASE + 29;
+
+ /**
* DSCP policy was successfully added.
*/
public static final int DSCP_POLICY_STATUS_SUCCESS = 0;
@@ -475,28 +484,6 @@
@Retention(RetentionPolicy.SOURCE)
public @interface DscpPolicyStatus {}
- /**
- * Sent by the NetworkAgent to ConnectivityService to notify that this network is expected to be
- * replaced within the specified time by a similar network.
- * arg1 = timeout in milliseconds
- * @hide
- */
- public static final int EVENT_UNREGISTER_AFTER_REPLACEMENT = BASE + 29;
-
- /**
- * Sent by AutomaticOnOffKeepaliveTracker periodically (when relevant) to trigger monitor
- * automatic keepalive request.
- *
- * NATT keepalives have an automatic mode where the system only sends keepalive packets when
- * TCP sockets are open over a VPN. The system will check periodically for presence of
- * such open sockets, and this message is what triggers the re-evaluation.
- *
- * arg1 = hardware slot number of the keepalive
- * obj = {@link Network} that the keepalive is started on.
- * @hide
- */
- public static final int CMD_MONITOR_AUTOMATIC_KEEPALIVE = BASE + 30;
-
private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
config.legacyTypeName, config.legacySubTypeName);
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index e70d75d..3cc9c65 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -53,18 +53,70 @@
import java.util.StringJoiner;
/**
- * Representation of the capabilities of an active network. Instances are
- * typically obtained through
- * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)}
- * or {@link ConnectivityManager#getNetworkCapabilities(Network)}.
- * <p>
- * This replaces the old {@link ConnectivityManager#TYPE_MOBILE} method of
- * network selection. Rather than indicate a need for Wi-Fi because an
- * application needs high bandwidth and risk obsolescence when a new, fast
- * network appears (like LTE), the application should specify it needs high
- * bandwidth. Similarly if an application needs an unmetered network for a bulk
- * transfer it can specify that rather than assuming all cellular based
- * connections are metered and all Wi-Fi based connections are not.
+ * Representation of the capabilities of an active network.
+ *
+ * <p>@see <a href="https://developer.android.com/training/basics/network-ops/reading-network-state>
+ * this general guide</a> on how to use NetworkCapabilities and related classes.
+ *
+ * <p>NetworkCapabilities represent what a network can do and what its
+ * characteristics are like. The principal attribute of NetworkCapabilities
+ * is in the capabilities bits, which are checked with
+ * {@link #hasCapability(int)}. See the list of capabilities and each
+ * capability for a description of what it means.
+ *
+ * <p>Some prime examples include {@code NET_CAPABILITY_MMS}, which means that the
+ * network is capable of sending MMS. A network without this capability
+ * is not capable of sending MMS.
+ * <p>The {@code NET_CAPABILITY_INTERNET} capability means that the network is
+ * configured to reach the general Internet. It may or may not actually
+ * provide connectivity ; the {@code NET_CAPABILITY_VALIDATED} bit indicates that
+ * the system found actual connectivity to the general Internet the last
+ * time it checked. Apps interested in actual connectivity should usually
+ * look at both these capabilities.
+ * <p>The {@code NET_CAPABILITY_NOT_METERED} capability is set for networks that
+ * do not bill the user for consumption of bytes. Applications are
+ * encouraged to consult this to determine appropriate usage, and to
+ * limit usage of metered network where possible, including deferring
+ * big downloads until such a time that an unmetered network is connected.
+ * Also see {@link android.app.job.JobScheduler} to help with scheduling such
+ * downloads, in particular
+ * {@link android.app.job.JobInfo.Builder#setRequiredNetwork(NetworkRequest)}.
+ * <p>NetworkCapabilities contain a number of other capabilities that
+ * represent what modern networks can and can't do. Look up the individual
+ * capabilities in this class to learn about each of them.
+ *
+ * <p>NetworkCapabilities typically represent attributes that can apply to
+ * any network. The attributes that apply only to specific transports like
+ * cellular or Wi-Fi can be found in the specifier (for requestable attributes)
+ * or in the transport info (for non-requestable ones). See
+ * {@link #getNetworkSpecifier} and {@link #getTransportInfo}. An app would
+ * downcast these to the specific class for the transport they need if they
+ * are interested in transport-specific attributes. Also see
+ * {@link android.net.wifi.WifiNetworkSpecifier} or
+ * {@link android.net.wifi.WifiInfo} for some examples of each of these.
+ *
+ * <p>NetworkCapabilities also contains other attributes like the estimated
+ * upstream and downstream bandwidth and the specific transport of that
+ * network (e.g. {@link #TRANSPORT_CELLULAR}). Generally, apps should normally
+ * have little reason to check for the type of transport ; for example, to
+ * query whether a network costs money to the user, do not look at the
+ * transport, but instead look at the absence or presence of
+ * {@link #NET_CAPABILITY_NOT_METERED} which will correctly account for
+ * metered Wi-Fis and free of charge cell connections.
+ *
+ * <p>The system communicates with apps about connected networks and uses
+ * NetworkCapabilities to express these capabilities about these networks.
+ * Apps should register callbacks with the {@link ConnectivityManager#requestNetwork}
+ * or {@link ConnectivityManager#registerNetworkCallback} family of methods
+ * to learn about the capabilities of a network on a continuous basis
+ * and be able to react to changes to capabilities. For quick debugging Android also
+ * provides {@link ConnectivityManager#getNetworkCapabilities(Network)},
+ * but the dynamic nature of networking makes this ill-suited to production
+ * code since capabilities obtained in this way can go stale immediately.
+ *
+ * <p>Also see {@link NetworkRequest} which uses the same capabilities
+ * together with {@link ConnectivityManager#requestNetwork} for how to
+ * request the system brings up the kind of network your application needs.
*/
public final class NetworkCapabilities implements Parcelable {
private static final String TAG = "NetworkCapabilities";
@@ -622,11 +674,19 @@
/**
* Indicates that this network should be able to prioritize latency for the internet.
+ *
+ * Starting with {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, requesting this capability with
+ * {@link ConnectivityManager#requestNetwork} requires declaration in the self-certified
+ * network capabilities. See {@link NetworkRequest} for the self-certification documentation.
*/
public static final int NET_CAPABILITY_PRIORITIZE_LATENCY = 34;
/**
* Indicates that this network should be able to prioritize bandwidth for the internet.
+ *
+ * Starting with {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, requesting this capability with
+ * {@link ConnectivityManager#requestNetwork} requires declaration in the self-certified
+ * network capabilities. See {@link NetworkRequest} for the self-certification documentation.
*/
public static final int NET_CAPABILITY_PRIORITIZE_BANDWIDTH = 35;
@@ -697,10 +757,10 @@
NET_CAPABILITY_PARTIAL_CONNECTIVITY);
/**
- * Capabilities that are allowed for test networks. This list must be set so that it is safe
- * for an unprivileged user to create a network with these capabilities via shell. As such,
- * it must never contain capabilities that are generally useful to the system, such as
- * INTERNET, IMS, SUPL, etc.
+ * Capabilities that are allowed for all test networks. This list must be set so that it is safe
+ * for an unprivileged user to create a network with these capabilities via shell. As such, it
+ * must never contain capabilities that are generally useful to the system, such as INTERNET,
+ * IMS, SUPL, etc.
*/
private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES =
BitUtils.packBitList(
@@ -714,6 +774,14 @@
NET_CAPABILITY_NOT_VCN_MANAGED);
/**
+ * Extra allowed capabilities for test networks that do not have TRANSPORT_CELLULAR. Test
+ * networks with TRANSPORT_CELLULAR must not have those capabilities in order to mitigate
+ * the risk of being used by running apps.
+ */
+ private static final long TEST_NETWORKS_EXTRA_ALLOWED_CAPABILITIES_ON_NON_CELL =
+ BitUtils.packBitList(NET_CAPABILITY_CBS, NET_CAPABILITY_DUN, NET_CAPABILITY_RCS);
+
+ /**
* Adds the given capability to this {@code NetworkCapability} instance.
* Note that when searching for a network to satisfy a request, all capabilities
* requested must be satisfied.
@@ -1066,14 +1134,22 @@
mTransportTypes =
(originalTransportTypes & UNRESTRICTED_TEST_NETWORKS_ALLOWED_TRANSPORTS)
| (1 << TRANSPORT_TEST);
-
- // SubIds are only allowed for Test Networks that only declare TRANSPORT_TEST.
- setSubscriptionIds(originalSubIds);
} else {
// If the test network is restricted, then it may declare any transport.
mTransportTypes = (originalTransportTypes | (1 << TRANSPORT_TEST));
}
+
+ if (hasSingleTransport(TRANSPORT_TEST)) {
+ // SubIds are only allowed for Test Networks that only declare TRANSPORT_TEST.
+ setSubscriptionIds(originalSubIds);
+ }
+
mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES;
+ if (!hasTransport(TRANSPORT_CELLULAR)) {
+ mNetworkCapabilities |=
+ (originalCapabilities & TEST_NETWORKS_EXTRA_ALLOWED_CAPABILITIES_ON_NON_CELL);
+ }
+
mNetworkSpecifier = originalSpecifier;
mSignalStrength = originalSignalStrength;
mTransportInfo = originalTransportInfo;
@@ -1110,6 +1186,7 @@
TRANSPORT_LOWPAN,
TRANSPORT_TEST,
TRANSPORT_USB,
+ TRANSPORT_THREAD,
})
public @interface Transport { }
@@ -1161,10 +1238,15 @@
*/
public static final int TRANSPORT_USB = 8;
+ /**
+ * Indicates this network uses a Thread transport.
+ */
+ public static final int TRANSPORT_THREAD = 9;
+
/** @hide */
public static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
/** @hide */
- public static final int MAX_TRANSPORT = TRANSPORT_USB;
+ public static final int MAX_TRANSPORT = TRANSPORT_THREAD;
private static final int ALL_VALID_TRANSPORTS;
static {
@@ -1189,7 +1271,8 @@
"WIFI_AWARE",
"LOWPAN",
"TEST",
- "USB"
+ "USB",
+ "THREAD",
};
/**
diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java
index b7a6076..6c351d0 100644
--- a/framework/src/android/net/NetworkRequest.java
+++ b/framework/src/android/net/NetworkRequest.java
@@ -54,9 +54,92 @@
import java.util.Set;
/**
- * Defines a request for a network, made through {@link NetworkRequest.Builder} and used
- * to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes
- * via {@link ConnectivityManager#registerNetworkCallback}.
+ * An object describing a network that the application is interested in.
+ *
+ * <p>@see <a href="https://developer.android.com/training/basics/network-ops/reading-network-state>
+ * this general guide</a> on how to use NetworkCapabilities and related classes.
+ *
+ * NetworkRequest defines a request for a network, made through
+ * {@link NetworkRequest.Builder} and used to request a network via
+ * {@link ConnectivityManager#requestNetwork} or to listen for changes
+ * via the {@link ConnectivityManager#registerNetworkCallback} family of
+ * functions.
+ *
+ * <p>{@link ConnectivityManager#requestNetwork} will try to find a connected
+ * network matching the NetworkRequest, and return it if there is one.
+ * As long as the request is outstanding, the system will try to find the best
+ * possible network that matches the request. The request will keep up the
+ * currently best connected network, and if a better one is found (e.g. cheaper
+ * or faster) the system will bring up that better network to better serve the
+ * request. A request filed with {@link ConnectivityManager#requestNetwork} will
+ * only match one network at a time (the one the system thinks is best), even if
+ * other networks can match the request that are being kept up by other requests.
+ *
+ * For example, an application needing a network with
+ * {@link NetworkCapabilities#NET_CAPABILITY_INTERNET} should use
+ * {@link ConnectivityManager#requestNetwork} to request the system keeps one up.
+ * A general cellular network can satisfy this request, but if the system finds
+ * a free Wi-Fi network which is expected to be faster, it will try and connect
+ * to that Wi-Fi network and switch the request over to it once it is connected.
+ * The cell network may stay connected if there are outstanding requests (from
+ * the same app or from other apps on the system) that match the cell network
+ * but not the Wi-Fi network, such as a request with {@link NetworkCapabilities#NET_CAPABILITY_MMS}.
+ *
+ * When a network is no longer needed to serve any request, the system can
+ * tear it down at any time and usually does so immediately, so make sure to
+ * keep up requests for the networks your app needs.
+ *
+ * <p>By contrast, requests filed with {@link ConnectivityManager#registerNetworkCallback}
+ * will receive callbacks for all matching networks, and will not cause the system to
+ * keep up the networks they match. Use this to listen to networks that the device is
+ * connected to, but that you don't want the system to keep up for your use case.
+ *
+ * <p>Applications build a NetworkRequest and pass it to one of the
+ * {@link ConnectivityManager} methods above together with a
+ * {@link ConnectivityManager.NetworkCallback} object. The callback
+ * will then start receiving method calls about networks that match
+ * the request.
+ *
+ * <p>Networks are brought up and/or matched according to the capabilities
+ * set in the builder. For example, a request with
+ * {@link NetworkCapabilities#NET_CAPABILITY_MMS} lets the system match
+ * and/or bring up a network that is capable to send MMS. A request with
+ * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} matches a network
+ * that doesn't charge the user for usage. See
+ * {@link NetworkCapabilities} for a list of capabilities and their
+ * description.
+ *
+ * <p>While all capabilities can be matched with the
+ * {@link ConnectivityManager#registerNetworkCallback} family of methods,
+ * not all capabilities can be used to request that the system brings
+ * up a network with {@link ConnectivityManager#requestNetwork}. For example,
+ * an application cannot use {@link ConnectivityManager#requestNetwork} to
+ * ask the system to bring up a network with
+ * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}, because the
+ * system won't know if a network has a captive portal before it connects
+ * to that network. Similarly, some capabilities may require a specific
+ * permission or privilege to be requested.
+ *
+ * Look up the specific capability and the {@link ConnectivityManager#requestNetwork}
+ * method for limitations applicable to each capability.
+ *
+ * <p>Also, starting with {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, some capabilities
+ * require the application to self-certify by explicitly adding the
+ * {@link android.content.pm.PackageManager#PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES}
+ * property in the AndroidManifest.xml, which points to an XML resource file. In the
+ * XML resource file, the application declares what kind of network capabilities the application
+ * wants to have.
+ *
+ * Here is an example self-certification XML resource file :
+ * <pre>
+ * {@code
+ * <network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ * <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ * <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+ * </network-capabilities-declaration>
+ * }
+ * </pre>
+ * Look up the specific capability to learn whether its usage requires this self-certification.
*/
public class NetworkRequest implements Parcelable {
/**
diff --git a/framework/src/android/net/SocketKeepalive.java b/framework/src/android/net/SocketKeepalive.java
index 90e5e9b..10daf17 100644
--- a/framework/src/android/net/SocketKeepalive.java
+++ b/framework/src/android/net/SocketKeepalive.java
@@ -65,6 +65,12 @@
public static final int SUCCESS = 0;
/**
+ * Success when trying to suspend.
+ * @hide
+ */
+ public static final int SUCCESS_PAUSED = 1;
+
+ /**
* No keepalive. This should only be internally as it indicates There is no keepalive.
* It should not propagate to applications.
* @hide
@@ -249,9 +255,6 @@
@NonNull protected final Executor mExecutor;
/** @hide */
@NonNull protected final ISocketKeepaliveCallback mCallback;
- // TODO: remove slot since mCallback could be used to identify which keepalive to stop.
- /** @hide */
- @Nullable protected Integer mSlot;
/** @hide */
public SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
@@ -263,11 +266,10 @@
mExecutor = executor;
mCallback = new ISocketKeepaliveCallback.Stub() {
@Override
- public void onStarted(int slot) {
+ public void onStarted() {
final long token = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> {
- mSlot = slot;
callback.onStarted();
});
} finally {
@@ -276,11 +278,22 @@
}
@Override
+ public void onResumed() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> {
+ callback.onResumed();
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
public void onStopped() {
final long token = Binder.clearCallingIdentity();
try {
executor.execute(() -> {
- mSlot = null;
callback.onStopped();
});
} finally {
@@ -289,11 +302,22 @@
}
@Override
+ public void onPaused() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> {
+ callback.onPaused();
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
public void onError(int error) {
final long token = Binder.clearCallingIdentity();
try {
executor.execute(() -> {
- mSlot = null;
callback.onError(error);
});
} finally {
@@ -306,7 +330,6 @@
final long token = Binder.clearCallingIdentity();
try {
executor.execute(() -> {
- mSlot = null;
callback.onDataReceived();
});
} finally {
@@ -333,7 +356,7 @@
*/
public final void start(@IntRange(from = MIN_INTERVAL_SEC, to = MAX_INTERVAL_SEC)
int intervalSec) {
- startImpl(intervalSec, 0 /* flags */);
+ startImpl(intervalSec, 0 /* flags */, null /* underpinnedNetwork */);
}
/**
@@ -352,16 +375,20 @@
* the supplied {@link Callback} will see a call to
* {@link Callback#onError(int)} with {@link #ERROR_INVALID_INTERVAL}.
* @param flags Flags to enable/disable available options on this keepalive.
+ * @param underpinnedNetwork an optional network running over mNetwork that this
+ * keepalive is intended to keep up, e.g. an IPSec
+ * tunnel running over mNetwork.
* @hide
*/
@SystemApi(client = PRIVILEGED_APPS)
public final void start(@IntRange(from = MIN_INTERVAL_SEC, to = MAX_INTERVAL_SEC)
- int intervalSec, @StartFlags int flags) {
- startImpl(intervalSec, flags);
+ int intervalSec, @StartFlags int flags, @Nullable Network underpinnedNetwork) {
+ startImpl(intervalSec, flags, underpinnedNetwork);
}
/** @hide */
- protected abstract void startImpl(int intervalSec, @StartFlags int flags);
+ protected abstract void startImpl(int intervalSec, @StartFlags int flags,
+ Network underpinnedNetwork);
/**
* Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped}
@@ -395,8 +422,18 @@
public static class Callback {
/** The requested keepalive was successfully started. */
public void onStarted() {}
+ /**
+ * The keepalive was resumed by the system after being suspended.
+ * @hide
+ **/
+ public void onResumed() {}
/** The keepalive was successfully stopped. */
public void onStopped() {}
+ /**
+ * The keepalive was paused by the system because it's not necessary right now.
+ * @hide
+ **/
+ public void onPaused() {}
/** An error occurred. */
public void onError(@ErrorCode int error) {}
/** The keepalive on a TCP socket was stopped because the socket received data. This is
diff --git a/framework/src/android/net/TcpSocketKeepalive.java b/framework/src/android/net/TcpSocketKeepalive.java
index 51d805e..696889f 100644
--- a/framework/src/android/net/TcpSocketKeepalive.java
+++ b/framework/src/android/net/TcpSocketKeepalive.java
@@ -50,11 +50,17 @@
* acknowledgement.
*/
@Override
- protected void startImpl(int intervalSec, int flags) {
+ protected void startImpl(int intervalSec, int flags, Network underpinnedNetwork) {
if (0 != flags) {
throw new IllegalArgumentException("Illegal flag value for "
+ this.getClass().getSimpleName() + " : " + flags);
}
+
+ if (underpinnedNetwork != null) {
+ throw new IllegalArgumentException("Illegal underpinned network for "
+ + this.getClass().getSimpleName() + " : " + underpinnedNetwork);
+ }
+
mExecutor.execute(() -> {
try {
mService.startTcpKeepalive(mNetwork, mPfd, intervalSec, mCallback);
@@ -69,9 +75,7 @@
protected void stopImpl() {
mExecutor.execute(() -> {
try {
- if (mSlot != null) {
- mService.stopKeepalive(mNetwork, mSlot);
- }
+ mService.stopKeepalive(mCallback);
} catch (RemoteException e) {
Log.e(TAG, "Error stopping packet keepalive: ", e);
throw e.rethrowFromSystemServer();
diff --git a/framework/src/android/net/connectivity/ConnectivityCompatChanges.java b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
new file mode 100644
index 0000000..dfe5867
--- /dev/null
+++ b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 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.connectivity;
+
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.EnabledSince;
+import android.os.Build;
+
+/**
+ * The class contains all CompatChanges for the Connectivity module.
+ *
+ * <p>This is the centralized place for the CompatChanges used in the Connectivity module.
+ * Putting all the CompatChanges in single place makes it possible to manage them under a single
+ * platform_compat_config.
+ * @hide
+ */
+public final class ConnectivityCompatChanges {
+
+ /**
+ * The {@link android.net.LinkProperties#getRoutes()} now can contain excluded as well as
+ * included routes. Use {@link android.net.RouteInfo#getType()} to determine route type.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
+ public static final long EXCLUDED_ROUTES = 186082280;
+
+ /**
+ * When enabled, apps targeting < Android 12 are considered legacy for
+ * the NSD native daemon.
+ * The platform will only keep the daemon running as long as there are
+ * any legacy apps connected.
+ *
+ * After Android 12, direct communication with the native daemon might not work since the native
+ * daemon won't always stay alive. Using the NSD APIs from NsdManager as the replacement is
+ * recommended.
+ * Another alternative could be bundling your own mdns solutions instead of
+ * depending on the system mdns native daemon.
+ *
+ * This compatibility change applies to Android 13 and later only. To toggle behavior on
+ * Android 12 and Android 12L, use RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
+ // This was a platform change ID with value 191844585L before T
+ public static final long RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER = 235355681L;
+
+ /**
+ * The self certified capabilities check should be enabled after android 13.
+ *
+ * <p> See {@link android.net.NetworkCapabilities} for more details.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ public static final long ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION = 266524688;
+
+ /**
+ * Apps targeting < Android 14 use a legacy NSD backend.
+ *
+ * The legacy apps use a legacy native daemon as NsdManager backend, but other apps use a
+ * platform-integrated mDNS implementation as backend.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ public static final long ENABLE_PLATFORM_MDNS_BACKEND = 270306772L;
+ private ConnectivityCompatChanges() {
+ }
+}
diff --git a/nearby/framework/Android.bp b/nearby/framework/Android.bp
index e223b54..278f823 100644
--- a/nearby/framework/Android.bp
+++ b/nearby/framework/Android.bp
@@ -32,10 +32,10 @@
filegroup {
name: "framework-nearby-sources",
+ defaults: ["framework-sources-module-defaults"],
srcs: [
":framework-nearby-java-sources",
],
- visibility: ["//frameworks/base"],
}
// Build of only framework-nearby (not as part of connectivity) for
@@ -45,6 +45,7 @@
srcs: [":framework-nearby-java-sources"],
sdk_version: "module_current",
libs: [
+ "androidx.annotation_annotation",
"framework-annotations-lib",
"framework-bluetooth",
],
diff --git a/nearby/halfsheet/Android.bp b/nearby/halfsheet/Android.bp
index 2d0d327..8011dc6 100644
--- a/nearby/halfsheet/Android.bp
+++ b/nearby/halfsheet/Android.bp
@@ -27,7 +27,7 @@
certificate: ":com.android.nearby.halfsheetcertificate",
libs: [
"framework-bluetooth",
- "framework-connectivity-t",
+ "framework-connectivity-t.impl",
"nearby-service-string",
],
static_libs: [
diff --git a/nearby/halfsheet/res/values-ky/strings.xml b/nearby/halfsheet/res/values-ky/strings.xml
index 812e0e8..b0dfe20 100644
--- a/nearby/halfsheet/res/values-ky/strings.xml
+++ b/nearby/halfsheet/res/values-ky/strings.xml
@@ -25,5 +25,5 @@
<string name="paring_action_save" msgid="6259357442067880136">"Сактоо"</string>
<string name="paring_action_connect" msgid="4801102939608129181">"Туташуу"</string>
<string name="paring_action_launch" msgid="8940808384126591230">"Жөндөө"</string>
- <string name="paring_action_settings" msgid="424875657242864302">"Жөндөөлөр"</string>
+ <string name="paring_action_settings" msgid="424875657242864302">"Параметрлер"</string>
</resources>
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java
index 2a38b8a..07e5776 100644
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/HalfSheetActivity.java
@@ -16,6 +16,8 @@
package com.android.nearby.halfsheet;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+
import static com.android.nearby.halfsheet.fragment.DevicePairingFragment.APP_LAUNCH_FRAGMENT_TYPE;
import static com.android.server.nearby.common.bluetooth.fastpair.FastPairConstants.EXTRA_MODEL_ID;
import static com.android.server.nearby.common.fastpair.service.UserActionHandlerBase.EXTRA_MAC_ADDRESS;
@@ -226,7 +228,8 @@
EXTRA_HALF_SHEET_IS_RETROACTIVE,
getIntent().getBooleanExtra(EXTRA_HALF_SHEET_IS_RETROACTIVE,
false))
- .putExtra(EXTRA_MAC_ADDRESS, mScanFastPairStoreItem.getAddress()));
+ .putExtra(EXTRA_MAC_ADDRESS, mScanFastPairStoreItem.getAddress()),
+ ACCESS_FINE_LOCATION);
}
}
diff --git a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/BroadcastUtils.java b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/BroadcastUtils.java
index 467997c..2f1e90a 100644
--- a/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/BroadcastUtils.java
+++ b/nearby/halfsheet/src/com/android/nearby/halfsheet/utils/BroadcastUtils.java
@@ -31,6 +31,13 @@
context.sendBroadcast(intent);
}
+ /**
+ * Helps send a broadcast with specified receiver permission.
+ */
+ public static void sendBroadcast(Context context, Intent intent, String receiverPermission) {
+ context.sendBroadcast(intent, receiverPermission);
+ }
+
private BroadcastUtils() {
}
}
diff --git a/nearby/tests/cts/fastpair/AndroidManifest.xml b/nearby/tests/cts/fastpair/AndroidManifest.xml
index 96e2783..9e1ec70 100644
--- a/nearby/tests/cts/fastpair/AndroidManifest.xml
+++ b/nearby/tests/cts/fastpair/AndroidManifest.xml
@@ -30,7 +30,5 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.nearby.cts"
android:label="CTS tests for android.nearby Fast Pair">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener"/>
</instrumentation>
</manifest>
diff --git a/nearby/tests/integration/untrusted/src/androidx/test/uiautomator/LogcatWaitMixin.java b/nearby/tests/integration/untrusted/src/androidx/test/uiautomator/LogcatWaitMixin.java
index 86e39dc..8b5ac12 100644
--- a/nearby/tests/integration/untrusted/src/androidx/test/uiautomator/LogcatWaitMixin.java
+++ b/nearby/tests/integration/untrusted/src/androidx/test/uiautomator/LogcatWaitMixin.java
@@ -54,7 +54,7 @@
@NonNull String specificLog, @NonNull Date startTime) {
return new Condition<UiDevice, Boolean>() {
@Override
- Boolean apply(UiDevice device) {
+ public Boolean apply(UiDevice device) {
String logcatLogs;
try {
logcatLogs = device.executeShellCommand("logcat -v time -v year -d");
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/src/android/nearby/fastpair/provider/simulator/app/MainActivity.java b/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/src/android/nearby/fastpair/provider/simulator/app/MainActivity.java
index e916c53..75fafb0 100644
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/src/android/nearby/fastpair/provider/simulator/app/MainActivity.java
+++ b/nearby/tests/multidevices/clients/test_support/fastpair_provider/simulator_app/src/android/nearby/fastpair/provider/simulator/app/MainActivity.java
@@ -657,9 +657,7 @@
int desiredIoCapability = getIoCapabilityFromModelId(modelId);
- mBluetoothController.setIoCapability(
- /*ioCapabilityClassic=*/ desiredIoCapability,
- /*ioCapabilityBLE=*/ desiredIoCapability);
+ mBluetoothController.setIoCapability(desiredIoCapability);
runOnUiThread(() -> {
updateStringStatusView(
@@ -950,9 +948,7 @@
}
// Recover the IO capability.
- mBluetoothController.setIoCapability(
- /*ioCapabilityClassic=*/ IO_CAPABILITY_IO, /*ioCapabilityBLE=*/
- IO_CAPABILITY_KBDISP);
+ mBluetoothController.setIoCapability(IO_CAPABILITY_IO);
super.onDestroy();
}
diff --git a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/bluetooth/BluetoothController.kt b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/bluetooth/BluetoothController.kt
index 0cc0c92..345e8d2 100644
--- a/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/bluetooth/BluetoothController.kt
+++ b/nearby/tests/multidevices/clients/test_support/fastpair_provider/src/android/nearby/fastpair/provider/bluetooth/BluetoothController.kt
@@ -50,23 +50,16 @@
}
/**
- * Sets the Input/Output capability of the device for both classic Bluetooth and BLE operations.
+ * Sets the Input/Output capability of the device for classic Bluetooth operations.
* Note: In order to let changes take effect, this method will make sure the Bluetooth stack is
* restarted by blocking calling thread.
*
* @param ioCapabilityClassic One of {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_NONE},
* ```
* {@link #IO_CAPABILITY_KBDISP} or more in {@link BluetoothAdapter}.
- * @param ioCapabilityBLE
- * ```
- * One of {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_NONE}, {@link
- * ```
- * #IO_CAPABILITY_KBDISP} or more in {@link BluetoothAdapter}.
- * ```
*/
- fun setIoCapability(ioCapabilityClassic: Int, ioCapabilityBLE: Int) {
+ fun setIoCapability(ioCapabilityClassic: Int) {
bluetoothAdapter.ioCapability = ioCapabilityClassic
- bluetoothAdapter.leIoCapability = ioCapabilityBLE
// Toggling airplane mode on/off to restart Bluetooth stack and reset the BLE.
try {
@@ -273,4 +266,4 @@
private const val TURN_AIRPLANE_MODE_OFF = 0
private const val TURN_AIRPLANE_MODE_ON = 1
}
-}
\ No newline at end of file
+}
diff --git a/nearby/tests/multidevices/clients/test_support/snippet_helper/tests/Android.bp b/nearby/tests/multidevices/clients/test_support/snippet_helper/tests/Android.bp
index 284d5c2..ec0392c 100644
--- a/nearby/tests/multidevices/clients/test_support/snippet_helper/tests/Android.bp
+++ b/nearby/tests/multidevices/clients/test_support/snippet_helper/tests/Android.bp
@@ -35,4 +35,5 @@
// timeout in seconds.
timeout: 36000,
},
-}
\ No newline at end of file
+ upstream: true,
+}
diff --git a/nearby/tests/multidevices/host/Android.bp b/nearby/tests/multidevices/host/Android.bp
index b81032d..b6c1c9d 100644
--- a/nearby/tests/multidevices/host/Android.bp
+++ b/nearby/tests/multidevices/host/Android.bp
@@ -22,7 +22,10 @@
name: "NearbyMultiDevicesTestSuite",
main: "suite_main.py",
srcs: ["*.py"],
- libs: ["NearbyMultiDevicesHostHelper"],
+ libs: [
+ "NearbyMultiDevicesHostHelper",
+ "mobly",
+ ],
test_suites: [
"general-tests",
"mts-tethering",
@@ -38,6 +41,11 @@
// Package the JSON metadata with the Mobly test.
"test_data/**/*",
],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
}
python_library_host {
diff --git a/nearby/tests/multidevices/host/AndroidTest.xml b/nearby/tests/multidevices/host/AndroidTest.xml
index c1f6a70..fff0ed1 100644
--- a/nearby/tests/multidevices/host/AndroidTest.xml
+++ b/nearby/tests/multidevices/host/AndroidTest.xml
@@ -42,11 +42,6 @@
<option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
<option name="run-command" value="wm dismiss-keyguard" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.PythonVirtualenvPreparer">
- <!-- Any python dependencies can be specified and will be installed with pip -->
- <!-- TODO(b/225958696): Import python dependencies -->
- <option name="dep-module" value="mobly" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
<option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
<option name="screen-always-on" value="on" />
diff --git a/nearby/tests/multidevices/host/suite_main.py b/nearby/tests/multidevices/host/suite_main.py
index 4f5d48c..9a580fb 100644
--- a/nearby/tests/multidevices/host/suite_main.py
+++ b/nearby/tests/multidevices/host/suite_main.py
@@ -31,11 +31,9 @@
]
-def _valid_argument(arg: str) -> bool:
- return arg.startswith(('--config', '-c', '--tests', '--test_case'))
-
-
if __name__ == '__main__':
logging.basicConfig(filename=_BOOTSTRAP_LOGGING_FILENAME, level=logging.INFO)
- suite_runner.run_suite(argv=[arg for arg in sys.argv if _valid_argument(arg)],
- test_classes=_TEST_CLASSES_LIST)
+ if '--' in sys.argv:
+ index = sys.argv.index('--')
+ sys.argv = sys.argv[:1] + sys.argv[index + 1:]
+ suite_runner.run_suite(test_classes=_TEST_CLASSES_LIST)
diff --git a/nearby/tests/robotests/Android.bp b/nearby/tests/robotests/Android.bp
index 56c0107..70fa0c3 100644
--- a/nearby/tests/robotests/Android.bp
+++ b/nearby/tests/robotests/Android.bp
@@ -42,15 +42,14 @@
"androidx.lifecycle_lifecycle-runtime",
"androidx.mediarouter_mediarouter-nodeps",
"error_prone_annotations",
- "mockito-robolectric-prebuilt",
"service-nearby-pre-jarjar",
"truth-prebuilt",
"robolectric_android-all-stub",
- "Robolectric_all-target",
],
test_options: {
// timeout in seconds.
timeout: 36000,
},
+ upstream: true,
}
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index 7950ff7..8081d12 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -32,7 +32,6 @@
namespace net {
using base::unique_fd;
-using bpf::NONEXISTENT_COOKIE;
using bpf::getSocketCookie;
using bpf::retrieveProgram;
using netdutils::Status;
@@ -93,7 +92,7 @@
// cgroup if the program is pinned properly.
// TODO: delete the if statement once all devices should support cgroup
// socket filter (ie. the minimum kernel version required is 4.14).
- if (!access(CGROUP_SOCKET_PROG_PATH, F_OK)) {
+ if (bpf::isAtLeastKernelVersion(4, 14, 0)) {
RETURN_IF_NOT_OK(
attachProgramToCgroup(CGROUP_SOCKET_PROG_PATH, cg_fd, BPF_CGROUP_INET_SOCK_CREATE));
}
@@ -185,7 +184,7 @@
}
uint64_t sock_cookie = getSocketCookie(sockFd);
- if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
+ if (!sock_cookie) return -errno;
UidTagValue newKey = {.uid = (uint32_t)chargeUid, .tag = tag};
@@ -249,7 +248,7 @@
int BpfHandler::untagSocket(int sockFd) {
uint64_t sock_cookie = getSocketCookie(sockFd);
- if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
+ if (!sock_cookie) return -errno;
if (!mCookieTagMap.isValid()) return -EPERM;
base::Result<void> res = mCookieTagMap.deleteValue(sock_cookie);
diff --git a/service-t/Android.bp b/service-t/Android.bp
index 5bf2973..7de749c 100644
--- a/service-t/Android.bp
+++ b/service-t/Android.bp
@@ -75,3 +75,47 @@
"//packages/modules/IPsec/tests/iketests",
],
}
+
+// Test building mDNS as a standalone, so that it can be imported into other repositories as-is.
+// The mDNS code is platform code so it should use framework-annotations-lib, contrary to apps that
+// should use sdk_version: "system_current" and only androidx.annotation_annotation. But this build
+// rule verifies that the mDNS code can be built into apps, if code transformations are applied to
+// the annotations.
+// When using "system_current", framework annotations are not available; they would appear as
+// package-private as they are marked as such in the system_current stubs. So build against
+// core_platform and add the stubs manually in "libs". See http://b/147773144#comment7.
+java_library {
+ name: "service-connectivity-mdns-standalone-build-test",
+ sdk_version: "core_platform",
+ srcs: [
+ ":service-mdns-droidstubs",
+ "src/com/android/server/connectivity/mdns/**/*.java",
+ ],
+ exclude_srcs: [
+ "src/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitor.java",
+ "src/com/android/server/connectivity/mdns/SocketNetLinkMonitorFactory.java"
+ ],
+ static_libs: [
+ "net-utils-device-common-mdns-standalone-build-test",
+ ],
+ libs: [
+ "framework-annotations-lib",
+ "android_system_stubs_current",
+ "androidx.annotation_annotation",
+ ],
+ visibility: [
+ "//visibility:private",
+ ],
+}
+
+droidstubs {
+ name: "service-mdns-droidstubs",
+ srcs: ["src/com/android/server/connectivity/mdns/SocketNetLinkMonitorFactory.java"],
+ libs: [
+ "net-utils-device-common-mdns-standalone-build-test",
+ "service-connectivity-tiramisu-pre-jarjar"
+ ],
+ visibility: [
+ "//visibility:private",
+ ],
+}
\ No newline at end of file
diff --git a/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp b/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp
index a3299a7..a16757b 100644
--- a/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp
+++ b/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp
@@ -170,23 +170,10 @@
return 0;
}
-static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jint limitUid,
- jobjectArray limitIfacesObj, jint limitTag) {
-
- std::vector<std::string> limitIfaces;
- if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
- int num = env->GetArrayLength(limitIfacesObj);
- for (int i = 0; i < num; i++) {
- jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
- ScopedUtfChars string8(env, string);
- if (string8.c_str() != NULL) {
- limitIfaces.push_back(std::string(string8.c_str()));
- }
- }
- }
+static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats) {
std::vector<stats_line> lines;
- if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
+ if (parseBpfNetworkStatsDetail(&lines) < 0)
return -1;
return statsLinesToNetworkStats(env, clazz, stats, lines);
@@ -202,15 +189,15 @@
}
static const JNINativeMethod gMethods[] = {
- { "nativeReadNetworkStatsDetail",
- "(Landroid/net/NetworkStats;I[Ljava/lang/String;I)I",
+ { "nativeReadNetworkStatsDetail", "(Landroid/net/NetworkStats;)I",
(void*) readNetworkStatsDetail },
{ "nativeReadNetworkStatsDev", "(Landroid/net/NetworkStats;)I",
(void*) readNetworkStatsDev },
};
int register_android_server_net_NetworkStatsFactory(JNIEnv* env) {
- int err = jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsFactory", gMethods,
+ int err = jniRegisterNativeMethods(env,
+ "android/net/connectivity/com/android/server/net/NetworkStatsFactory", gMethods,
NELEM(gMethods));
gStringClass = env->FindClass("java/lang/String");
gStringClass = static_cast<jclass>(env->NewGlobalRef(gStringClass));
diff --git a/service-t/jni/com_android_server_net_NetworkStatsService.cpp b/service-t/jni/com_android_server_net_NetworkStatsService.cpp
index af0b8d8..dab9d07 100644
--- a/service-t/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/service-t/jni/com_android_server_net_NetworkStatsService.cpp
@@ -116,8 +116,9 @@
};
int register_android_server_net_NetworkStatsService(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods,
- NELEM(gMethods));
+ return jniRegisterNativeMethods(env,
+ "android/net/connectivity/com/android/server/net/NetworkStatsService", gMethods,
+ NELEM(gMethods));
}
}
diff --git a/service-t/native/libs/libnetworkstats/Android.bp b/service-t/native/libs/libnetworkstats/Android.bp
index aa1ee41..f40d388 100644
--- a/service-t/native/libs/libnetworkstats/Android.bp
+++ b/service-t/native/libs/libnetworkstats/Android.bp
@@ -26,6 +26,7 @@
srcs: [
"BpfNetworkStats.cpp",
"NetworkTraceHandler.cpp",
+ "NetworkTracePoller.cpp",
],
shared_libs: [
"libbase",
@@ -62,6 +63,7 @@
srcs: [
"BpfNetworkStatsTest.cpp",
"NetworkTraceHandlerTest.cpp",
+ "NetworkTracePollerTest.cpp",
],
cflags: [
"-Wall",
@@ -73,6 +75,8 @@
"libgmock",
"libnetworkstats",
"libperfetto_client_experimental",
+ "libprotobuf-cpp-lite",
+ "perfetto_trace_protos",
],
shared_libs: [
"libbase",
diff --git a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
index 122c2d4..1bc8ca5 100644
--- a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
+++ b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
@@ -109,13 +109,12 @@
return newLine;
}
-int parseBpfNetworkStatsDetailInternal(std::vector<stats_line>* lines,
- const std::vector<std::string>& limitIfaces, int limitTag,
- int limitUid, const BpfMap<StatsKey, StatsValue>& statsMap,
+int parseBpfNetworkStatsDetailInternal(std::vector<stats_line>& lines,
+ const BpfMap<StatsKey, StatsValue>& statsMap,
const BpfMap<uint32_t, IfaceValue>& ifaceMap) {
int64_t unknownIfaceBytesTotal = 0;
const auto processDetailUidStats =
- [lines, &limitIfaces, &limitTag, &limitUid, &unknownIfaceBytesTotal, &ifaceMap](
+ [&lines, &unknownIfaceBytesTotal, &ifaceMap](
const StatsKey& key,
const BpfMap<StatsKey, StatsValue>& statsMap) -> Result<void> {
char ifname[IFNAMSIZ];
@@ -123,23 +122,17 @@
&unknownIfaceBytesTotal)) {
return Result<void>();
}
- std::string ifnameStr(ifname);
- if (limitIfaces.size() > 0 &&
- std::find(limitIfaces.begin(), limitIfaces.end(), ifnameStr) == limitIfaces.end()) {
- // Nothing matched; skip this line.
- return Result<void>();
- }
- if (limitTag != TAG_ALL && uint32_t(limitTag) != key.tag) {
- return Result<void>();
- }
- if (limitUid != UID_ALL && uint32_t(limitUid) != key.uid) {
- return Result<void>();
- }
Result<StatsValue> statsEntry = statsMap.readValue(key);
if (!statsEntry.ok()) {
return base::ResultError(statsEntry.error().message(), statsEntry.error().code());
}
- lines->push_back(populateStatsEntry(key, statsEntry.value(), ifname));
+ stats_line newLine = populateStatsEntry(key, statsEntry.value(), ifname);
+ lines.push_back(newLine);
+ if (newLine.tag) {
+ // account tagged traffic in the untagged stats (for historical reasons?)
+ newLine.tag = 0;
+ lines.push_back(newLine);
+ }
return Result<void>();
};
Result<void> res = statsMap.iterate(processDetailUidStats);
@@ -162,9 +155,7 @@
return 0;
}
-int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines,
- const std::vector<std::string>& limitIfaces, int limitTag,
- int limitUid) {
+int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines) {
static BpfMapRO<uint32_t, IfaceValue> ifaceIndexNameMap(IFACE_INDEX_NAME_MAP_PATH);
static BpfMapRO<uint32_t, uint32_t> configurationMap(CONFIGURATION_MAP_PATH);
static BpfMap<StatsKey, StatsValue> statsMapA(STATS_MAP_A_PATH);
@@ -195,8 +186,7 @@
// TODO: the above comment feels like it may be obsolete / out of date,
// since we no longer swap the map via netd binder rpc - though we do
// still swap it.
- int ret = parseBpfNetworkStatsDetailInternal(lines, limitIfaces, limitTag, limitUid,
- *inactiveStatsMap, ifaceIndexNameMap);
+ int ret = parseBpfNetworkStatsDetailInternal(*lines, *inactiveStatsMap, ifaceIndexNameMap);
if (ret) {
ALOGE("parse detail network stats failed: %s", strerror(errno));
return ret;
@@ -211,11 +201,11 @@
return 0;
}
-int parseBpfNetworkStatsDevInternal(std::vector<stats_line>* lines,
+int parseBpfNetworkStatsDevInternal(std::vector<stats_line>& lines,
const BpfMap<uint32_t, StatsValue>& statsMap,
const BpfMap<uint32_t, IfaceValue>& ifaceMap) {
int64_t unknownIfaceBytesTotal = 0;
- const auto processDetailIfaceStats = [lines, &unknownIfaceBytesTotal, &ifaceMap, &statsMap](
+ const auto processDetailIfaceStats = [&lines, &unknownIfaceBytesTotal, &ifaceMap, &statsMap](
const uint32_t& key, const StatsValue& value,
const BpfMap<uint32_t, StatsValue>&) {
char ifname[IFNAMSIZ];
@@ -227,7 +217,7 @@
.tag = (uint32_t)TAG_NONE,
.counterSet = (uint32_t)SET_ALL,
};
- lines->push_back(populateStatsEntry(fakeKey, value, ifname));
+ lines.push_back(populateStatsEntry(fakeKey, value, ifname));
return Result<void>();
};
Result<void> res = statsMap.iterateWithValue(processDetailIfaceStats);
@@ -244,33 +234,28 @@
int parseBpfNetworkStatsDev(std::vector<stats_line>* lines) {
static BpfMapRO<uint32_t, IfaceValue> ifaceIndexNameMap(IFACE_INDEX_NAME_MAP_PATH);
static BpfMapRO<uint32_t, StatsValue> ifaceStatsMap(IFACE_STATS_MAP_PATH);
- return parseBpfNetworkStatsDevInternal(lines, ifaceStatsMap, ifaceIndexNameMap);
+ return parseBpfNetworkStatsDevInternal(*lines, ifaceStatsMap, ifaceIndexNameMap);
}
-uint64_t combineUidTag(const uid_t uid, const uint32_t tag) {
- return (uint64_t)uid << 32 | tag;
-}
-
-void groupNetworkStats(std::vector<stats_line>* lines) {
- if (lines->size() <= 1) return;
- std::sort(lines->begin(), lines->end());
+void groupNetworkStats(std::vector<stats_line>& lines) {
+ if (lines.size() <= 1) return;
+ std::sort(lines.begin(), lines.end());
// Similar to std::unique(), but aggregates the duplicates rather than discarding them.
- size_t nextOutput = 0;
- for (size_t i = 1; i < lines->size(); i++) {
- if (lines->at(nextOutput) == lines->at(i)) {
- lines->at(nextOutput) += lines->at(i);
+ size_t currentOutput = 0;
+ for (size_t i = 1; i < lines.size(); i++) {
+ // note that == operator only compares the 'key' portion: iface/uid/tag/set
+ if (lines[currentOutput] == lines[i]) {
+ // while += operator only affects the 'data' portion: {rx,tx}{Bytes,Packets}
+ lines[currentOutput] += lines[i];
} else {
- nextOutput++;
- if (nextOutput != i) {
- lines->at(nextOutput) = lines->at(i);
- }
+ // okay, we're done aggregating the current line, move to the next one
+ lines[++currentOutput] = lines[i];
}
}
- if (lines->size() != nextOutput + 1) {
- lines->resize(nextOutput + 1);
- }
+ // possibly shrink the vector - currentOutput is the last line with valid data
+ lines.resize(currentOutput + 1);
}
// True if lhs equals to rhs, only compare iface, uid, tag and set.
diff --git a/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp b/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp
index ff62c0b..ccd3f5e 100644
--- a/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp
+++ b/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp
@@ -225,18 +225,11 @@
ASSERT_EQ(0, bpfGetUidStatsInternal(TEST_UID2, &result2, mFakeAppUidStatsMap));
expectStatsEqual(value2, result2);
std::vector<stats_line> lines;
- std::vector<std::string> ifaces;
populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET1, value1, mFakeStatsMap);
populateFakeStats(TEST_UID2, 0, IFACE_INDEX3, TEST_COUNTERSET1, value1, mFakeStatsMap);
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
- mFakeStatsMap, mFakeIfaceIndexNameMap));
- ASSERT_EQ((unsigned long)2, lines.size());
- lines.clear();
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
- mFakeStatsMap, mFakeIfaceIndexNameMap));
- ASSERT_EQ((unsigned long)1, lines.size());
- expectStatsLineEqual(value1, IFACE_NAME3, TEST_UID2, TEST_COUNTERSET1, 0, lines.front());
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ((unsigned long)3, lines.size());
}
TEST_F(BpfNetworkStatsHelperTest, TestGetIfaceStatsInternal) {
@@ -297,24 +290,8 @@
mFakeStatsMap);
populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
std::vector<stats_line> lines;
- std::vector<std::string> ifaces;
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
- mFakeIfaceIndexNameMap));
- ASSERT_EQ((unsigned long)4, lines.size());
- lines.clear();
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
- mFakeStatsMap, mFakeIfaceIndexNameMap));
- ASSERT_EQ((unsigned long)3, lines.size());
- lines.clear();
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
- mFakeStatsMap, mFakeIfaceIndexNameMap));
- ASSERT_EQ((unsigned long)2, lines.size());
- lines.clear();
- ifaces.push_back(std::string(IFACE_NAME1));
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TEST_TAG, TEST_UID1,
- mFakeStatsMap, mFakeIfaceIndexNameMap));
- ASSERT_EQ((unsigned long)1, lines.size());
- expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines.front());
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ((unsigned long)7, lines.size());
}
TEST_F(BpfNetworkStatsHelperTest, TestGetStatsWithSkippedIface) {
@@ -333,24 +310,8 @@
populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET1, value1, mFakeStatsMap);
populateFakeStats(TEST_UID2, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
std::vector<stats_line> lines;
- std::vector<std::string> ifaces;
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
- mFakeIfaceIndexNameMap));
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)4, lines.size());
- lines.clear();
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
- mFakeStatsMap, mFakeIfaceIndexNameMap));
- ASSERT_EQ((unsigned long)3, lines.size());
- lines.clear();
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID2,
- mFakeStatsMap, mFakeIfaceIndexNameMap));
- ASSERT_EQ((unsigned long)1, lines.size());
- expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, 0, lines.front());
- lines.clear();
- ifaces.push_back(std::string(IFACE_NAME1));
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, TEST_UID1,
- mFakeStatsMap, mFakeIfaceIndexNameMap));
- ASSERT_EQ((unsigned long)2, lines.size());
}
TEST_F(BpfNetworkStatsHelperTest, TestUnknownIfaceError) {
@@ -387,10 +348,8 @@
ifname, curKey, &unknownIfaceBytesTotal));
ASSERT_EQ(-1, unknownIfaceBytesTotal);
std::vector<stats_line> lines;
- std::vector<std::string> ifaces;
// TODO: find a way to test the total of unknown Iface Bytes go above limit.
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
- mFakeIfaceIndexNameMap));
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)1, lines.size());
expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines.front());
}
@@ -422,7 +381,7 @@
EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value2, BPF_ANY));
std::vector<stats_line> lines;
ASSERT_EQ(0,
- parseBpfNetworkStatsDevInternal(&lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
+ parseBpfNetworkStatsDevInternal(lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((unsigned long)4, lines.size());
expectStatsLineEqual(value1, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]);
@@ -450,28 +409,32 @@
.txPackets = TEST_PACKET0,
.txBytes = TEST_BYTES0,
};
- StatsValue value3 = {
+ StatsValue value3 = { // value1 *2
.rxPackets = TEST_PACKET0 * 2,
.rxBytes = TEST_BYTES0 * 2,
.txPackets = TEST_PACKET1 * 2,
.txBytes = TEST_BYTES1 * 2,
};
+ StatsValue value5 = { // value2 + value3
+ .rxPackets = TEST_PACKET1 + TEST_PACKET0 * 2,
+ .rxBytes = TEST_BYTES1 + TEST_BYTES0 * 2,
+ .txPackets = TEST_PACKET0 + TEST_PACKET1 * 2,
+ .txBytes = TEST_BYTES0 + TEST_BYTES1 * 2,
+ };
std::vector<stats_line> lines;
- std::vector<std::string> ifaces;
// Test empty stats.
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
- mFakeIfaceIndexNameMap));
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((size_t) 0, lines.size());
lines.clear();
// Test 1 line stats.
populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
- mFakeIfaceIndexNameMap));
- ASSERT_EQ((size_t) 1, lines.size());
- expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[0]);
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ((size_t) 2, lines.size()); // TEST_TAG != 0 -> 1 entry becomes 2 lines
+ expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines[0]);
+ expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[1]);
lines.clear();
// These items should not be grouped.
@@ -480,25 +443,27 @@
populateFakeStats(TEST_UID1, TEST_TAG + 1, IFACE_INDEX1, TEST_COUNTERSET0, value2,
mFakeStatsMap);
populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
- mFakeIfaceIndexNameMap));
- ASSERT_EQ((size_t) 5, lines.size());
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ((size_t) 9, lines.size());
lines.clear();
// These items should be grouped.
populateFakeStats(TEST_UID1, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1, mFakeStatsMap);
populateFakeStats(TEST_UID2, TEST_TAG, IFACE_INDEX3, TEST_COUNTERSET0, value1, mFakeStatsMap);
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
- mFakeIfaceIndexNameMap));
- ASSERT_EQ((size_t) 5, lines.size());
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ((size_t) 9, lines.size());
// Verify Sorted & Grouped.
- expectStatsLineEqual(value3, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[0]);
- expectStatsLineEqual(value2, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET1, TEST_TAG, lines[1]);
- expectStatsLineEqual(value2, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG + 1, lines[2]);
- expectStatsLineEqual(value3, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, TEST_TAG, lines[3]);
- expectStatsLineEqual(value2, IFACE_NAME2, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[4]);
+ expectStatsLineEqual(value5, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines[0]);
+ expectStatsLineEqual(value2, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET1, 0, lines[1]);
+ expectStatsLineEqual(value3, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[2]);
+ expectStatsLineEqual(value2, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET1, TEST_TAG, lines[3]);
+ expectStatsLineEqual(value2, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, TEST_TAG + 1, lines[4]);
+ expectStatsLineEqual(value3, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, 0, lines[5]);
+ expectStatsLineEqual(value3, IFACE_NAME1, TEST_UID2, TEST_COUNTERSET0, TEST_TAG, lines[6]);
+ expectStatsLineEqual(value2, IFACE_NAME2, TEST_UID1, TEST_COUNTERSET0, 0, lines[7]);
+ expectStatsLineEqual(value2, IFACE_NAME2, TEST_UID1, TEST_COUNTERSET0, TEST_TAG, lines[8]);
lines.clear();
// Perform test on IfaceStats.
@@ -512,7 +477,7 @@
EXPECT_RESULT_OK(mFakeIfaceStatsMap.writeValue(ifaceStatsKey, value1, BPF_ANY));
ASSERT_EQ(0,
- parseBpfNetworkStatsDevInternal(&lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
+ parseBpfNetworkStatsDevInternal(lines, mFakeIfaceStatsMap, mFakeIfaceIndexNameMap));
ASSERT_EQ((size_t) 2, lines.size());
expectStatsLineEqual(value3, IFACE_NAME1, UID_ALL, SET_ALL, TAG_NONE, lines[0]);
@@ -531,41 +496,48 @@
.txPackets = TEST_PACKET1,
.txBytes = TEST_BYTES1,
};
+ StatsValue value4 = { // value1 * 4
+ .rxPackets = TEST_PACKET0 * 4,
+ .rxBytes = TEST_BYTES0 * 4,
+ .txPackets = TEST_PACKET1 * 4,
+ .txBytes = TEST_BYTES1 * 4,
+ };
// Mutate uid, 0 < TEST_UID1 < INT_MAX < INT_MIN < UINT_MAX.
- populateFakeStats(0, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
- populateFakeStats(UINT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
- populateFakeStats(INT_MIN, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
- populateFakeStats(INT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(0, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(UINT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(INT_MIN, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(INT_MAX, TEST_TAG, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
// Mutate tag, 0 < TEST_TAG < INT_MAX < INT_MIN < UINT_MAX.
- populateFakeStats(TEST_UID1, INT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
- populateFakeStats(TEST_UID1, INT_MIN, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
- populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, INT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, INT_MIN, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
+ populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
populateFakeStats(TEST_UID1, UINT_MAX, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
// TODO: Mutate counterSet and enlarge TEST_MAP_SIZE if overflow on counterSet is possible.
std::vector<stats_line> lines;
- std::vector<std::string> ifaces;
- ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(&lines, ifaces, TAG_ALL, UID_ALL, mFakeStatsMap,
- mFakeIfaceIndexNameMap));
- ASSERT_EQ((size_t) 8, lines.size());
+ ASSERT_EQ(0, parseBpfNetworkStatsDetailInternal(lines, mFakeStatsMap, mFakeIfaceIndexNameMap));
+ ASSERT_EQ((size_t) 12, lines.size());
// Uid 0 first
- expectStatsLineEqual(value1, IFACE_NAME1, 0, TEST_COUNTERSET0, TEST_TAG, lines[0]);
+ expectStatsLineEqual(value1, IFACE_NAME1, 0, TEST_COUNTERSET0, 0, lines[0]);
+ expectStatsLineEqual(value1, IFACE_NAME1, 0, TEST_COUNTERSET0, TEST_TAG, lines[1]);
// Test uid, mutate tag.
- expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines[1]);
- expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, INT_MAX, lines[2]);
- expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, INT_MIN, lines[3]);
- expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, UINT_MAX, lines[4]);
+ expectStatsLineEqual(value4, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, 0, lines[2]);
+ expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, INT_MAX, lines[3]);
+ expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, INT_MIN, lines[4]);
+ expectStatsLineEqual(value1, IFACE_NAME1, TEST_UID1, TEST_COUNTERSET0, UINT_MAX, lines[5]);
// Mutate uid.
- expectStatsLineEqual(value1, IFACE_NAME1, INT_MAX, TEST_COUNTERSET0, TEST_TAG, lines[5]);
- expectStatsLineEqual(value1, IFACE_NAME1, INT_MIN, TEST_COUNTERSET0, TEST_TAG, lines[6]);
- expectStatsLineEqual(value1, IFACE_NAME1, UINT_MAX, TEST_COUNTERSET0, TEST_TAG, lines[7]);
- lines.clear();
+ expectStatsLineEqual(value1, IFACE_NAME1, INT_MAX, TEST_COUNTERSET0, 0, lines[6]);
+ expectStatsLineEqual(value1, IFACE_NAME1, INT_MAX, TEST_COUNTERSET0, TEST_TAG, lines[7]);
+ expectStatsLineEqual(value1, IFACE_NAME1, INT_MIN, TEST_COUNTERSET0, 0, lines[8]);
+ expectStatsLineEqual(value1, IFACE_NAME1, INT_MIN, TEST_COUNTERSET0, TEST_TAG, lines[9]);
+ expectStatsLineEqual(value1, IFACE_NAME1, UINT_MAX, TEST_COUNTERSET0, 0, lines[10]);
+ expectStatsLineEqual(value1, IFACE_NAME1, UINT_MAX, TEST_COUNTERSET0, TEST_TAG, lines[11]);
}
} // namespace bpf
} // namespace android
diff --git a/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp b/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
index 4c37b8d..6aa0fb4 100644
--- a/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
+++ b/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
@@ -33,11 +33,62 @@
namespace android {
namespace bpf {
+using ::android::bpf::internal::NetworkTracePoller;
+using ::perfetto::protos::pbzero::NetworkPacketBundle;
using ::perfetto::protos::pbzero::NetworkPacketEvent;
using ::perfetto::protos::pbzero::NetworkPacketTraceConfig;
using ::perfetto::protos::pbzero::TracePacket;
using ::perfetto::protos::pbzero::TrafficDirection;
+// Bundling takes groups of packets with similar contextual fields (generally,
+// all fields except timestamp and length) and summarises them in a single trace
+// packet. For example, rather than
+//
+// {.timestampNs = 1, .uid = 1000, .tag = 123, .len = 72}
+// {.timestampNs = 2, .uid = 1000, .tag = 123, .len = 100}
+// {.timestampNs = 5, .uid = 1000, .tag = 123, .len = 456}
+//
+// The output will be something like
+// {
+// .timestamp = 1
+// .ctx = {.uid = 1000, .tag = 123}
+// .timestamp = [0, 1, 4], // delta encoded
+// .length = [72, 100, 456], // should be zipped with timestamps
+// }
+//
+// Most workloads have many packets from few contexts. Bundling greatly reduces
+// the amount of redundant information written, thus reducing the overall trace
+// size. Interning ids are similarly based on unique bundle contexts.
+
+// Based on boost::hash_combine
+template <typename T, typename... Rest>
+void HashCombine(std::size_t& seed, const T& val, const Rest&... rest) {
+ seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ (HashCombine(seed, rest), ...);
+}
+
+// Details summarises the timestamp and lengths of packets in a bundle.
+struct BundleDetails {
+ std::vector<std::pair<uint64_t, uint32_t>> time_and_len;
+ uint64_t minTs = std::numeric_limits<uint64_t>::max();
+ uint64_t maxTs = std::numeric_limits<uint64_t>::min();
+ uint32_t bytes = 0;
+};
+
+#define AGG_FIELDS(x) \
+ (x).ifindex, (x).uid, (x).tag, (x).sport, (x).dport, (x).egress, \
+ (x).ipProto, (x).tcpFlags
+
+std::size_t BundleHash::operator()(const BundleKey& a) const {
+ std::size_t seed = 0;
+ HashCombine(seed, AGG_FIELDS(a));
+ return seed;
+}
+
+bool BundleEq::operator()(const BundleKey& a, const BundleKey& b) const {
+ return std::tie(AGG_FIELDS(a)) == std::tie(AGG_FIELDS(b));
+}
+
// static
void NetworkTraceHandler::RegisterDataSource() {
ALOGD("Registering Perfetto data source");
@@ -50,17 +101,27 @@
void NetworkTraceHandler::InitPerfettoTracing() {
perfetto::TracingInitArgs args = {};
args.backends |= perfetto::kSystemBackend;
+ // The following line disables the Perfetto system consumer. Perfetto inlines
+ // the call to `Initialize` which allows the compiler to see that the branch
+ // with the SystemConsumerTracingBackend is not used. With LTO enabled, this
+ // strips the Perfetto consumer code and reduces the size of this binary by
+ // around 270KB total. Be careful when changing this value.
+ args.enable_system_consumer = false;
perfetto::Tracing::Initialize(args);
NetworkTraceHandler::RegisterDataSource();
}
-NetworkTraceHandler::NetworkTraceHandler()
- : NetworkTraceHandler([this](const PacketTrace& pkt) {
- NetworkTraceHandler::Trace(
- [this, pkt](NetworkTraceHandler::TraceContext ctx) {
- Fill(pkt, *ctx.NewTracePacket());
- });
- }) {}
+// static
+NetworkTracePoller NetworkTraceHandler::sPoller(
+ [](const std::vector<PacketTrace>& packets) {
+ // Trace calls the provided callback for each active session. The context
+ // gets a reference to the NetworkTraceHandler instance associated with
+ // the session and delegates writing. The corresponding handler will write
+ // with the setting specified in the trace config.
+ NetworkTraceHandler::Trace([&](NetworkTraceHandler::TraceContext ctx) {
+ ctx.GetDataSourceLocked()->Write(packets, ctx);
+ });
+ });
void NetworkTraceHandler::OnSetup(const SetupArgs& args) {
const std::string& raw = args.config->network_packet_trace_config_raw();
@@ -71,38 +132,118 @@
ALOGI("poll_ms is missing or below the 100ms minimum. Increasing to 100ms");
mPollMs = 100;
}
+
+ mInternLimit = config.intern_limit();
+ mAggregationThreshold = config.aggregation_threshold();
+ mDropLocalPort = config.drop_local_port();
+ mDropRemotePort = config.drop_remote_port();
+ mDropTcpFlags = config.drop_tcp_flags();
}
void NetworkTraceHandler::OnStart(const StartArgs&) {
- if (!Start()) return;
- mTaskRunner = perfetto::Platform::GetDefaultPlatform()->CreateTaskRunner({});
- Loop();
+ if (mIsTest) return; // Don't touch non-hermetic bpf in test.
+ mStarted = sPoller.Start(mPollMs);
}
void NetworkTraceHandler::OnStop(const StopArgs&) {
- Stop();
- mTaskRunner.reset();
+ if (mIsTest) return; // Don't touch non-hermetic bpf in test.
+ if (mStarted) sPoller.Stop();
+ mStarted = false;
}
-void NetworkTraceHandler::Loop() {
- mTaskRunner->PostDelayedTask([this]() { Loop(); }, mPollMs);
- ConsumeAll();
+void NetworkTraceHandler::Write(const std::vector<PacketTrace>& packets,
+ NetworkTraceHandler::TraceContext& ctx) {
+ // TODO: remove this fallback once Perfetto stable has support for bundles.
+ if (!mInternLimit && !mAggregationThreshold) {
+ for (const PacketTrace& pkt : packets) {
+ auto dst = ctx.NewTracePacket();
+ dst->set_timestamp(pkt.timestampNs);
+ auto* event = dst->set_network_packet();
+ event->set_length(pkt.length);
+ Fill(pkt, event);
+ }
+ return;
+ }
+
+ uint64_t minTs = std::numeric_limits<uint64_t>::max();
+ std::unordered_map<BundleKey, BundleDetails, BundleHash, BundleEq> bundles;
+ for (const PacketTrace& pkt : packets) {
+ BundleKey key = pkt;
+
+ // Dropping fields should remove them from the output and remove them from
+ // the aggregation key. In order to do the latter without changing the hash
+ // function, set the dropped fields to zero.
+ if (mDropTcpFlags) key.tcpFlags = 0;
+ if (mDropLocalPort) (key.egress ? key.sport : key.dport) = 0;
+ if (mDropRemotePort) (key.egress ? key.dport : key.sport) = 0;
+
+ minTs = std::min(minTs, pkt.timestampNs);
+
+ BundleDetails& bundle = bundles[key];
+ bundle.time_and_len.emplace_back(pkt.timestampNs, pkt.length);
+ bundle.minTs = std::min(bundle.minTs, pkt.timestampNs);
+ bundle.maxTs = std::max(bundle.maxTs, pkt.timestampNs);
+ bundle.bytes += pkt.length;
+ }
+
+ NetworkTraceState* incr_state = ctx.GetIncrementalState();
+ for (const auto& kv : bundles) {
+ const BundleKey& key = kv.first;
+ const BundleDetails& details = kv.second;
+
+ auto dst = ctx.NewTracePacket();
+ dst->set_timestamp(details.minTs);
+
+ // Incremental state is only used when interning. Set the flag based on
+ // whether state was cleared. Leave the flag empty in non-intern configs.
+ if (mInternLimit > 0) {
+ if (incr_state->cleared) {
+ dst->set_sequence_flags(TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
+ incr_state->cleared = false;
+ } else {
+ dst->set_sequence_flags(TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
+ }
+ }
+
+ auto* event = FillWithInterning(incr_state, key, dst.get());
+
+ int count = details.time_and_len.size();
+ if (!mAggregationThreshold || count < mAggregationThreshold) {
+ protozero::PackedVarInt offsets;
+ protozero::PackedVarInt lengths;
+ for (const auto& kv : details.time_and_len) {
+ offsets.Append(kv.first - details.minTs);
+ lengths.Append(kv.second);
+ }
+
+ event->set_packet_timestamps(offsets);
+ event->set_packet_lengths(lengths);
+ } else {
+ event->set_total_duration(details.maxTs - details.minTs);
+ event->set_total_length(details.bytes);
+ event->set_total_packets(count);
+ }
+ }
}
-void NetworkTraceHandler::Fill(const PacketTrace& src, TracePacket& dst) {
- dst.set_timestamp(src.timestampNs);
- auto* event = dst.set_network_packet();
+void NetworkTraceHandler::Fill(const PacketTrace& src,
+ NetworkPacketEvent* event) {
event->set_direction(src.egress ? TrafficDirection::DIR_EGRESS
: TrafficDirection::DIR_INGRESS);
- event->set_length(src.length);
event->set_uid(src.uid);
event->set_tag(src.tag);
- event->set_local_port(src.egress ? ntohs(src.sport) : ntohs(src.dport));
- event->set_remote_port(src.egress ? ntohs(src.dport) : ntohs(src.sport));
+ if (!mDropLocalPort) {
+ event->set_local_port(ntohs(src.egress ? src.sport : src.dport));
+ }
+ if (!mDropRemotePort) {
+ event->set_remote_port(ntohs(src.egress ? src.dport : src.sport));
+ }
+ if (!mDropTcpFlags) {
+ event->set_tcp_flags(src.tcpFlags);
+ }
event->set_ip_proto(src.ipProto);
- event->set_tcp_flags(src.tcpFlags);
char ifname[IF_NAMESIZE] = {};
if (if_indextoname(src.ifindex, ifname) == ifname) {
@@ -112,59 +253,38 @@
}
}
-bool NetworkTraceHandler::Start() {
- ALOGD("Starting datasource");
+NetworkPacketBundle* NetworkTraceHandler::FillWithInterning(
+ NetworkTraceState* state, const BundleKey& key, TracePacket* dst) {
+ uint64_t iid = 0;
+ bool found = false;
- auto status = mConfigurationMap.init(PACKET_TRACE_ENABLED_MAP_PATH);
- if (!status.ok()) {
- ALOGW("Failed to bind config map: %s", status.error().message().c_str());
- return false;
+ if (state->iids.size() < mInternLimit) {
+ auto [iter, success] = state->iids.try_emplace(key, state->iids.size() + 1);
+ iid = iter->second;
+ found = true;
+
+ if (success) {
+ // If we successfully empaced, record the newly interned data.
+ auto* packet_context = dst->set_interned_data()->add_packet_context();
+ Fill(key, packet_context->set_ctx());
+ packet_context->set_iid(iid);
+ }
+ } else {
+ auto iter = state->iids.find(key);
+ if (iter != state->iids.end()) {
+ iid = iter->second;
+ found = true;
+ }
}
- auto rb = BpfRingbuf<PacketTrace>::Create(PACKET_TRACE_RINGBUF_PATH);
- if (!rb.ok()) {
- ALOGW("Failed to create ringbuf: %s", rb.error().message().c_str());
- return false;
+ auto* event = dst->set_network_packet_bundle();
+ if (found) {
+ event->set_iid(iid);
+ } else {
+ Fill(key, event->set_ctx());
}
- mRingBuffer = std::move(*rb);
-
- auto res = mConfigurationMap.writeValue(0, true, BPF_ANY);
- if (!res.ok()) {
- ALOGW("Failed to enable tracing: %s", res.error().message().c_str());
- return false;
- }
-
- return true;
-}
-
-bool NetworkTraceHandler::Stop() {
- ALOGD("Stopping datasource");
-
- auto res = mConfigurationMap.writeValue(0, false, BPF_ANY);
- if (!res.ok()) {
- ALOGW("Failed to disable tracing: %s", res.error().message().c_str());
- return false;
- }
-
- mRingBuffer.reset();
-
- return true;
-}
-
-bool NetworkTraceHandler::ConsumeAll() {
- if (mRingBuffer == nullptr) {
- ALOGW("Tracing is not active");
- return false;
- }
-
- base::Result<int> ret = mRingBuffer->ConsumeAll(mCallback);
- if (!ret.ok()) {
- ALOGW("Failed to poll ringbuf: %s", ret.error().message().c_str());
- return false;
- }
-
- return true;
+ return event;
}
} // namespace bpf
diff --git a/service-t/native/libs/libnetworkstats/NetworkTraceHandlerTest.cpp b/service-t/native/libs/libnetworkstats/NetworkTraceHandlerTest.cpp
index 760ae91..f2c1a86 100644
--- a/service-t/native/libs/libnetworkstats/NetworkTraceHandlerTest.cpp
+++ b/service-t/native/libs/libnetworkstats/NetworkTraceHandlerTest.cpp
@@ -14,184 +14,381 @@
* limitations under the License.
*/
-#include <android-base/unique_fd.h>
-#include <android/multinetwork.h>
-#include <arpa/inet.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <inttypes.h>
-#include <net/if.h>
-#include <netinet/tcp.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
#include <vector>
#include "netdbpf/NetworkTraceHandler.h"
-
-using ::testing::AllOf;
-using ::testing::AnyOf;
-using ::testing::Each;
-using ::testing::Eq;
-using ::testing::Field;
-using ::testing::Test;
+#include "protos/perfetto/config/android/network_trace_config.gen.h"
+#include "protos/perfetto/trace/android/network_trace.pb.h"
+#include "protos/perfetto/trace/trace.pb.h"
+#include "protos/perfetto/trace/trace_packet.pb.h"
namespace android {
namespace bpf {
-
-__be16 bindAndListen(int s) {
- sockaddr_in sin = {.sin_family = AF_INET};
- socklen_t len = sizeof(sin);
- if (bind(s, (sockaddr*)&sin, sizeof(sin))) return 0;
- if (listen(s, 1)) return 0;
- if (getsockname(s, (sockaddr*)&sin, &len)) return 0;
- return sin.sin_port;
-}
-
-// This takes tcp flag constants from the standard library and makes them usable
-// with the flags we get from BPF. The standard library flags are big endian
-// whereas the BPF flags are reported in host byte order. BPF also trims the
-// flags down to the 8 single-bit flag bits (fin, syn, rst, etc).
-constexpr inline uint8_t FlagToHost(__be32 be_unix_flags) {
- return ntohl(be_unix_flags) >> 16;
-}
-
-// Pretty prints all fields for a list of packets (useful for debugging).
-struct PacketPrinter {
- const std::vector<PacketTrace>& data;
- static constexpr char kTcpFlagNames[] = "FSRPAUEC";
-
- friend std::ostream& operator<<(std::ostream& os, const PacketPrinter& d) {
- os << "Packet count: " << d.data.size();
- for (const PacketTrace& info : d.data) {
- os << "\nifidx=" << info.ifindex;
- os << ", len=" << info.length;
- os << ", uid=" << info.uid;
- os << ", tag=" << info.tag;
- os << ", sport=" << info.sport;
- os << ", dport=" << info.dport;
- os << ", direction=" << (info.egress ? "egress" : "ingress");
- os << ", proto=" << static_cast<int>(info.ipProto);
- os << ", ip=" << static_cast<int>(info.ipVersion);
- os << ", flags=";
- for (int i = 0; i < 8; i++) {
- os << ((info.tcpFlags & (1 << i)) ? kTcpFlagNames[i] : '.');
- }
- }
- return os;
- }
-};
+using ::perfetto::protos::NetworkPacketEvent;
+using ::perfetto::protos::NetworkPacketTraceConfig;
+using ::perfetto::protos::Trace;
+using ::perfetto::protos::TracePacket;
+using ::perfetto::protos::TrafficDirection;
class NetworkTraceHandlerTest : public testing::Test {
protected:
- void SetUp() {
- if (access(PACKET_TRACE_RINGBUF_PATH, R_OK)) {
- GTEST_SKIP() << "Network tracing is not enabled/loaded on this build";
+ // Starts a tracing session with the handler under test.
+ std::unique_ptr<perfetto::TracingSession> StartTracing(
+ NetworkPacketTraceConfig settings) {
+ perfetto::TracingInitArgs args;
+ args.backends = perfetto::kInProcessBackend;
+ perfetto::Tracing::Initialize(args);
+
+ perfetto::DataSourceDescriptor dsd;
+ dsd.set_name("test.network_packets");
+ NetworkTraceHandler::Register(dsd, /*isTest=*/true);
+
+ perfetto::TraceConfig cfg;
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* config = cfg.add_data_sources()->mutable_config();
+ config->set_name("test.network_packets");
+ config->set_network_packet_trace_config_raw(settings.SerializeAsString());
+
+ auto session = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
+ session->Setup(cfg);
+ session->StartBlocking();
+ return session;
+ }
+
+ // Stops the trace session and reports all relevant trace packets.
+ bool StopTracing(perfetto::TracingSession* session,
+ std::vector<TracePacket>* output) {
+ session->StopBlocking();
+
+ Trace trace;
+ std::vector<char> raw_trace = session->ReadTraceBlocking();
+ if (!trace.ParseFromArray(raw_trace.data(), raw_trace.size())) {
+ ADD_FAILURE() << "trace.ParseFromArray failed";
+ return false;
}
+
+ // This is a real trace and includes irrelevant trace packets such as trace
+ // metadata. The following strips the results to just the packets we want.
+ for (const auto& pkt : trace.packet()) {
+ if (pkt.has_network_packet() || pkt.has_network_packet_bundle()) {
+ output->emplace_back(pkt);
+ }
+ }
+
+ return true;
+ }
+
+ // This runs a trace with a single call to Write.
+ bool TraceAndSortPackets(const std::vector<PacketTrace>& input,
+ std::vector<TracePacket>* output,
+ NetworkPacketTraceConfig config = {}) {
+ auto session = StartTracing(config);
+ NetworkTraceHandler::Trace([&](NetworkTraceHandler::TraceContext ctx) {
+ ctx.GetDataSourceLocked()->Write(input, ctx);
+ ctx.Flush();
+ });
+
+ if (!StopTracing(session.get(), output)) {
+ return false;
+ }
+
+ // Sort to provide deterministic ordering regardless of Perfetto internals
+ // or implementation-defined (e.g. hash map) reshuffling.
+ std::sort(output->begin(), output->end(),
+ [](const TracePacket& a, const TracePacket& b) {
+ return a.timestamp() < b.timestamp();
+ });
+
+ return true;
}
};
-TEST_F(NetworkTraceHandlerTest, PollWhileInactive) {
- NetworkTraceHandler handler([&](const PacketTrace& pkt) {});
+TEST_F(NetworkTraceHandlerTest, WriteBasicFields) {
+ std::vector<PacketTrace> input = {
+ PacketTrace{
+ .timestampNs = 1000,
+ .length = 100,
+ .uid = 10,
+ .tag = 123,
+ .ipProto = 6,
+ .tcpFlags = 1,
+ },
+ };
- // One succeed after start and before stop.
- EXPECT_FALSE(handler.ConsumeAll());
- ASSERT_TRUE(handler.Start());
- EXPECT_TRUE(handler.ConsumeAll());
- ASSERT_TRUE(handler.Stop());
- EXPECT_FALSE(handler.ConsumeAll());
+ std::vector<TracePacket> events;
+ ASSERT_TRUE(TraceAndSortPackets(input, &events));
+
+ ASSERT_EQ(events.size(), 1);
+ EXPECT_THAT(events[0].timestamp(), 1000);
+ EXPECT_THAT(events[0].network_packet().uid(), 10);
+ EXPECT_THAT(events[0].network_packet().tag(), 123);
+ EXPECT_THAT(events[0].network_packet().ip_proto(), 6);
+ EXPECT_THAT(events[0].network_packet().tcp_flags(), 1);
+ EXPECT_THAT(events[0].network_packet().length(), 100);
+ EXPECT_THAT(events[0].has_sequence_flags(), false);
}
-TEST_F(NetworkTraceHandlerTest, TraceTcpSession) {
- __be16 server_port = 0;
- std::vector<PacketTrace> packets;
+TEST_F(NetworkTraceHandlerTest, WriteDirectionAndPorts) {
+ std::vector<PacketTrace> input = {
+ PacketTrace{
+ .timestampNs = 1,
+ .sport = htons(8080),
+ .dport = htons(443),
+ .egress = true,
+ },
+ PacketTrace{
+ .timestampNs = 2,
+ .sport = htons(443),
+ .dport = htons(8080),
+ .egress = false,
+ },
+ };
- // Record all packets with the bound address and current uid. This callback is
- // involked only within ConsumeAll, at which point the port should have
- // already been filled in and all packets have been processed.
- NetworkTraceHandler handler([&](const PacketTrace& pkt) {
- if (pkt.sport != server_port && pkt.dport != server_port) return;
- if (pkt.uid != getuid()) return;
- packets.push_back(pkt);
+ std::vector<TracePacket> events;
+ ASSERT_TRUE(TraceAndSortPackets(input, &events));
+
+ ASSERT_EQ(events.size(), 2);
+ EXPECT_THAT(events[0].network_packet().local_port(), 8080);
+ EXPECT_THAT(events[0].network_packet().remote_port(), 443);
+ EXPECT_THAT(events[0].network_packet().direction(),
+ TrafficDirection::DIR_EGRESS);
+ EXPECT_THAT(events[1].network_packet().local_port(), 8080);
+ EXPECT_THAT(events[1].network_packet().remote_port(), 443);
+ EXPECT_THAT(events[1].network_packet().direction(),
+ TrafficDirection::DIR_INGRESS);
+}
+
+TEST_F(NetworkTraceHandlerTest, BasicBundling) {
+ // TODO: remove this once bundling becomes default. Until then, set arbitrary
+ // aggregation threshold to enable bundling.
+ NetworkPacketTraceConfig config;
+ config.set_aggregation_threshold(10);
+
+ std::vector<PacketTrace> input = {
+ PacketTrace{.uid = 123, .timestampNs = 2, .length = 200},
+ PacketTrace{.uid = 123, .timestampNs = 1, .length = 100},
+ PacketTrace{.uid = 123, .timestampNs = 4, .length = 300},
+
+ PacketTrace{.uid = 456, .timestampNs = 2, .length = 400},
+ PacketTrace{.uid = 456, .timestampNs = 4, .length = 100},
+ };
+
+ std::vector<TracePacket> events;
+ ASSERT_TRUE(TraceAndSortPackets(input, &events, config));
+
+ ASSERT_EQ(events.size(), 2);
+
+ EXPECT_THAT(events[0].timestamp(), 1);
+ EXPECT_THAT(events[0].network_packet_bundle().ctx().uid(), 123);
+ EXPECT_THAT(events[0].network_packet_bundle().packet_lengths(),
+ testing::ElementsAre(200, 100, 300));
+ EXPECT_THAT(events[0].network_packet_bundle().packet_timestamps(),
+ testing::ElementsAre(1, 0, 3));
+
+ EXPECT_THAT(events[1].timestamp(), 2);
+ EXPECT_THAT(events[1].network_packet_bundle().ctx().uid(), 456);
+ EXPECT_THAT(events[1].network_packet_bundle().packet_lengths(),
+ testing::ElementsAre(400, 100));
+ EXPECT_THAT(events[1].network_packet_bundle().packet_timestamps(),
+ testing::ElementsAre(0, 2));
+}
+
+TEST_F(NetworkTraceHandlerTest, AggregationThreshold) {
+ // With an aggregation threshold of 3, the set of packets with uid=123 will
+ // be aggregated (3>=3) whereas packets with uid=456 get per-packet info.
+ NetworkPacketTraceConfig config;
+ config.set_aggregation_threshold(3);
+
+ std::vector<PacketTrace> input = {
+ PacketTrace{.uid = 123, .timestampNs = 2, .length = 200},
+ PacketTrace{.uid = 123, .timestampNs = 1, .length = 100},
+ PacketTrace{.uid = 123, .timestampNs = 4, .length = 300},
+
+ PacketTrace{.uid = 456, .timestampNs = 2, .length = 400},
+ PacketTrace{.uid = 456, .timestampNs = 4, .length = 100},
+ };
+
+ std::vector<TracePacket> events;
+ ASSERT_TRUE(TraceAndSortPackets(input, &events, config));
+
+ ASSERT_EQ(events.size(), 2);
+
+ EXPECT_EQ(events[0].timestamp(), 1);
+ EXPECT_EQ(events[0].network_packet_bundle().ctx().uid(), 123);
+ EXPECT_EQ(events[0].network_packet_bundle().total_duration(), 3);
+ EXPECT_EQ(events[0].network_packet_bundle().total_packets(), 3);
+ EXPECT_EQ(events[0].network_packet_bundle().total_length(), 600);
+
+ EXPECT_EQ(events[1].timestamp(), 2);
+ EXPECT_EQ(events[1].network_packet_bundle().ctx().uid(), 456);
+ EXPECT_THAT(events[1].network_packet_bundle().packet_lengths(),
+ testing::ElementsAre(400, 100));
+ EXPECT_THAT(events[1].network_packet_bundle().packet_timestamps(),
+ testing::ElementsAre(0, 2));
+}
+
+TEST_F(NetworkTraceHandlerTest, DropLocalPort) {
+ NetworkPacketTraceConfig config;
+ config.set_drop_local_port(true);
+ config.set_aggregation_threshold(10);
+
+ __be16 a = htons(10000);
+ __be16 b = htons(10001);
+ std::vector<PacketTrace> input = {
+ // Recall that local is `src` for egress and `dst` for ingress.
+ PacketTrace{.timestampNs = 1, .length = 2, .egress = true, .sport = a},
+ PacketTrace{.timestampNs = 2, .length = 4, .egress = false, .dport = a},
+ PacketTrace{.timestampNs = 3, .length = 6, .egress = true, .sport = b},
+ PacketTrace{.timestampNs = 4, .length = 8, .egress = false, .dport = b},
+ };
+
+ std::vector<TracePacket> events;
+ ASSERT_TRUE(TraceAndSortPackets(input, &events, config));
+ ASSERT_EQ(events.size(), 2);
+
+ // Despite having different local ports, drop and bundle by remaining fields.
+ EXPECT_EQ(events[0].network_packet_bundle().ctx().direction(),
+ TrafficDirection::DIR_EGRESS);
+ EXPECT_THAT(events[0].network_packet_bundle().packet_lengths(),
+ testing::ElementsAre(2, 6));
+
+ EXPECT_EQ(events[1].network_packet_bundle().ctx().direction(),
+ TrafficDirection::DIR_INGRESS);
+ EXPECT_THAT(events[1].network_packet_bundle().packet_lengths(),
+ testing::ElementsAre(4, 8));
+
+ // Local port shouldn't be in output.
+ EXPECT_FALSE(events[0].network_packet_bundle().ctx().has_local_port());
+ EXPECT_FALSE(events[1].network_packet_bundle().ctx().has_local_port());
+}
+
+TEST_F(NetworkTraceHandlerTest, DropRemotePort) {
+ NetworkPacketTraceConfig config;
+ config.set_drop_remote_port(true);
+ config.set_aggregation_threshold(10);
+
+ __be16 a = htons(443);
+ __be16 b = htons(80);
+ std::vector<PacketTrace> input = {
+ // Recall that remote is `dst` for egress and `src` for ingress.
+ PacketTrace{.timestampNs = 1, .length = 2, .egress = true, .dport = a},
+ PacketTrace{.timestampNs = 2, .length = 4, .egress = false, .sport = a},
+ PacketTrace{.timestampNs = 3, .length = 6, .egress = true, .dport = b},
+ PacketTrace{.timestampNs = 4, .length = 8, .egress = false, .sport = b},
+ };
+
+ std::vector<TracePacket> events;
+ ASSERT_TRUE(TraceAndSortPackets(input, &events, config));
+ ASSERT_EQ(events.size(), 2);
+
+ // Despite having different remote ports, drop and bundle by remaining fields.
+ EXPECT_EQ(events[0].network_packet_bundle().ctx().direction(),
+ TrafficDirection::DIR_EGRESS);
+ EXPECT_THAT(events[0].network_packet_bundle().packet_lengths(),
+ testing::ElementsAre(2, 6));
+
+ EXPECT_EQ(events[1].network_packet_bundle().ctx().direction(),
+ TrafficDirection::DIR_INGRESS);
+ EXPECT_THAT(events[1].network_packet_bundle().packet_lengths(),
+ testing::ElementsAre(4, 8));
+
+ // Remote port shouldn't be in output.
+ EXPECT_FALSE(events[0].network_packet_bundle().ctx().has_remote_port());
+ EXPECT_FALSE(events[1].network_packet_bundle().ctx().has_remote_port());
+}
+
+TEST_F(NetworkTraceHandlerTest, DropTcpFlags) {
+ NetworkPacketTraceConfig config;
+ config.set_drop_tcp_flags(true);
+ config.set_aggregation_threshold(10);
+
+ std::vector<PacketTrace> input = {
+ PacketTrace{.timestampNs = 1, .uid = 123, .length = 1, .tcpFlags = 1},
+ PacketTrace{.timestampNs = 2, .uid = 123, .length = 2, .tcpFlags = 2},
+ PacketTrace{.timestampNs = 3, .uid = 456, .length = 3, .tcpFlags = 1},
+ PacketTrace{.timestampNs = 4, .uid = 456, .length = 4, .tcpFlags = 2},
+ };
+
+ std::vector<TracePacket> events;
+ ASSERT_TRUE(TraceAndSortPackets(input, &events, config));
+
+ ASSERT_EQ(events.size(), 2);
+
+ // Despite having different tcp flags, drop and bundle by remaining fields.
+ EXPECT_EQ(events[0].network_packet_bundle().ctx().uid(), 123);
+ EXPECT_THAT(events[0].network_packet_bundle().packet_lengths(),
+ testing::ElementsAre(1, 2));
+
+ EXPECT_EQ(events[1].network_packet_bundle().ctx().uid(), 456);
+ EXPECT_THAT(events[1].network_packet_bundle().packet_lengths(),
+ testing::ElementsAre(3, 4));
+
+ // Tcp flags shouldn't be in output.
+ EXPECT_FALSE(events[0].network_packet_bundle().ctx().has_tcp_flags());
+ EXPECT_FALSE(events[1].network_packet_bundle().ctx().has_tcp_flags());
+}
+
+TEST_F(NetworkTraceHandlerTest, Interning) {
+ NetworkPacketTraceConfig config;
+ config.set_intern_limit(2);
+
+ // The test writes 4 packets coming from three sources (uids). With an intern
+ // limit of 2, the first two sources should be interned. This test splits this
+ // into individual writes since internally an unordered map is used and would
+ // otherwise non-deterministically choose what to intern (this is fine for
+ // real use, but not good for test assertions).
+ std::vector<std::vector<PacketTrace>> inputs = {
+ {PacketTrace{.timestampNs = 1, .uid = 123}},
+ {PacketTrace{.timestampNs = 2, .uid = 456}},
+ {PacketTrace{.timestampNs = 3, .uid = 789}},
+ {PacketTrace{.timestampNs = 4, .uid = 123}},
+ };
+
+ auto session = StartTracing(config);
+
+ NetworkTraceHandler::Trace([&](NetworkTraceHandler::TraceContext ctx) {
+ ctx.GetDataSourceLocked()->Write(inputs[0], ctx);
+ ctx.GetDataSourceLocked()->Write(inputs[1], ctx);
+ ctx.GetDataSourceLocked()->Write(inputs[2], ctx);
+ ctx.GetDataSourceLocked()->Write(inputs[3], ctx);
+ ctx.Flush();
});
- ASSERT_TRUE(handler.Start());
- const uint32_t kClientTag = 2468;
- const uint32_t kServerTag = 1357;
+ std::vector<TracePacket> events;
+ ASSERT_TRUE(StopTracing(session.get(), &events));
- // Go through a typical connection sequence between two v4 sockets using tcp.
- // This covers connection handshake, shutdown, and one data packet.
- {
- android::base::unique_fd clientsocket(socket(AF_INET, SOCK_STREAM, 0));
- ASSERT_NE(-1, clientsocket) << "Failed to open client socket";
- ASSERT_EQ(android_tag_socket(clientsocket, kClientTag), 0);
+ ASSERT_EQ(events.size(), 4);
- android::base::unique_fd serversocket(socket(AF_INET, SOCK_STREAM, 0));
- ASSERT_NE(-1, serversocket) << "Failed to open server socket";
- ASSERT_EQ(android_tag_socket(serversocket, kServerTag), 0);
+ // First time seen, emit new interned data, bundle uses iid instead of ctx.
+ EXPECT_EQ(events[0].network_packet_bundle().iid(), 1);
+ ASSERT_EQ(events[0].interned_data().packet_context().size(), 1);
+ EXPECT_EQ(events[0].interned_data().packet_context(0).iid(), 1);
+ EXPECT_EQ(events[0].interned_data().packet_context(0).ctx().uid(), 123);
+ EXPECT_EQ(events[0].sequence_flags(),
+ TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
- server_port = bindAndListen(serversocket);
- ASSERT_NE(0, server_port) << "Can't bind to server port";
+ // First time seen, emit new interned data, bundle uses iid instead of ctx.
+ EXPECT_EQ(events[1].network_packet_bundle().iid(), 2);
+ ASSERT_EQ(events[1].interned_data().packet_context().size(), 1);
+ EXPECT_EQ(events[1].interned_data().packet_context(0).iid(), 2);
+ EXPECT_EQ(events[1].interned_data().packet_context(0).ctx().uid(), 456);
+ EXPECT_EQ(events[1].sequence_flags(),
+ TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
- sockaddr_in addr = {.sin_family = AF_INET, .sin_port = server_port};
- ASSERT_EQ(0, connect(clientsocket, (sockaddr*)&addr, sizeof(addr)))
- << "connect to loopback failed: " << strerror(errno);
+ // Not enough room in intern table (limit 2), inline the context.
+ EXPECT_EQ(events[2].network_packet_bundle().ctx().uid(), 789);
+ EXPECT_EQ(events[2].interned_data().packet_context().size(), 0);
+ EXPECT_EQ(events[2].sequence_flags(),
+ TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
- int accepted = accept(serversocket, nullptr, nullptr);
- ASSERT_NE(-1, accepted) << "accept connection failed: " << strerror(errno);
-
- const char data[] = "abcdefghijklmnopqrstuvwxyz";
- EXPECT_EQ(send(clientsocket, data, sizeof(data), 0), sizeof(data))
- << "failed to send message: " << strerror(errno);
-
- char buff[100] = {};
- EXPECT_EQ(recv(accepted, buff, sizeof(buff), 0), sizeof(data))
- << "failed to receive message: " << strerror(errno);
-
- EXPECT_EQ(std::string(data), std::string(buff));
- }
-
- ASSERT_TRUE(handler.ConsumeAll());
- ASSERT_TRUE(handler.Stop());
-
- // There are 12 packets in total (6 messages: each seen by client & server):
- // 1. Client connects to server with syn
- // 2. Server responds with syn ack
- // 3. Client responds with ack
- // 4. Client sends data with psh ack
- // 5. Server acks the data packet
- // 6. Client closes connection with fin ack
- ASSERT_EQ(packets.size(), 12) << PacketPrinter{packets};
-
- // All packets should be TCP packets.
- EXPECT_THAT(packets, Each(Field(&PacketTrace::ipProto, Eq(IPPROTO_TCP))));
-
- // Packet 1: client requests connection with server.
- EXPECT_EQ(packets[0].egress, 1) << PacketPrinter{packets};
- EXPECT_EQ(packets[0].dport, server_port) << PacketPrinter{packets};
- EXPECT_EQ(packets[0].tag, kClientTag) << PacketPrinter{packets};
- EXPECT_EQ(packets[0].tcpFlags, FlagToHost(TCP_FLAG_SYN))
- << PacketPrinter{packets};
-
- // Packet 2: server receives request from client.
- EXPECT_EQ(packets[1].egress, 0) << PacketPrinter{packets};
- EXPECT_EQ(packets[1].dport, server_port) << PacketPrinter{packets};
- EXPECT_EQ(packets[1].tag, kServerTag) << PacketPrinter{packets};
- EXPECT_EQ(packets[1].tcpFlags, FlagToHost(TCP_FLAG_SYN))
- << PacketPrinter{packets};
-
- // Packet 3: server replies back with syn ack.
- EXPECT_EQ(packets[2].egress, 1) << PacketPrinter{packets};
- EXPECT_EQ(packets[2].sport, server_port) << PacketPrinter{packets};
- EXPECT_EQ(packets[2].tcpFlags, FlagToHost(TCP_FLAG_SYN | TCP_FLAG_ACK))
- << PacketPrinter{packets};
-
- // Packet 4: client receives the server's syn ack.
- EXPECT_EQ(packets[3].egress, 0) << PacketPrinter{packets};
- EXPECT_EQ(packets[3].sport, server_port) << PacketPrinter{packets};
- EXPECT_EQ(packets[3].tcpFlags, FlagToHost(TCP_FLAG_SYN | TCP_FLAG_ACK))
- << PacketPrinter{packets};
+ // Second time seen, no need to re-emit interned data, only record iid.
+ EXPECT_EQ(events[3].network_packet_bundle().iid(), 1);
+ EXPECT_EQ(events[3].interned_data().packet_context().size(), 0);
+ EXPECT_EQ(events[3].sequence_flags(),
+ TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
}
} // namespace bpf
diff --git a/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp b/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp
new file mode 100644
index 0000000..3de9897
--- /dev/null
+++ b/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 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 "NetworkTrace"
+
+#include "netdbpf/NetworkTracePoller.h"
+
+#include <bpf/BpfUtils.h>
+#include <log/log.h>
+#include <perfetto/tracing/platform.h>
+#include <perfetto/tracing/tracing.h>
+
+namespace android {
+namespace bpf {
+namespace internal {
+
+void NetworkTracePoller::SchedulePolling() {
+ // Schedules another run of ourselves to recursively poll periodically.
+ mTaskRunner->PostDelayedTask(
+ [this]() {
+ mMutex.lock();
+ SchedulePolling();
+ ConsumeAllLocked();
+ mMutex.unlock();
+ },
+ mPollMs);
+}
+
+bool NetworkTracePoller::Start(uint32_t pollMs) {
+ ALOGD("Starting datasource");
+
+ std::scoped_lock<std::mutex> lock(mMutex);
+ if (mSessionCount > 0) {
+ if (mPollMs != pollMs) {
+ // Nothing technical prevents mPollMs from changing, it's just unclear
+ // what the right behavior is. Taking the min of active values could poll
+ // too frequently giving some sessions too much data. Taking the max could
+ // be too infrequent. For now, do nothing.
+ ALOGI("poll_ms can't be changed while running, ignoring poll_ms=%d",
+ pollMs);
+ }
+ mSessionCount++;
+ return true;
+ }
+
+ auto status = mConfigurationMap.init(PACKET_TRACE_ENABLED_MAP_PATH);
+ if (!status.ok()) {
+ ALOGW("Failed to bind config map: %s", status.error().message().c_str());
+ return false;
+ }
+
+ auto rb = BpfRingbuf<PacketTrace>::Create(PACKET_TRACE_RINGBUF_PATH);
+ if (!rb.ok()) {
+ ALOGW("Failed to create ringbuf: %s", rb.error().message().c_str());
+ return false;
+ }
+
+ mRingBuffer = std::move(*rb);
+
+ auto res = mConfigurationMap.writeValue(0, true, BPF_ANY);
+ if (!res.ok()) {
+ ALOGW("Failed to enable tracing: %s", res.error().message().c_str());
+ return false;
+ }
+
+ // Start a task runner to run ConsumeAll every mPollMs milliseconds.
+ mTaskRunner = perfetto::Platform::GetDefaultPlatform()->CreateTaskRunner({});
+ mPollMs = pollMs;
+ SchedulePolling();
+
+ mSessionCount++;
+ return true;
+}
+
+bool NetworkTracePoller::Stop() {
+ ALOGD("Stopping datasource");
+
+ std::scoped_lock<std::mutex> lock(mMutex);
+ if (mSessionCount == 0) return false; // This should never happen
+
+ // If this isn't the last session, don't clean up yet.
+ if (--mSessionCount > 0) return true;
+
+ auto res = mConfigurationMap.writeValue(0, false, BPF_ANY);
+ if (!res.ok()) {
+ ALOGW("Failed to disable tracing: %s", res.error().message().c_str());
+ }
+
+ // Make sure everything in the system has actually seen the 'false' we just
+ // wrote, things should now be well and truly disabled.
+ synchronizeKernelRCU();
+
+ // Drain remaining events from the ring buffer now that tracing is disabled.
+ // This prevents the next trace from seeing stale events and allows writing
+ // the last batch of events to Perfetto.
+ ConsumeAllLocked();
+
+ mTaskRunner.reset();
+ mRingBuffer.reset();
+
+ return res.ok();
+}
+
+bool NetworkTracePoller::ConsumeAll() {
+ std::scoped_lock<std::mutex> lock(mMutex);
+ return ConsumeAllLocked();
+}
+
+bool NetworkTracePoller::ConsumeAllLocked() {
+ if (mRingBuffer == nullptr) {
+ ALOGW("Tracing is not active");
+ return false;
+ }
+
+ std::vector<PacketTrace> packets;
+ base::Result<int> ret = mRingBuffer->ConsumeAll(
+ [&](const PacketTrace& pkt) { packets.push_back(pkt); });
+ if (!ret.ok()) {
+ ALOGW("Failed to poll ringbuf: %s", ret.error().message().c_str());
+ return false;
+ }
+
+ mCallback(packets);
+
+ return true;
+}
+
+} // namespace internal
+} // namespace bpf
+} // namespace android
diff --git a/service-t/native/libs/libnetworkstats/NetworkTracePollerTest.cpp b/service-t/native/libs/libnetworkstats/NetworkTracePollerTest.cpp
new file mode 100644
index 0000000..df07bbe
--- /dev/null
+++ b/service-t/native/libs/libnetworkstats/NetworkTracePollerTest.cpp
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2023 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 <android-base/unique_fd.h>
+#include <android/multinetwork.h>
+#include <arpa/inet.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <inttypes.h>
+#include <net/if.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <chrono>
+#include <thread>
+#include <vector>
+
+#include "netdbpf/NetworkTracePoller.h"
+
+using ::testing::AllOf;
+using ::testing::AnyOf;
+using ::testing::Each;
+using ::testing::Eq;
+using ::testing::Field;
+using ::testing::Test;
+
+namespace android {
+namespace bpf {
+namespace internal {
+// Use uint32 max to cause the handler to never Loop. Instead, the tests will
+// manually drive things by calling ConsumeAll explicitly.
+constexpr uint32_t kNeverPoll = std::numeric_limits<uint32_t>::max();
+
+__be16 bindAndListen(int s) {
+ sockaddr_in sin = {.sin_family = AF_INET};
+ socklen_t len = sizeof(sin);
+ if (bind(s, (sockaddr*)&sin, sizeof(sin))) return 0;
+ if (listen(s, 1)) return 0;
+ if (getsockname(s, (sockaddr*)&sin, &len)) return 0;
+ return sin.sin_port;
+}
+
+// This takes tcp flag constants from the standard library and makes them usable
+// with the flags we get from BPF. The standard library flags are big endian
+// whereas the BPF flags are reported in host byte order. BPF also trims the
+// flags down to the 8 single-bit flag bits (fin, syn, rst, etc).
+constexpr inline uint8_t FlagToHost(__be32 be_unix_flags) {
+ return ntohl(be_unix_flags) >> 16;
+}
+
+// Pretty prints all fields for a list of packets (useful for debugging).
+struct PacketPrinter {
+ const std::vector<PacketTrace>& data;
+ static constexpr char kTcpFlagNames[] = "FSRPAUEC";
+
+ friend std::ostream& operator<<(std::ostream& os, const PacketPrinter& d) {
+ os << "Packet count: " << d.data.size();
+ for (const PacketTrace& info : d.data) {
+ os << "\nifidx=" << info.ifindex;
+ os << ", len=" << info.length;
+ os << ", uid=" << info.uid;
+ os << ", tag=" << info.tag;
+ os << ", sport=" << info.sport;
+ os << ", dport=" << info.dport;
+ os << ", direction=" << (info.egress ? "egress" : "ingress");
+ os << ", proto=" << static_cast<int>(info.ipProto);
+ os << ", ip=" << static_cast<int>(info.ipVersion);
+ os << ", flags=";
+ for (int i = 0; i < 8; i++) {
+ os << ((info.tcpFlags & (1 << i)) ? kTcpFlagNames[i] : '.');
+ }
+ }
+ return os;
+ }
+};
+
+class NetworkTracePollerTest : public testing::Test {
+ protected:
+ void SetUp() {
+ if (access(PACKET_TRACE_RINGBUF_PATH, R_OK)) {
+ GTEST_SKIP() << "Network tracing is not enabled/loaded on this build.";
+ }
+ if (sizeof(void*) != 8) {
+ GTEST_SKIP() << "Network tracing requires 64-bit build.";
+ }
+ }
+};
+
+TEST_F(NetworkTracePollerTest, PollWhileInactive) {
+ NetworkTracePoller handler([&](const std::vector<PacketTrace>& pkt) {});
+
+ // One succeed after start and before stop.
+ EXPECT_FALSE(handler.ConsumeAll());
+ ASSERT_TRUE(handler.Start(kNeverPoll));
+ EXPECT_TRUE(handler.ConsumeAll());
+ ASSERT_TRUE(handler.Stop());
+ EXPECT_FALSE(handler.ConsumeAll());
+}
+
+TEST_F(NetworkTracePollerTest, ConcurrentSessions) {
+ // Simulate two concurrent sessions (two starts followed by two stops). Check
+ // that tracing is stopped only after both sessions finish.
+ NetworkTracePoller handler([&](const std::vector<PacketTrace>& pkt) {});
+
+ ASSERT_TRUE(handler.Start(kNeverPoll));
+ EXPECT_TRUE(handler.ConsumeAll());
+
+ ASSERT_TRUE(handler.Start(kNeverPoll));
+ EXPECT_TRUE(handler.ConsumeAll());
+
+ ASSERT_TRUE(handler.Stop());
+ EXPECT_TRUE(handler.ConsumeAll());
+
+ ASSERT_TRUE(handler.Stop());
+ EXPECT_FALSE(handler.ConsumeAll());
+}
+
+TEST_F(NetworkTracePollerTest, TraceTcpSession) {
+ __be16 server_port = 0;
+ std::vector<PacketTrace> packets, unmatched;
+
+ // Record all packets with the bound address and current uid. This callback is
+ // involked only within ConsumeAll, at which point the port should have
+ // already been filled in and all packets have been processed.
+ NetworkTracePoller handler([&](const std::vector<PacketTrace>& pkts) {
+ for (const PacketTrace& pkt : pkts) {
+ if ((pkt.sport == server_port || pkt.dport == server_port) &&
+ pkt.uid == getuid()) {
+ packets.push_back(pkt);
+ } else {
+ // There may be spurious packets not caused by the test. These are only
+ // captured so that we can report them to help debug certain errors.
+ unmatched.push_back(pkt);
+ }
+ }
+ });
+
+ ASSERT_TRUE(handler.Start(kNeverPoll));
+ const uint32_t kClientTag = 2468;
+ const uint32_t kServerTag = 1357;
+
+ // Go through a typical connection sequence between two v4 sockets using tcp.
+ // This covers connection handshake, shutdown, and one data packet.
+ {
+ android::base::unique_fd clientsocket(socket(AF_INET, SOCK_STREAM, 0));
+ ASSERT_NE(-1, clientsocket) << "Failed to open client socket";
+ ASSERT_EQ(android_tag_socket(clientsocket, kClientTag), 0);
+
+ android::base::unique_fd serversocket(socket(AF_INET, SOCK_STREAM, 0));
+ ASSERT_NE(-1, serversocket) << "Failed to open server socket";
+ ASSERT_EQ(android_tag_socket(serversocket, kServerTag), 0);
+
+ server_port = bindAndListen(serversocket);
+ ASSERT_NE(0, server_port) << "Can't bind to server port";
+
+ sockaddr_in addr = {.sin_family = AF_INET, .sin_port = server_port};
+ ASSERT_EQ(0, connect(clientsocket, (sockaddr*)&addr, sizeof(addr)))
+ << "connect to loopback failed: " << strerror(errno);
+
+ int accepted = accept(serversocket, nullptr, nullptr);
+ ASSERT_NE(-1, accepted) << "accept connection failed: " << strerror(errno);
+
+ const char data[] = "abcdefghijklmnopqrstuvwxyz";
+ EXPECT_EQ(send(clientsocket, data, sizeof(data), 0), sizeof(data))
+ << "failed to send message: " << strerror(errno);
+
+ char buff[100] = {};
+ EXPECT_EQ(recv(accepted, buff, sizeof(buff), 0), sizeof(data))
+ << "failed to receive message: " << strerror(errno);
+
+ EXPECT_EQ(std::string(data), std::string(buff));
+ }
+
+ // Poll until we get all the packets (typically we get it first try).
+ for (int attempt = 0; attempt < 10; attempt++) {
+ ASSERT_TRUE(handler.ConsumeAll());
+ if (packets.size() >= 12) break;
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
+ }
+
+ ASSERT_TRUE(handler.Stop());
+
+ // There are 12 packets in total (6 messages: each seen by client & server):
+ // 1. Client connects to server with syn
+ // 2. Server responds with syn ack
+ // 3. Client responds with ack
+ // 4. Client sends data with psh ack
+ // 5. Server acks the data packet
+ // 6. Client closes connection with fin ack
+ ASSERT_EQ(packets.size(), 12)
+ << PacketPrinter{packets}
+ << "\nUnmatched packets: " << PacketPrinter{unmatched};
+
+ // All packets should be TCP packets.
+ EXPECT_THAT(packets, Each(Field(&PacketTrace::ipProto, Eq(IPPROTO_TCP))));
+
+ // Packet 1: client requests connection with server.
+ EXPECT_EQ(packets[0].egress, 1) << PacketPrinter{packets};
+ EXPECT_EQ(packets[0].dport, server_port) << PacketPrinter{packets};
+ EXPECT_EQ(packets[0].tag, kClientTag) << PacketPrinter{packets};
+ EXPECT_EQ(packets[0].tcpFlags, FlagToHost(TCP_FLAG_SYN))
+ << PacketPrinter{packets};
+
+ // Packet 2: server receives request from client.
+ EXPECT_EQ(packets[1].egress, 0) << PacketPrinter{packets};
+ EXPECT_EQ(packets[1].dport, server_port) << PacketPrinter{packets};
+ EXPECT_EQ(packets[1].tag, kServerTag) << PacketPrinter{packets};
+ EXPECT_EQ(packets[1].tcpFlags, FlagToHost(TCP_FLAG_SYN))
+ << PacketPrinter{packets};
+
+ // Packet 3: server replies back with syn ack.
+ EXPECT_EQ(packets[2].egress, 1) << PacketPrinter{packets};
+ EXPECT_EQ(packets[2].sport, server_port) << PacketPrinter{packets};
+ EXPECT_EQ(packets[2].tcpFlags, FlagToHost(TCP_FLAG_SYN | TCP_FLAG_ACK))
+ << PacketPrinter{packets};
+
+ // Packet 4: client receives the server's syn ack.
+ EXPECT_EQ(packets[3].egress, 0) << PacketPrinter{packets};
+ EXPECT_EQ(packets[3].sport, server_port) << PacketPrinter{packets};
+ EXPECT_EQ(packets[3].tcpFlags, FlagToHost(TCP_FLAG_SYN | TCP_FLAG_ACK))
+ << PacketPrinter{packets};
+}
+
+} // namespace internal
+} // namespace bpf
+} // namespace android
diff --git a/service-t/native/libs/libnetworkstats/include/netdbpf/BpfNetworkStats.h b/service-t/native/libs/libnetworkstats/include/netdbpf/BpfNetworkStats.h
index 03a1a44..133009f 100644
--- a/service-t/native/libs/libnetworkstats/include/netdbpf/BpfNetworkStats.h
+++ b/service-t/native/libs/libnetworkstats/include/netdbpf/BpfNetworkStats.h
@@ -26,7 +26,7 @@
// TODO: set this to a proper value based on the map size;
constexpr int TAG_STATS_MAP_SOFT_LIMIT = 3;
constexpr int UID_ALL = -1;
-constexpr int TAG_ALL = -1;
+//constexpr int TAG_ALL = -1;
constexpr int TAG_NONE = 0;
constexpr int SET_ALL = -1;
constexpr int SET_DEFAULT = 0;
@@ -63,9 +63,8 @@
const BpfMap<uint32_t, StatsValue>& ifaceStatsMap,
const BpfMap<uint32_t, IfaceValue>& ifaceNameMap);
// For test only
-int parseBpfNetworkStatsDetailInternal(std::vector<stats_line>* lines,
- const std::vector<std::string>& limitIfaces, int limitTag,
- int limitUid, const BpfMap<StatsKey, StatsValue>& statsMap,
+int parseBpfNetworkStatsDetailInternal(std::vector<stats_line>& lines,
+ const BpfMap<StatsKey, StatsValue>& statsMap,
const BpfMap<uint32_t, IfaceValue>& ifaceMap);
// For test only
int cleanStatsMapInternal(const base::unique_fd& cookieTagMap, const base::unique_fd& tagStatsMap);
@@ -107,18 +106,16 @@
}
// For test only
-int parseBpfNetworkStatsDevInternal(std::vector<stats_line>* lines,
+int parseBpfNetworkStatsDevInternal(std::vector<stats_line>& lines,
const BpfMap<uint32_t, StatsValue>& statsMap,
const BpfMap<uint32_t, IfaceValue>& ifaceMap);
int bpfGetUidStats(uid_t uid, Stats* stats);
int bpfGetIfaceStats(const char* iface, Stats* stats);
-int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines,
- const std::vector<std::string>& limitIfaces, int limitTag,
- int limitUid);
+int parseBpfNetworkStatsDetail(std::vector<stats_line>* lines);
int parseBpfNetworkStatsDev(std::vector<stats_line>* lines);
-void groupNetworkStats(std::vector<stats_line>* lines);
+void groupNetworkStats(std::vector<stats_line>& lines);
int cleanStatsMap();
} // namespace bpf
} // namespace android
diff --git a/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h
index c257aa0..bc10e68 100644
--- a/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h
+++ b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h
@@ -22,8 +22,7 @@
#include <string>
#include <unordered_map>
-#include "bpf/BpfMap.h"
-#include "bpf/BpfRingbuf.h"
+#include "netdbpf/NetworkTracePoller.h"
// For PacketTrace struct definition
#include "netd.h"
@@ -31,7 +30,39 @@
namespace android {
namespace bpf {
-class NetworkTraceHandler : public perfetto::DataSource<NetworkTraceHandler> {
+// BundleKeys are PacketTraces where timestamp and length are ignored.
+using BundleKey = PacketTrace;
+
+// BundleKeys are hashed using all fields except timestamp/length.
+struct BundleHash {
+ std::size_t operator()(const BundleKey& a) const;
+};
+
+// BundleKeys are equal if all fields except timestamp/length are equal.
+struct BundleEq {
+ bool operator()(const BundleKey& a, const BundleKey& b) const;
+};
+
+// Track the bundles we've interned and their corresponding intern id (iid). We
+// use IncrementalState (rather than state in the Handler) so that we stay in
+// sync with Perfetto's periodic state clearing (which helps recover from packet
+// loss). When state is cleared, the state object is replaced with a new default
+// constructed instance.
+struct NetworkTraceState {
+ bool cleared = true;
+ std::unordered_map<BundleKey, uint64_t, BundleHash, BundleEq> iids;
+};
+
+// Inject our custom incremental state type using type traits.
+struct NetworkTraceTraits : public perfetto::DefaultDataSourceTraits {
+ using IncrementalStateType = NetworkTraceState;
+};
+
+// NetworkTraceHandler implements the android.network_packets data source. This
+// class is registered with Perfetto and is instantiated when tracing starts and
+// destroyed when tracing ends. There is one instance per trace session.
+class NetworkTraceHandler
+ : public perfetto::DataSource<NetworkTraceHandler, NetworkTraceTraits> {
public:
// Registers this DataSource.
static void RegisterDataSource();
@@ -39,45 +70,40 @@
// Connects to the system Perfetto daemon and registers the trace handler.
static void InitPerfettoTracing();
- // Initialize with the default Perfetto callback.
- NetworkTraceHandler();
-
- // Testonly: initialize with a callback capable of intercepting data.
- NetworkTraceHandler(std::function<void(const PacketTrace&)> callback)
- : mCallback(std::move(callback)) {}
-
- // Testonly: standalone functions without perfetto dependency.
- bool Start();
- bool Stop();
- bool ConsumeAll();
+ // When isTest is true, skip non-hermetic code.
+ NetworkTraceHandler(bool isTest = false) : mIsTest(isTest) {}
// perfetto::DataSource overrides:
- void OnSetup(const SetupArgs&) override;
+ void OnSetup(const SetupArgs& args) override;
void OnStart(const StartArgs&) override;
void OnStop(const StopArgs&) override;
- // Convert a PacketTrace into a Perfetto trace packet.
- void Fill(const PacketTrace& src,
- ::perfetto::protos::pbzero::TracePacket& dst);
+ // Writes the packets as Perfetto TracePackets, creating packets as needed
+ // using the provided callback (which allows easy testing).
+ void Write(const std::vector<PacketTrace>& packets,
+ NetworkTraceHandler::TraceContext& ctx);
private:
- void Loop();
+ // Convert a PacketTrace into a Perfetto trace packet.
+ void Fill(const PacketTrace& src,
+ ::perfetto::protos::pbzero::NetworkPacketEvent* event);
- // How often to poll the ring buffer, defined by the trace config.
+ // Fills in contextual information either inline or via interning.
+ ::perfetto::protos::pbzero::NetworkPacketBundle* FillWithInterning(
+ NetworkTraceState* state, const BundleKey& key,
+ ::perfetto::protos::pbzero::TracePacket* dst);
+
+ static internal::NetworkTracePoller sPoller;
+ bool mStarted;
+ bool mIsTest;
+
+ // Values from config, see proto for details.
uint32_t mPollMs;
-
- // The function to process PacketTrace, typically a Perfetto sink.
- std::function<void(const PacketTrace&)> mCallback;
-
- // The BPF ring buffer handle.
- std::unique_ptr<BpfRingbuf<PacketTrace>> mRingBuffer;
-
- // The packet tracing config map (really a 1-element array).
- BpfMap<uint32_t, bool> mConfigurationMap;
-
- // This must be the last member, causing it to be the first deleted. If it is
- // not, members required for callbacks can be deleted before it's stopped.
- std::unique_ptr<perfetto::base::TaskRunner> mTaskRunner;
+ uint32_t mInternLimit;
+ uint32_t mAggregationThreshold;
+ bool mDropLocalPort;
+ bool mDropRemotePort;
+ bool mDropTcpFlags;
};
} // namespace bpf
diff --git a/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTracePoller.h b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTracePoller.h
new file mode 100644
index 0000000..adde51e
--- /dev/null
+++ b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTracePoller.h
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2023, 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.
+ */
+
+#pragma once
+
+#include <perfetto/base/task_runner.h>
+#include <perfetto/tracing.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "android-base/thread_annotations.h"
+#include "bpf/BpfMap.h"
+#include "bpf/BpfRingbuf.h"
+
+// For PacketTrace struct definition
+#include "netd.h"
+
+namespace android {
+namespace bpf {
+namespace internal {
+
+// NetworkTracePoller is responsible for interactions with the BPF ring buffer
+// including polling. This class is an internal helper for NetworkTraceHandler,
+// it is not meant to be used elsewhere.
+class NetworkTracePoller {
+ public:
+ using EventSink = std::function<void(const std::vector<PacketTrace>&)>;
+
+ // Testonly: initialize with a callback capable of intercepting data.
+ NetworkTracePoller(EventSink callback) : mCallback(std::move(callback)) {}
+
+ // Starts tracing with the given poll interval.
+ bool Start(uint32_t pollMs) EXCLUDES(mMutex);
+
+ // Stops tracing and release any held state.
+ bool Stop() EXCLUDES(mMutex);
+
+ // Consumes all available events from the ringbuffer.
+ bool ConsumeAll() EXCLUDES(mMutex);
+
+ private:
+ void SchedulePolling() REQUIRES(mMutex);
+ bool ConsumeAllLocked() REQUIRES(mMutex);
+
+ std::mutex mMutex;
+
+ // Records the number of successfully started active sessions so that only the
+ // first active session attempts setup and only the last cleans up. Note that
+ // the session count will remain zero if Start fails. It is expected that Stop
+ // will not be called for any trace session where Start fails.
+ int mSessionCount GUARDED_BY(mMutex);
+
+ // How often to poll the ring buffer, defined by the trace config.
+ uint32_t mPollMs GUARDED_BY(mMutex);
+
+ // The function to process PacketTrace, typically a Perfetto sink.
+ EventSink mCallback GUARDED_BY(mMutex);
+
+ // The BPF ring buffer handle.
+ std::unique_ptr<BpfRingbuf<PacketTrace>> mRingBuffer GUARDED_BY(mMutex);
+
+ // The packet tracing config map (really a 1-element array).
+ BpfMap<uint32_t, bool> mConfigurationMap GUARDED_BY(mMutex);
+
+ // This must be the last member, causing it to be the first deleted. If it is
+ // not, members required for callbacks can be deleted before it's stopped.
+ std::unique_ptr<perfetto::base::TaskRunner> mTaskRunner GUARDED_BY(mMutex);
+};
+
+} // namespace internal
+} // namespace bpf
+} // namespace android
diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java
index 9e71eb3..a884840 100644
--- a/service-t/src/com/android/server/IpSecService.java
+++ b/service-t/src/com/android/server/IpSecService.java
@@ -17,6 +17,7 @@
package com.android.server;
import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.net.IpSecManager.FEATURE_IPSEC_TUNNEL_MIGRATION;
import static android.net.IpSecManager.INVALID_RESOURCE_ID;
import static android.system.OsConstants.AF_INET;
@@ -65,6 +66,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.PermissionUtils;
@@ -102,6 +104,7 @@
private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
private static final InetAddress INADDR_ANY;
+ private static final InetAddress IN6ADDR_ANY;
@VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10;
@@ -110,6 +113,8 @@
static {
try {
INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
+ IN6ADDR_ANY = InetAddress.getByAddress(
+ new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
@@ -1013,11 +1018,13 @@
private final class EncapSocketRecord extends OwnedResourceRecord {
private FileDescriptor mSocket;
private final int mPort;
+ private final int mFamily; // TODO: what about IPV6_ADDRFORM?
- EncapSocketRecord(int resourceId, FileDescriptor socket, int port) {
+ EncapSocketRecord(int resourceId, FileDescriptor socket, int port, int family) {
super(resourceId);
mSocket = socket;
mPort = port;
+ mFamily = family;
}
/** always guarded by IpSecService#this */
@@ -1038,6 +1045,10 @@
return mSocket;
}
+ public int getFamily() {
+ return mFamily;
+ }
+
@Override
protected ResourceTracker getResourceTracker() {
return getUserRecord().mSocketQuotaTracker;
@@ -1210,15 +1221,16 @@
* and re-binding, during which the system could *technically* hand that port out to someone
* else.
*/
- private int bindToRandomPort(FileDescriptor sockFd) throws IOException {
+ private int bindToRandomPort(FileDescriptor sockFd, int family, InetAddress localAddr)
+ throws IOException {
for (int i = MAX_PORT_BIND_ATTEMPTS; i > 0; i--) {
try {
- FileDescriptor probeSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- Os.bind(probeSocket, INADDR_ANY, 0);
+ FileDescriptor probeSocket = Os.socket(family, SOCK_DGRAM, IPPROTO_UDP);
+ Os.bind(probeSocket, localAddr, 0);
int port = ((InetSocketAddress) Os.getsockname(probeSocket)).getPort();
Os.close(probeSocket);
Log.v(TAG, "Binding to port " + port);
- Os.bind(sockFd, INADDR_ANY, port);
+ Os.bind(sockFd, localAddr, port);
return port;
} catch (ErrnoException e) {
// Someone miraculously claimed the port just after we closed probeSocket.
@@ -1260,6 +1272,19 @@
@Override
public synchronized IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, IBinder binder)
throws RemoteException {
+ // Experimental support for IPv6 UDP encap.
+ final int family;
+ final InetAddress localAddr;
+ if (SdkLevel.isAtLeastU() && port >= 65536) {
+ PermissionUtils.enforceNetworkStackPermissionOr(mContext, NETWORK_SETTINGS);
+ port -= 65536;
+ family = AF_INET6;
+ localAddr = IN6ADDR_ANY;
+ } else {
+ family = AF_INET;
+ localAddr = INADDR_ANY;
+ }
+
if (port != 0 && (port < FREE_PORT_MIN || port > PORT_MAX)) {
throw new IllegalArgumentException(
"Specified port number must be a valid non-reserved UDP port");
@@ -1278,7 +1303,7 @@
FileDescriptor sockFd = null;
try {
- sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ sockFd = Os.socket(family, SOCK_DGRAM, IPPROTO_UDP);
pFd = ParcelFileDescriptor.dup(sockFd);
} finally {
IoUtils.closeQuietly(sockFd);
@@ -1295,15 +1320,16 @@
mNetd.ipSecSetEncapSocketOwner(pFd, callingUid);
if (port != 0) {
Log.v(TAG, "Binding to port " + port);
- Os.bind(pFd.getFileDescriptor(), INADDR_ANY, port);
+ Os.bind(pFd.getFileDescriptor(), localAddr, port);
} else {
- port = bindToRandomPort(pFd.getFileDescriptor());
+ port = bindToRandomPort(pFd.getFileDescriptor(), family, localAddr);
}
userRecord.mEncapSocketRecords.put(
resourceId,
new RefcountedResource<EncapSocketRecord>(
- new EncapSocketRecord(resourceId, pFd.getFileDescriptor(), port),
+ new EncapSocketRecord(resourceId, pFd.getFileDescriptor(), port,
+ family),
binder));
return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port,
pFd.getFileDescriptor());
@@ -1580,6 +1606,7 @@
*/
private void checkIpSecConfig(IpSecConfig config) {
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
+ EncapSocketRecord encapSocketRecord = null;
switch (config.getEncapType()) {
case IpSecTransform.ENCAP_NONE:
@@ -1587,7 +1614,7 @@
case IpSecTransform.ENCAP_ESPINUDP:
case IpSecTransform.ENCAP_ESPINUDP_NON_IKE:
// Retrieve encap socket record; will throw IllegalArgumentException if not found
- userRecord.mEncapSocketRecords.getResourceOrThrow(
+ encapSocketRecord = userRecord.mEncapSocketRecords.getResourceOrThrow(
config.getEncapSocketResourceId());
int port = config.getEncapRemotePort();
@@ -1641,10 +1668,9 @@
+ ") have different address families.");
}
- // Throw an error if UDP Encapsulation is not used in IPv4.
- if (config.getEncapType() != IpSecTransform.ENCAP_NONE && sourceFamily != AF_INET) {
+ if (encapSocketRecord != null && encapSocketRecord.getFamily() != destinationFamily) {
throw new IllegalArgumentException(
- "UDP Encapsulation is not supported for this address family");
+ "UDP encapsulation socket and destination address families must match");
}
switch (config.getMode()) {
diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java
index 5dcf860..c5104d8 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -20,6 +20,9 @@
import static android.net.nsd.NsdManager.MDNS_DISCOVERY_MANAGER_EVENT;
import static android.net.nsd.NsdManager.MDNS_SERVICE_EVENT;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
+import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
+
+import static com.android.modules.utils.build.SdkLevel.isAtLeastU;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -50,9 +53,7 @@
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
-import android.util.Pair;
import android.util.SparseArray;
-import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.State;
@@ -71,6 +72,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
@@ -80,10 +82,10 @@
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -111,6 +113,34 @@
*/
private static final String MDNS_ADVERTISER_VERSION = "mdns_advertiser_version";
+ /**
+ * Comma-separated list of type:flag mappings indicating the flags to use to allowlist
+ * discovery/advertising using MdnsDiscoveryManager / MdnsAdvertiser for a given type.
+ *
+ * For example _mytype._tcp.local and _othertype._tcp.local would be configured with:
+ * _mytype._tcp:mytype,_othertype._tcp.local:othertype
+ *
+ * In which case the flags:
+ * "mdns_discovery_manager_allowlist_mytype_version",
+ * "mdns_advertiser_allowlist_mytype_version",
+ * "mdns_discovery_manager_allowlist_othertype_version",
+ * "mdns_advertiser_allowlist_othertype_version"
+ * would be used to toggle MdnsDiscoveryManager / MdnsAdvertiser for each type. The flags will
+ * be read with
+ * {@link DeviceConfigUtils#isFeatureEnabled(Context, String, String, String, boolean)}.
+ *
+ * @see #MDNS_DISCOVERY_MANAGER_ALLOWLIST_FLAG_PREFIX
+ * @see #MDNS_ADVERTISER_ALLOWLIST_FLAG_PREFIX
+ * @see #MDNS_ALLOWLIST_FLAG_SUFFIX
+ */
+ private static final String MDNS_TYPE_ALLOWLIST_FLAGS = "mdns_type_allowlist_flags";
+
+ private static final String MDNS_DISCOVERY_MANAGER_ALLOWLIST_FLAG_PREFIX =
+ "mdns_discovery_manager_allowlist_";
+ private static final String MDNS_ADVERTISER_ALLOWLIST_FLAG_PREFIX =
+ "mdns_advertiser_allowlist_";
+ private static final String MDNS_ALLOWLIST_FLAG_SUFFIX = "_version";
+
public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
private static final long CLEANUP_DELAY_MS = 10000;
private static final int IFACE_IDX_ANY = 0;
@@ -119,13 +149,15 @@
private final NsdStateMachine mNsdStateMachine;
private final MDnsManager mMDnsManager;
private final MDnsEventCallback mMDnsEventCallback;
- @Nullable
+ @NonNull
+ private final Dependencies mDeps;
+ @NonNull
private final MdnsMultinetworkSocketClient mMdnsSocketClient;
- @Nullable
+ @NonNull
private final MdnsDiscoveryManager mMdnsDiscoveryManager;
- @Nullable
+ @NonNull
private final MdnsSocketProvider mMdnsSocketProvider;
- @Nullable
+ @NonNull
private final MdnsAdvertiser mAdvertiser;
// WARNING : Accessing these values in any thread is not safe, it must only be changed in the
// state machine thread. If change this outside state machine, it will need to introduce
@@ -234,6 +266,35 @@
}
}
+ private class ServiceInfoListener extends MdnsListener {
+
+ ServiceInfoListener(int clientId, int transactionId, @NonNull NsdServiceInfo reqServiceInfo,
+ @NonNull String listenServiceType) {
+ super(clientId, transactionId, reqServiceInfo, listenServiceType);
+ }
+
+ @Override
+ public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo) {
+ mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
+ NsdManager.SERVICE_UPDATED,
+ new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
+ }
+
+ @Override
+ public void onServiceUpdated(@NonNull MdnsServiceInfo serviceInfo) {
+ mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
+ NsdManager.SERVICE_UPDATED,
+ new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
+ }
+
+ @Override
+ public void onServiceRemoved(@NonNull MdnsServiceInfo serviceInfo) {
+ mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
+ NsdManager.SERVICE_UPDATED_LOST,
+ new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
+ }
+ }
+
/**
* Data class of mdns service callback information.
*/
@@ -312,19 +373,12 @@
mIsMonitoringSocketsStarted = true;
}
- private void maybeStopMonitoringSockets() {
- if (!mIsMonitoringSocketsStarted) {
- if (DBG) Log.d(TAG, "Socket monitoring has not been started.");
- return;
- }
- mMdnsSocketProvider.stopMonitoringSockets();
- mIsMonitoringSocketsStarted = false;
- }
-
private void maybeStopMonitoringSocketsIfNoActiveRequest() {
- if (!isAnyRequestActive()) {
- maybeStopMonitoringSockets();
- }
+ if (!mIsMonitoringSocketsStarted) return;
+ if (isAnyRequestActive()) return;
+
+ mMdnsSocketProvider.requestStopWhenInactive();
+ mIsMonitoringSocketsStarted = false;
}
NsdStateMachine(String name, Handler handler) {
@@ -343,13 +397,12 @@
final int clientId = msg.arg2;
switch (msg.what) {
case NsdManager.REGISTER_CLIENT:
- final Pair<NsdServiceConnector, INsdManagerCallback> arg =
- (Pair<NsdServiceConnector, INsdManagerCallback>) msg.obj;
- final INsdManagerCallback cb = arg.second;
+ final ConnectorArgs arg = (ConnectorArgs) msg.obj;
+ final INsdManagerCallback cb = arg.callback;
try {
- cb.asBinder().linkToDeath(arg.first, 0);
- cInfo = new ClientInfo(cb);
- mClients.put(arg.first, cInfo);
+ cb.asBinder().linkToDeath(arg.connector, 0);
+ cInfo = new ClientInfo(cb, arg.useJavaBackend);
+ mClients.put(arg.connector, cInfo);
} catch (RemoteException e) {
Log.w(TAG, "Client " + clientId + " has already died");
}
@@ -358,17 +411,12 @@
final NsdServiceConnector connector = (NsdServiceConnector) msg.obj;
cInfo = mClients.remove(connector);
if (cInfo != null) {
- if (mMdnsDiscoveryManager != null) {
- cInfo.unregisterAllListeners();
- }
cInfo.expungeAllRequests();
- if (cInfo.isLegacy()) {
+ if (cInfo.isPreSClient()) {
mLegacyClientCount -= 1;
}
}
- if (mMdnsDiscoveryManager != null || mAdvertiser != null) {
- maybeStopMonitoringSocketsIfNoActiveRequest();
- }
+ maybeStopMonitoringSocketsIfNoActiveRequest();
maybeScheduleStop();
break;
case NsdManager.DISCOVER_SERVICES:
@@ -429,7 +477,7 @@
cInfo = getClientInfoForReply(msg);
if (cInfo != null) {
cancelStop();
- cInfo.setLegacy();
+ cInfo.setPreSClient();
mLegacyClientCount += 1;
maybeStartDaemon();
}
@@ -461,72 +509,45 @@
}
private boolean requestLimitReached(ClientInfo clientInfo) {
- if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) {
+ if (clientInfo.mClientRequests.size() >= ClientInfo.MAX_LIMIT) {
if (DBG) Log.d(TAG, "Exceeded max outstanding requests " + clientInfo);
return true;
}
return false;
}
- private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo, int what) {
- clientInfo.mClientIds.put(clientId, globalId);
- clientInfo.mClientRequests.put(clientId, what);
+ private void storeLegacyRequestMap(int clientId, int globalId, ClientInfo clientInfo,
+ int what) {
+ clientInfo.mClientRequests.put(clientId, new LegacyClientRequest(globalId, what));
mIdToClientInfoMap.put(globalId, clientInfo);
// Remove the cleanup event because here comes a new request.
cancelStop();
}
- private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
- clientInfo.mClientIds.delete(clientId);
- clientInfo.mClientRequests.delete(clientId);
- mIdToClientInfoMap.remove(globalId);
- maybeScheduleStop();
- maybeStopMonitoringSocketsIfNoActiveRequest();
- }
-
- private void storeListenerMap(int clientId, int transactionId, MdnsListener listener,
+ private void storeAdvertiserRequestMap(int clientId, int globalId,
ClientInfo clientInfo) {
- clientInfo.mClientIds.put(clientId, transactionId);
- clientInfo.mListeners.put(clientId, listener);
- mIdToClientInfoMap.put(transactionId, clientInfo);
+ clientInfo.mClientRequests.put(clientId, new AdvertiserClientRequest(globalId));
+ mIdToClientInfoMap.put(globalId, clientInfo);
}
- private void removeListenerMap(int clientId, int transactionId, ClientInfo clientInfo) {
- clientInfo.mClientIds.delete(clientId);
- clientInfo.mListeners.delete(clientId);
- mIdToClientInfoMap.remove(transactionId);
- maybeStopMonitoringSocketsIfNoActiveRequest();
+ private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
+ final ClientRequest existing = clientInfo.mClientRequests.get(clientId);
+ if (existing == null) return;
+ clientInfo.mClientRequests.remove(clientId);
+ mIdToClientInfoMap.remove(globalId);
+
+ if (existing instanceof LegacyClientRequest) {
+ maybeScheduleStop();
+ } else {
+ maybeStopMonitoringSocketsIfNoActiveRequest();
+ }
}
- private void clearRegisteredServiceInfo(ClientInfo clientInfo) {
- clientInfo.mRegisteredService = null;
- clientInfo.mClientIdForServiceUpdates = 0;
- }
-
- /**
- * Check the given service type is valid and construct it to a service type
- * which can use for discovery / resolution service.
- *
- * <p> The valid service type should be 2 labels, or 3 labels if the query is for a
- * subtype (see RFC6763 7.1). Each label is up to 63 characters and must start with an
- * underscore; they are alphanumerical characters or dashes or underscore, except the
- * last one that is just alphanumerical. The last label must be _tcp or _udp.
- *
- * @param serviceType the request service type for discovery / resolution service
- * @return constructed service type or null if the given service type is invalid.
- */
- @Nullable
- private String constructServiceType(String serviceType) {
- if (TextUtils.isEmpty(serviceType)) return null;
-
- final Pattern serviceTypePattern = Pattern.compile(
- "^(_[a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]\\.)?"
- + "(_[a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]\\._(?:tcp|udp))$");
- final Matcher matcher = serviceTypePattern.matcher(serviceType);
- if (!matcher.matches()) return null;
- return matcher.group(1) == null
- ? serviceType
- : matcher.group(1) + "_sub." + matcher.group(2);
+ private void storeDiscoveryManagerRequestMap(int clientId, int globalId,
+ MdnsListener listener, ClientInfo clientInfo) {
+ clientInfo.mClientRequests.put(clientId,
+ new DiscoveryManagerRequest(globalId, listener));
+ mIdToClientInfoMap.put(globalId, clientInfo);
}
/**
@@ -552,6 +573,12 @@
return new String(out.array(), 0, out.position(), utf8);
}
+ private void stopDiscoveryManagerRequest(ClientRequest request, int clientId, int id,
+ ClientInfo clientInfo) {
+ clientInfo.unregisterMdnsListenerFromRequest(request);
+ removeRequestMap(clientId, id, clientInfo);
+ }
+
@Override
public boolean processMessage(Message msg) {
final ClientInfo clientInfo;
@@ -579,8 +606,10 @@
final NsdServiceInfo info = args.serviceInfo;
id = getUniqueId();
- if (mMdnsDiscoveryManager != null) {
- final String serviceType = constructServiceType(info.getServiceType());
+ final String serviceType = constructServiceType(info.getServiceType());
+ if (clientInfo.mUseJavaBackend
+ || mDeps.isMdnsDiscoveryManagerEnabled(mContext)
+ || useDiscoveryManagerForType(serviceType)) {
if (serviceType == null) {
clientInfo.onDiscoverServicesFailed(clientId,
NsdManager.FAILURE_INTERNAL_ERROR);
@@ -597,7 +626,7 @@
.build();
mMdnsDiscoveryManager.registerListener(
listenServiceType, listener, options);
- storeListenerMap(clientId, id, listener, clientInfo);
+ storeDiscoveryManagerRequestMap(clientId, id, listener, clientInfo);
clientInfo.onDiscoverServicesStarted(clientId, info);
} else {
maybeStartDaemon();
@@ -606,7 +635,7 @@
Log.d(TAG, "Discover " + msg.arg2 + " " + id
+ info.getServiceType());
}
- storeRequestMap(clientId, id, clientInfo, msg.what);
+ storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
clientInfo.onDiscoverServicesStarted(clientId, info);
} else {
stopServiceDiscovery(id);
@@ -616,7 +645,7 @@
}
break;
}
- case NsdManager.STOP_DISCOVERY:
+ case NsdManager.STOP_DISCOVERY: {
if (DBG) Log.d(TAG, "Stop service discovery");
args = (ListenerArgs) msg.obj;
clientInfo = mClients.get(args.connector);
@@ -628,23 +657,17 @@
break;
}
- try {
- id = clientInfo.mClientIds.get(clientId);
- } catch (NullPointerException e) {
- clientInfo.onStopDiscoveryFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+ final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+ if (request == null) {
+ Log.e(TAG, "Unknown client request in STOP_DISCOVERY");
break;
}
- if (mMdnsDiscoveryManager != null) {
- final MdnsListener listener = clientInfo.mListeners.get(clientId);
- if (listener == null) {
- clientInfo.onStopDiscoveryFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- break;
- }
- mMdnsDiscoveryManager.unregisterListener(
- listener.getListenedServiceType(), listener);
- removeListenerMap(clientId, id, clientInfo);
+ id = request.mGlobalId;
+ // Note isMdnsDiscoveryManagerEnabled may have changed to false at this
+ // point, so this needs to check the type of the original request to
+ // unregister instead of looking at the flag value.
+ if (request instanceof DiscoveryManagerRequest) {
+ stopDiscoveryManagerRequest(request, clientId, id, clientInfo);
clientInfo.onStopDiscoverySucceeded(clientId);
} else {
removeRequestMap(clientId, id, clientInfo);
@@ -656,7 +679,8 @@
}
}
break;
- case NsdManager.REGISTER_SERVICE:
+ }
+ case NsdManager.REGISTER_SERVICE: {
if (DBG) Log.d(TAG, "Register service");
args = (ListenerArgs) msg.obj;
clientInfo = mClients.get(args.connector);
@@ -675,10 +699,12 @@
}
id = getUniqueId();
- if (mAdvertiser != null) {
- final NsdServiceInfo serviceInfo = args.serviceInfo;
- final String serviceType = serviceInfo.getServiceType();
- final String registerServiceType = constructServiceType(serviceType);
+ final NsdServiceInfo serviceInfo = args.serviceInfo;
+ final String serviceType = serviceInfo.getServiceType();
+ final String registerServiceType = constructServiceType(serviceType);
+ if (clientInfo.mUseJavaBackend
+ || mDeps.isMdnsAdvertiserEnabled(mContext)
+ || useAdvertiserForType(registerServiceType)) {
if (registerServiceType == null) {
Log.e(TAG, "Invalid service type: " + serviceType);
clientInfo.onRegisterServiceFailed(clientId,
@@ -691,12 +717,12 @@
maybeStartMonitoringSockets();
mAdvertiser.addService(id, serviceInfo);
- storeRequestMap(clientId, id, clientInfo, msg.what);
+ storeAdvertiserRequestMap(clientId, id, clientInfo);
} else {
maybeStartDaemon();
- if (registerService(id, args.serviceInfo)) {
+ if (registerService(id, serviceInfo)) {
if (DBG) Log.d(TAG, "Register " + clientId + " " + id);
- storeRequestMap(clientId, id, clientInfo, msg.what);
+ storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
// Return success after mDns reports success
} else {
unregisterService(id);
@@ -706,7 +732,8 @@
}
break;
- case NsdManager.UNREGISTER_SERVICE:
+ }
+ case NsdManager.UNREGISTER_SERVICE: {
if (DBG) Log.d(TAG, "unregister service");
args = (ListenerArgs) msg.obj;
clientInfo = mClients.get(args.connector);
@@ -717,10 +744,18 @@
Log.e(TAG, "Unknown connector in unregistration");
break;
}
- id = clientInfo.mClientIds.get(clientId);
+ final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+ if (request == null) {
+ Log.e(TAG, "Unknown client request in UNREGISTER_SERVICE");
+ break;
+ }
+ id = request.mGlobalId;
removeRequestMap(clientId, id, clientInfo);
- if (mAdvertiser != null) {
+ // Note isMdnsAdvertiserEnabled may have changed to false at this point,
+ // so this needs to check the type of the original request to unregister
+ // instead of looking at the flag value.
+ if (request instanceof AdvertiserClientRequest) {
mAdvertiser.removeService(id);
clientInfo.onUnregisterServiceSucceeded(clientId);
} else {
@@ -732,6 +767,7 @@
}
}
break;
+ }
case NsdManager.RESOLVE_SERVICE: {
if (DBG) Log.d(TAG, "Resolve service");
args = (ListenerArgs) msg.obj;
@@ -746,8 +782,10 @@
final NsdServiceInfo info = args.serviceInfo;
id = getUniqueId();
- if (mMdnsDiscoveryManager != null) {
- final String serviceType = constructServiceType(info.getServiceType());
+ final String serviceType = constructServiceType(info.getServiceType());
+ if (clientInfo.mUseJavaBackend
+ || mDeps.isMdnsDiscoveryManagerEnabled(mContext)
+ || useDiscoveryManagerForType(serviceType)) {
if (serviceType == null) {
clientInfo.onResolveServiceFailed(clientId,
NsdManager.FAILURE_INTERNAL_ERROR);
@@ -761,10 +799,11 @@
final MdnsSearchOptions options = MdnsSearchOptions.newBuilder()
.setNetwork(info.getNetwork())
.setIsPassiveMode(true)
+ .setResolveInstanceName(info.getServiceName())
.build();
mMdnsDiscoveryManager.registerListener(
resolveServiceType, listener, options);
- storeListenerMap(clientId, id, listener, clientInfo);
+ storeDiscoveryManagerRequestMap(clientId, id, listener, clientInfo);
} else {
if (clientInfo.mResolvedService != null) {
clientInfo.onResolveServiceFailed(
@@ -773,9 +812,9 @@
}
maybeStartDaemon();
- if (resolveService(id, args.serviceInfo)) {
+ if (resolveService(id, info)) {
clientInfo.mResolvedService = new NsdServiceInfo();
- storeRequestMap(clientId, id, clientInfo, msg.what);
+ storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
} else {
clientInfo.onResolveServiceFailed(
clientId, NsdManager.FAILURE_INTERNAL_ERROR);
@@ -783,7 +822,7 @@
}
break;
}
- case NsdManager.STOP_RESOLUTION:
+ case NsdManager.STOP_RESOLUTION: {
if (DBG) Log.d(TAG, "Stop service resolution");
args = (ListenerArgs) msg.obj;
clientInfo = mClients.get(args.connector);
@@ -795,18 +834,31 @@
break;
}
- id = clientInfo.mClientIds.get(clientId);
- removeRequestMap(clientId, id, clientInfo);
- if (stopResolveService(id)) {
+ final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+ if (request == null) {
+ Log.e(TAG, "Unknown client request in STOP_RESOLUTION");
+ break;
+ }
+ id = request.mGlobalId;
+ // Note isMdnsDiscoveryManagerEnabled may have changed to false at this
+ // point, so this needs to check the type of the original request to
+ // unregister instead of looking at the flag value.
+ if (request instanceof DiscoveryManagerRequest) {
+ stopDiscoveryManagerRequest(request, clientId, id, clientInfo);
clientInfo.onStopResolutionSucceeded(clientId);
} else {
- clientInfo.onStopResolutionFailed(
- clientId, NsdManager.FAILURE_OPERATION_NOT_RUNNING);
+ removeRequestMap(clientId, id, clientInfo);
+ if (stopResolveService(id)) {
+ clientInfo.onStopResolutionSucceeded(clientId);
+ } else {
+ clientInfo.onStopResolutionFailed(
+ clientId, NsdManager.FAILURE_OPERATION_NOT_RUNNING);
+ }
+ clientInfo.mResolvedService = null;
}
- clientInfo.mResolvedService = null;
- // TODO: Implement the stop resolution with MdnsDiscoveryManager.
break;
- case NsdManager.REGISTER_SERVICE_CALLBACK:
+ }
+ case NsdManager.REGISTER_SERVICE_CALLBACK: {
if (DBG) Log.d(TAG, "Register a service callback");
args = (ListenerArgs) msg.obj;
clientInfo = mClients.get(args.connector);
@@ -818,24 +870,30 @@
break;
}
- if (clientInfo.mRegisteredService != null) {
- clientInfo.onServiceInfoCallbackRegistrationFailed(
- clientId, NsdManager.FAILURE_ALREADY_ACTIVE);
+ final NsdServiceInfo info = args.serviceInfo;
+ id = getUniqueId();
+ final String serviceType = constructServiceType(info.getServiceType());
+ if (serviceType == null) {
+ clientInfo.onServiceInfoCallbackRegistrationFailed(clientId,
+ NsdManager.FAILURE_BAD_PARAMETERS);
break;
}
+ final String resolveServiceType = serviceType + ".local";
- maybeStartDaemon();
- id = getUniqueId();
- if (resolveService(id, args.serviceInfo)) {
- clientInfo.mRegisteredService = new NsdServiceInfo();
- clientInfo.mClientIdForServiceUpdates = clientId;
- storeRequestMap(clientId, id, clientInfo, msg.what);
- } else {
- clientInfo.onServiceInfoCallbackRegistrationFailed(
- clientId, NsdManager.FAILURE_BAD_PARAMETERS);
- }
+ maybeStartMonitoringSockets();
+ final MdnsListener listener =
+ new ServiceInfoListener(clientId, id, info, resolveServiceType);
+ final MdnsSearchOptions options = MdnsSearchOptions.newBuilder()
+ .setNetwork(info.getNetwork())
+ .setIsPassiveMode(true)
+ .setResolveInstanceName(info.getServiceName())
+ .build();
+ mMdnsDiscoveryManager.registerListener(
+ resolveServiceType, listener, options);
+ storeDiscoveryManagerRequestMap(clientId, id, listener, clientInfo);
break;
- case NsdManager.UNREGISTER_SERVICE_CALLBACK:
+ }
+ case NsdManager.UNREGISTER_SERVICE_CALLBACK: {
if (DBG) Log.d(TAG, "Unregister a service callback");
args = (ListenerArgs) msg.obj;
clientInfo = mClients.get(args.connector);
@@ -847,15 +905,20 @@
break;
}
- id = clientInfo.mClientIds.get(clientId);
- removeRequestMap(clientId, id, clientInfo);
- if (stopResolveService(id)) {
+ final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+ if (request == null) {
+ Log.e(TAG, "Unknown client request in UNREGISTER_SERVICE_CALLBACK");
+ break;
+ }
+ id = request.mGlobalId;
+ if (request instanceof DiscoveryManagerRequest) {
+ stopDiscoveryManagerRequest(request, clientId, id, clientInfo);
clientInfo.onServiceInfoCallbackUnregistered(clientId);
} else {
- Log.e(TAG, "Failed to unregister service info callback");
+ loge("Unregister failed with non-DiscoveryManagerRequest.");
}
- clearRegisteredServiceInfo(clientInfo);
break;
+ }
case MDNS_SERVICE_EVENT:
if (!handleMDnsServiceEvent(msg.arg1, msg.arg2, msg.obj)) {
return NOT_HANDLED;
@@ -872,19 +935,6 @@
return HANDLED;
}
- private void notifyResolveFailedResult(boolean isListenedToUpdates, int clientId,
- ClientInfo clientInfo, int error) {
- if (isListenedToUpdates) {
- clientInfo.onServiceInfoCallbackRegistrationFailed(clientId, error);
- clearRegisteredServiceInfo(clientInfo);
- } else {
- // The resolve API always returned FAILURE_INTERNAL_ERROR on error; keep it
- // for backwards compatibility.
- clientInfo.onResolveServiceFailed(clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- clientInfo.mResolvedService = null;
- }
- }
-
private boolean handleMDnsServiceEvent(int code, int id, Object obj) {
NsdServiceInfo servInfo;
ClientInfo clientInfo = mIdToClientInfoMap.get(id);
@@ -941,8 +991,6 @@
// found services on the same interface index and their network at the time
setServiceNetworkForCallback(servInfo, lostNetId, info.interfaceIdx);
clientInfo.onServiceLost(clientId, servInfo);
- // TODO: also support registered service lost when not discovering
- clientInfo.maybeNotifyRegisteredServiceLost(servInfo);
break;
}
case IMDnsEventListener.SERVICE_DISCOVERY_FAILED:
@@ -979,11 +1027,7 @@
String rest = fullName.substring(index);
String type = rest.replace(".local.", "");
- final boolean isListenedToUpdates =
- clientId == clientInfo.mClientIdForServiceUpdates;
- final NsdServiceInfo serviceInfo = isListenedToUpdates
- ? clientInfo.mRegisteredService : clientInfo.mResolvedService;
-
+ final NsdServiceInfo serviceInfo = clientInfo.mResolvedService;
serviceInfo.setServiceName(name);
serviceInfo.setServiceType(type);
serviceInfo.setPort(info.port);
@@ -995,10 +1039,12 @@
final int id2 = getUniqueId();
if (getAddrInfo(id2, info.hostname, info.interfaceIdx)) {
- storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
+ storeLegacyRequestMap(clientId, id2, clientInfo,
+ NsdManager.RESOLVE_SERVICE);
} else {
- notifyResolveFailedResult(isListenedToUpdates, clientId, clientInfo,
- NsdManager.FAILURE_BAD_PARAMETERS);
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.mResolvedService = null;
}
break;
}
@@ -1006,17 +1052,17 @@
/* NNN resolveId errorCode */
stopResolveService(id);
removeRequestMap(clientId, id, clientInfo);
- notifyResolveFailedResult(
- clientId == clientInfo.mClientIdForServiceUpdates,
- clientId, clientInfo, NsdManager.FAILURE_BAD_PARAMETERS);
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.mResolvedService = null;
break;
case IMDnsEventListener.SERVICE_GET_ADDR_FAILED:
/* NNN resolveId errorCode */
stopGetAddrInfo(id);
removeRequestMap(clientId, id, clientInfo);
- notifyResolveFailedResult(
- clientId == clientInfo.mClientIdForServiceUpdates,
- clientId, clientInfo, NsdManager.FAILURE_BAD_PARAMETERS);
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+ clientInfo.mResolvedService = null;
break;
case IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS: {
/* NNN resolveId hostname ttl addr interfaceIdx netId */
@@ -1033,38 +1079,19 @@
// If the resolved service is on an interface without a network, consider it
// as a failure: it would not be usable by apps as they would need
// privileged permissions.
- if (clientId == clientInfo.mClientIdForServiceUpdates) {
- if (netId != NETID_UNSET && serviceHost != null) {
- setServiceNetworkForCallback(clientInfo.mRegisteredService,
- netId, info.interfaceIdx);
- final List<InetAddress> addresses =
- clientInfo.mRegisteredService.getHostAddresses();
- addresses.add(serviceHost);
- clientInfo.mRegisteredService.setHostAddresses(addresses);
- clientInfo.onServiceUpdated(
- clientId, clientInfo.mRegisteredService);
- } else {
- stopGetAddrInfo(id);
- removeRequestMap(clientId, id, clientInfo);
- clearRegisteredServiceInfo(clientInfo);
- clientInfo.onServiceInfoCallbackRegistrationFailed(
- clientId, NsdManager.FAILURE_BAD_PARAMETERS);
- }
+ if (netId != NETID_UNSET && serviceHost != null) {
+ clientInfo.mResolvedService.setHost(serviceHost);
+ setServiceNetworkForCallback(clientInfo.mResolvedService,
+ netId, info.interfaceIdx);
+ clientInfo.onResolveServiceSucceeded(
+ clientId, clientInfo.mResolvedService);
} else {
- if (netId != NETID_UNSET && serviceHost != null) {
- clientInfo.mResolvedService.setHost(serviceHost);
- setServiceNetworkForCallback(clientInfo.mResolvedService,
- netId, info.interfaceIdx);
- clientInfo.onResolveServiceSucceeded(
- clientId, clientInfo.mResolvedService);
- } else {
- clientInfo.onResolveServiceFailed(
- clientId, NsdManager.FAILURE_INTERNAL_ERROR);
- }
- stopGetAddrInfo(id);
- removeRequestMap(clientId, id, clientInfo);
- clientInfo.mResolvedService = null;
+ clientInfo.onResolveServiceFailed(
+ clientId, NsdManager.FAILURE_INTERNAL_ERROR);
}
+ stopGetAddrInfo(id);
+ removeRequestMap(clientId, id, clientInfo);
+ clientInfo.mResolvedService = null;
break;
}
default:
@@ -1079,9 +1106,12 @@
final String serviceName = serviceInfo.getServiceInstanceName();
final NsdServiceInfo servInfo = new NsdServiceInfo(serviceName, serviceType);
final Network network = serviceInfo.getNetwork();
+ // In MdnsDiscoveryManagerEvent, the Network can be null which means it is a
+ // network for Tethering interface. In other words, the network == null means the
+ // network has netId = INetd.LOCAL_NET_ID.
setServiceNetworkForCallback(
servInfo,
- network == null ? NETID_UNSET : network.netId,
+ network == null ? INetd.LOCAL_NET_ID : network.netId,
serviceInfo.getInterfaceIndex());
return servInfo;
}
@@ -1110,6 +1140,11 @@
clientInfo.onServiceLost(clientId, info);
break;
case NsdManager.RESOLVE_SERVICE_SUCCEEDED: {
+ final ClientRequest request = clientInfo.mClientRequests.get(clientId);
+ if (request == null) {
+ Log.e(TAG, "Unknown client request in RESOLVE_SERVICE_SUCCEEDED");
+ break;
+ }
final MdnsServiceInfo serviceInfo = event.mMdnsServiceInfo;
// Add '.' in front of the service type that aligns with historical behavior
info.setServiceType("." + event.mRequestedServiceType);
@@ -1124,28 +1159,46 @@
Log.e(TAG, "Invalid attribute", e);
}
}
- try {
- if (serviceInfo.getIpv4Address() != null) {
- info.setHost(InetAddresses.parseNumericAddress(
- serviceInfo.getIpv4Address()));
- } else {
- info.setHost(InetAddresses.parseNumericAddress(
- serviceInfo.getIpv6Address()));
- }
+ final List<InetAddress> addresses = getInetAddresses(serviceInfo);
+ if (addresses.size() != 0) {
+ info.setHostAddresses(addresses);
clientInfo.onResolveServiceSucceeded(clientId, info);
- } catch (IllegalArgumentException e) {
- Log.wtf(TAG, "Invalid address in RESOLVE_SERVICE_SUCCEEDED", e);
+ } else {
+ // No address. Notify resolution failure.
clientInfo.onResolveServiceFailed(
clientId, NsdManager.FAILURE_INTERNAL_ERROR);
}
// Unregister the listener immediately like IMDnsEventListener design
- final MdnsListener listener = clientInfo.mListeners.get(clientId);
- mMdnsDiscoveryManager.unregisterListener(
- listener.getListenedServiceType(), listener);
- removeListenerMap(clientId, transactionId, clientInfo);
+ if (!(request instanceof DiscoveryManagerRequest)) {
+ Log.wtf(TAG, "non-DiscoveryManager request in DiscoveryManager event");
+ break;
+ }
+ stopDiscoveryManagerRequest(request, clientId, transactionId, clientInfo);
break;
}
+ case NsdManager.SERVICE_UPDATED: {
+ final MdnsServiceInfo serviceInfo = event.mMdnsServiceInfo;
+ info.setPort(serviceInfo.getPort());
+
+ Map<String, String> attrs = serviceInfo.getAttributes();
+ for (Map.Entry<String, String> kv : attrs.entrySet()) {
+ final String key = kv.getKey();
+ try {
+ info.setAttribute(key, serviceInfo.getAttributeAsBytes(key));
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Invalid attribute", e);
+ }
+ }
+
+ final List<InetAddress> addresses = getInetAddresses(serviceInfo);
+ info.setHostAddresses(addresses);
+ clientInfo.onServiceUpdated(clientId, info);
+ break;
+ }
+ case NsdManager.SERVICE_UPDATED_LOST:
+ clientInfo.onServiceUpdatedLost(clientId);
+ break;
default:
return false;
}
@@ -1154,6 +1207,36 @@
}
}
+ @NonNull
+ private static List<InetAddress> getInetAddresses(@NonNull MdnsServiceInfo serviceInfo) {
+ final List<String> v4Addrs = serviceInfo.getIpv4Addresses();
+ final List<String> v6Addrs = serviceInfo.getIpv6Addresses();
+ final List<InetAddress> addresses = new ArrayList<>(v4Addrs.size() + v6Addrs.size());
+ for (String ipv4Address : v4Addrs) {
+ try {
+ addresses.add(InetAddresses.parseNumericAddress(ipv4Address));
+ } catch (IllegalArgumentException e) {
+ Log.wtf(TAG, "Invalid ipv4 address", e);
+ }
+ }
+ for (String ipv6Address : v6Addrs) {
+ try {
+ final InetAddress addr = InetAddresses.parseNumericAddress(ipv6Address);
+ if (addr.isLinkLocalAddress()) {
+ final Inet6Address v6Addr = Inet6Address.getByAddress(
+ null /* host */, addr.getAddress(),
+ serviceInfo.getInterfaceIndex());
+ addresses.add(v6Addr);
+ } else {
+ addresses.add(addr);
+ }
+ } catch (IllegalArgumentException | UnknownHostException e) {
+ Log.wtf(TAG, "Invalid ipv6 address", e);
+ }
+ }
+ return addresses;
+ }
+
private static void setServiceNetworkForCallback(NsdServiceInfo info, int netId, int ifaceIdx) {
switch (netId) {
case NETID_UNSET:
@@ -1203,6 +1286,34 @@
return sb.toString();
}
+ /**
+ * Check the given service type is valid and construct it to a service type
+ * which can use for discovery / resolution service.
+ *
+ * <p> The valid service type should be 2 labels, or 3 labels if the query is for a
+ * subtype (see RFC6763 7.1). Each label is up to 63 characters and must start with an
+ * underscore; they are alphanumerical characters or dashes or underscore, except the
+ * last one that is just alphanumerical. The last label must be _tcp or _udp.
+ *
+ * @param serviceType the request service type for discovery / resolution service
+ * @return constructed service type or null if the given service type is invalid.
+ */
+ @Nullable
+ public static String constructServiceType(String serviceType) {
+ if (TextUtils.isEmpty(serviceType)) return null;
+
+ final Pattern serviceTypePattern = Pattern.compile(
+ "^(_[a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]\\.)?"
+ + "(_[a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]\\._(?:tcp|udp))"
+ // Drop '.' at the end of service type that is compatible with old backend.
+ + "\\.?$");
+ final Matcher matcher = serviceTypePattern.matcher(serviceType);
+ if (!matcher.matches()) return null;
+ return matcher.group(1) == null
+ ? matcher.group(2)
+ : matcher.group(1) + "_sub." + matcher.group(2);
+ }
+
@VisibleForTesting
NsdService(Context ctx, Handler handler, long cleanupDelayMs) {
this(ctx, handler, cleanupDelayMs, new Dependencies());
@@ -1216,32 +1327,19 @@
mNsdStateMachine.start();
mMDnsManager = ctx.getSystemService(MDnsManager.class);
mMDnsEventCallback = new MDnsEventCallback(mNsdStateMachine);
+ mDeps = deps;
- final boolean discoveryManagerEnabled = deps.isMdnsDiscoveryManagerEnabled(ctx);
- final boolean advertiserEnabled = deps.isMdnsAdvertiserEnabled(ctx);
- if (discoveryManagerEnabled || advertiserEnabled) {
- mMdnsSocketProvider = deps.makeMdnsSocketProvider(ctx, handler.getLooper());
- } else {
- mMdnsSocketProvider = null;
- }
-
- if (discoveryManagerEnabled) {
- mMdnsSocketClient =
- new MdnsMultinetworkSocketClient(handler.getLooper(), mMdnsSocketProvider);
- mMdnsDiscoveryManager =
- deps.makeMdnsDiscoveryManager(new ExecutorProvider(), mMdnsSocketClient);
- handler.post(() -> mMdnsSocketClient.setCallback(mMdnsDiscoveryManager));
- } else {
- mMdnsSocketClient = null;
- mMdnsDiscoveryManager = null;
- }
-
- if (advertiserEnabled) {
- mAdvertiser = deps.makeMdnsAdvertiser(handler.getLooper(), mMdnsSocketProvider,
- new AdvertiserCallback());
- } else {
- mAdvertiser = null;
- }
+ mMdnsSocketProvider = deps.makeMdnsSocketProvider(ctx, handler.getLooper());
+ // Netlink monitor starts on boot, and intentionally never stopped, to ensure that all
+ // address events are received.
+ handler.post(mMdnsSocketProvider::startNetLinkMonitor);
+ mMdnsSocketClient =
+ new MdnsMultinetworkSocketClient(handler.getLooper(), mMdnsSocketProvider);
+ mMdnsDiscoveryManager =
+ deps.makeMdnsDiscoveryManager(new ExecutorProvider(), mMdnsSocketClient);
+ handler.post(() -> mMdnsSocketClient.setCallback(mMdnsDiscoveryManager));
+ mAdvertiser = deps.makeMdnsAdvertiser(handler.getLooper(), mMdnsSocketProvider,
+ new AdvertiserCallback());
}
/**
@@ -1256,8 +1354,9 @@
* @return true if the MdnsDiscoveryManager feature is enabled.
*/
public boolean isMdnsDiscoveryManagerEnabled(Context context) {
- return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY,
- MDNS_DISCOVERY_MANAGER_VERSION, false /* defaultEnabled */);
+ return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context,
+ NAMESPACE_CONNECTIVITY, MDNS_DISCOVERY_MANAGER_VERSION,
+ false /* defaultEnabled */);
}
/**
@@ -1267,8 +1366,26 @@
* @return true if the MdnsAdvertiser feature is enabled.
*/
public boolean isMdnsAdvertiserEnabled(Context context) {
- return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY,
- MDNS_ADVERTISER_VERSION, false /* defaultEnabled */);
+ return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context,
+ NAMESPACE_CONNECTIVITY, MDNS_ADVERTISER_VERSION, false /* defaultEnabled */);
+ }
+
+ /**
+ * Get the type allowlist flag value.
+ * @see #MDNS_TYPE_ALLOWLIST_FLAGS
+ */
+ @Nullable
+ public String getTypeAllowlistFlags() {
+ return DeviceConfigUtils.getDeviceConfigProperty(NAMESPACE_TETHERING,
+ MDNS_TYPE_ALLOWLIST_FLAGS, null);
+ }
+
+ /**
+ * @see DeviceConfigUtils#isFeatureEnabled(Context, String, String, String, boolean)
+ */
+ public boolean isFeatureEnabled(Context context, String feature) {
+ return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_TETHERING,
+ feature, DeviceConfigUtils.TETHERING_MODULE_NAME, false /* defaultEnabled */);
}
/**
@@ -1296,6 +1413,41 @@
}
}
+ /**
+ * Return whether a type is allowlisted to use the Java backend.
+ * @param type The service type
+ * @param flagPrefix One of {@link #MDNS_ADVERTISER_ALLOWLIST_FLAG_PREFIX} or
+ * {@link #MDNS_DISCOVERY_MANAGER_ALLOWLIST_FLAG_PREFIX}.
+ */
+ private boolean isTypeAllowlistedForJavaBackend(@Nullable String type,
+ @NonNull String flagPrefix) {
+ if (type == null) return false;
+ final String typesConfig = mDeps.getTypeAllowlistFlags();
+ if (TextUtils.isEmpty(typesConfig)) return false;
+
+ final String mappingPrefix = type + ":";
+ String mappedFlag = null;
+ for (String mapping : TextUtils.split(typesConfig, ",")) {
+ if (mapping.startsWith(mappingPrefix)) {
+ mappedFlag = mapping.substring(mappingPrefix.length());
+ break;
+ }
+ }
+
+ if (mappedFlag == null) return false;
+
+ return mDeps.isFeatureEnabled(mContext,
+ flagPrefix + mappedFlag + MDNS_ALLOWLIST_FLAG_SUFFIX);
+ }
+
+ private boolean useDiscoveryManagerForType(@Nullable String type) {
+ return isTypeAllowlistedForJavaBackend(type, MDNS_DISCOVERY_MANAGER_ALLOWLIST_FLAG_PREFIX);
+ }
+
+ private boolean useAdvertiserForType(@Nullable String type) {
+ return isTypeAllowlistedForJavaBackend(type, MDNS_ADVERTISER_ALLOWLIST_FLAG_PREFIX);
+ }
+
public static NsdService create(Context context) {
HandlerThread thread = new HandlerThread(TAG);
thread.start();
@@ -1389,12 +1541,27 @@
}
}
+ private static class ConnectorArgs {
+ @NonNull public final NsdServiceConnector connector;
+ @NonNull public final INsdManagerCallback callback;
+ public final boolean useJavaBackend;
+
+ ConnectorArgs(@NonNull NsdServiceConnector connector, @NonNull INsdManagerCallback callback,
+ boolean useJavaBackend) {
+ this.connector = connector;
+ this.callback = callback;
+ this.useJavaBackend = useJavaBackend;
+ }
+ }
+
@Override
- public INsdServiceConnector connect(INsdManagerCallback cb) {
+ public INsdServiceConnector connect(INsdManagerCallback cb, boolean useJavaBackend) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService");
+ if (DBG) Log.d(TAG, "New client connect. useJavaBackend=" + useJavaBackend);
final INsdServiceConnector connector = new NsdServiceConnector();
mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
- NsdManager.REGISTER_CLIENT, new Pair<>(connector, cb)));
+ NsdManager.REGISTER_CLIENT,
+ new ConnectorArgs((NsdServiceConnector) connector, cb, useJavaBackend)));
return connector;
}
@@ -1604,6 +1771,39 @@
mNsdStateMachine.dump(fd, pw, args);
}
+ private abstract static class ClientRequest {
+ private final int mGlobalId;
+
+ private ClientRequest(int globalId) {
+ mGlobalId = globalId;
+ }
+ }
+
+ private static class LegacyClientRequest extends ClientRequest {
+ private final int mRequestCode;
+
+ private LegacyClientRequest(int globalId, int requestCode) {
+ super(globalId);
+ mRequestCode = requestCode;
+ }
+ }
+
+ private static class AdvertiserClientRequest extends ClientRequest {
+ private AdvertiserClientRequest(int globalId) {
+ super(globalId);
+ }
+ }
+
+ private static class DiscoveryManagerRequest extends ClientRequest {
+ @NonNull
+ private final MdnsListener mListener;
+
+ private DiscoveryManagerRequest(int globalId, @NonNull MdnsListener listener) {
+ super(globalId);
+ mListener = listener;
+ }
+ }
+
/* Information tracked per client */
private class ClientInfo {
@@ -1612,25 +1812,17 @@
/* Remembers a resolved service until getaddrinfo completes */
private NsdServiceInfo mResolvedService;
- /* A map from client id to unique id sent to mDns */
- private final SparseIntArray mClientIds = new SparseIntArray();
-
- /* A map from client id to the type of the request we had received */
- private final SparseIntArray mClientRequests = new SparseIntArray();
-
- /* A map from client id to the MdnsListener */
- private final SparseArray<MdnsListener> mListeners = new SparseArray<>();
+ /* A map from client-side ID (listenerKey) to the request */
+ private final SparseArray<ClientRequest> mClientRequests = new SparseArray<>();
// The target SDK of this client < Build.VERSION_CODES.S
- private boolean mIsLegacy = false;
+ private boolean mIsPreSClient = false;
+ // The flag of using java backend if the client's target SDK >= U
+ private final boolean mUseJavaBackend;
- /*** The service that is registered to listen to its updates */
- private NsdServiceInfo mRegisteredService;
- /*** The client id that listen to updates */
- private int mClientIdForServiceUpdates;
-
- private ClientInfo(INsdManagerCallback cb) {
+ private ClientInfo(INsdManagerCallback cb, boolean useJavaBackend) {
mCb = cb;
+ mUseJavaBackend = useJavaBackend;
if (DBG) Log.d(TAG, "New client");
}
@@ -1638,38 +1830,63 @@
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("mResolvedService ").append(mResolvedService).append("\n");
- sb.append("mIsLegacy ").append(mIsLegacy).append("\n");
- for(int i = 0; i< mClientIds.size(); i++) {
- int clientID = mClientIds.keyAt(i);
- sb.append("clientId ").append(clientID).
- append(" mDnsId ").append(mClientIds.valueAt(i)).
- append(" type ").append(mClientRequests.get(clientID)).append("\n");
+ sb.append("mIsLegacy ").append(mIsPreSClient).append("\n");
+ for (int i = 0; i < mClientRequests.size(); i++) {
+ int clientID = mClientRequests.keyAt(i);
+ sb.append("clientId ")
+ .append(clientID)
+ .append(" mDnsId ").append(mClientRequests.valueAt(i).mGlobalId)
+ .append(" type ").append(
+ mClientRequests.valueAt(i).getClass().getSimpleName())
+ .append("\n");
}
return sb.toString();
}
- private boolean isLegacy() {
- return mIsLegacy;
+ private boolean isPreSClient() {
+ return mIsPreSClient;
}
- private void setLegacy() {
- mIsLegacy = true;
+ private void setPreSClient() {
+ mIsPreSClient = true;
+ }
+
+ private void unregisterMdnsListenerFromRequest(ClientRequest request) {
+ final MdnsListener listener =
+ ((DiscoveryManagerRequest) request).mListener;
+ mMdnsDiscoveryManager.unregisterListener(
+ listener.getListenedServiceType(), listener);
}
// Remove any pending requests from the global map when we get rid of a client,
// and send cancellations to the daemon.
private void expungeAllRequests() {
- int globalId, clientId, i;
// TODO: to keep handler responsive, do not clean all requests for that client at once.
- for (i = 0; i < mClientIds.size(); i++) {
- clientId = mClientIds.keyAt(i);
- globalId = mClientIds.valueAt(i);
+ for (int i = 0; i < mClientRequests.size(); i++) {
+ final int clientId = mClientRequests.keyAt(i);
+ final ClientRequest request = mClientRequests.valueAt(i);
+ final int globalId = request.mGlobalId;
mIdToClientInfoMap.remove(globalId);
if (DBG) {
Log.d(TAG, "Terminating client-ID " + clientId
+ " global-ID " + globalId + " type " + mClientRequests.get(clientId));
}
- switch (mClientRequests.get(clientId)) {
+
+ if (request instanceof DiscoveryManagerRequest) {
+ unregisterMdnsListenerFromRequest(request);
+ continue;
+ }
+
+ if (request instanceof AdvertiserClientRequest) {
+ mAdvertiser.removeService(globalId);
+ continue;
+ }
+
+ if (!(request instanceof LegacyClientRequest)) {
+ throw new IllegalStateException("Unknown request type: " + request.getClass());
+ }
+
+ switch (((LegacyClientRequest) request).mRequestCode) {
case NsdManager.DISCOVER_SERVICES:
stopServiceDiscovery(globalId);
break;
@@ -1677,49 +1894,25 @@
stopResolveService(globalId);
break;
case NsdManager.REGISTER_SERVICE:
- if (mAdvertiser != null) {
- mAdvertiser.removeService(globalId);
- } else {
- unregisterService(globalId);
- }
+ unregisterService(globalId);
break;
default:
break;
}
}
- mClientIds.clear();
mClientRequests.clear();
}
- void unregisterAllListeners() {
- for (int i = 0; i < mListeners.size(); i++) {
- final MdnsListener listener = mListeners.valueAt(i);
- mMdnsDiscoveryManager.unregisterListener(
- listener.getListenedServiceType(), listener);
- }
- mListeners.clear();
- }
-
- // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id,
- // return the corresponding listener id. mDnsClient id is also called a global id.
+ // mClientRequests is a sparse array of listener id -> ClientRequest. For a given
+ // mDnsClient id, return the corresponding listener id. mDnsClient id is also called a
+ // global id.
private int getClientId(final int globalId) {
- int idx = mClientIds.indexOfValue(globalId);
- if (idx < 0) {
- return idx;
+ for (int i = 0; i < mClientRequests.size(); i++) {
+ if (mClientRequests.valueAt(i).mGlobalId == globalId) {
+ return mClientRequests.keyAt(i);
+ }
}
- return mClientIds.keyAt(idx);
- }
-
- private void maybeNotifyRegisteredServiceLost(@NonNull NsdServiceInfo info) {
- if (mRegisteredService == null) return;
- if (!Objects.equals(mRegisteredService.getServiceName(), info.getServiceName())) return;
- // Resolved services have a leading dot appended at the beginning of their type, but in
- // discovered info it's at the end
- if (!Objects.equals(
- mRegisteredService.getServiceType() + ".", "." + info.getServiceType())) {
- return;
- }
- onServiceUpdatedLost(mClientIdForServiceUpdates);
+ return -1;
}
void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
diff --git a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
index fdd1478..9a67007 100644
--- a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
+++ b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
@@ -60,13 +60,21 @@
}
}
+ @NonNull
private final WeakReference<MdnsSocketClientBase> weakRequestSender;
+ @NonNull
private final MdnsPacketWriter packetWriter;
+ @NonNull
private final String[] serviceTypeLabels;
+ @NonNull
private final List<String> subtypes;
private final boolean expectUnicastResponse;
private final int transactionId;
+ @Nullable
private final Network network;
+ private final boolean sendDiscoveryQueries;
+ @NonNull
+ private final List<MdnsResponse> servicesToResolve;
EnqueueMdnsQueryCallable(
@NonNull MdnsSocketClientBase requestSender,
@@ -75,7 +83,9 @@
@NonNull Collection<String> subtypes,
boolean expectUnicastResponse,
int transactionId,
- @Nullable Network network) {
+ @Nullable Network network,
+ boolean sendDiscoveryQueries,
+ @NonNull Collection<MdnsResponse> servicesToResolve) {
weakRequestSender = new WeakReference<>(requestSender);
this.packetWriter = packetWriter;
serviceTypeLabels = TextUtils.split(serviceType, "\\.");
@@ -83,6 +93,8 @@
this.expectUnicastResponse = expectUnicastResponse;
this.transactionId = transactionId;
this.network = network;
+ this.sendDiscoveryQueries = sendDiscoveryQueries;
+ this.servicesToResolve = new ArrayList<>(servicesToResolve);
}
// Incompatible return type for override of Callable#call().
@@ -96,9 +108,44 @@
return null;
}
- int numQuestions = 1;
- if (!subtypes.isEmpty()) {
- numQuestions += subtypes.size();
+ int numQuestions = 0;
+
+ if (sendDiscoveryQueries) {
+ numQuestions++; // Base service type
+ if (!subtypes.isEmpty()) {
+ numQuestions += subtypes.size();
+ }
+ }
+
+ // List of (name, type) to query
+ final ArrayList<Pair<String[], Integer>> missingKnownAnswerRecords = new ArrayList<>();
+ for (MdnsResponse response : servicesToResolve) {
+ // TODO: also send queries to renew record TTL (as per RFC6762 7.1 no need to query
+ // if remaining TTL is more than half the original one, so send the queries if half
+ // the TTL has passed).
+ if (response.isComplete()) continue;
+ final String[] serviceName = response.getServiceName();
+ if (serviceName == null) continue;
+ if (!response.hasTextRecord()) {
+ missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_TXT));
+ }
+ if (!response.hasServiceRecord()) {
+ missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_SRV));
+ // The hostname is not yet known, so queries for address records will be sent
+ // the next time the EnqueueMdnsQueryCallable is enqueued if the reply does not
+ // contain them. In practice, advertisers should include the address records
+ // when queried for SRV, although it's not a MUST requirement (RFC6763 12.2).
+ } else if (!response.hasInet4AddressRecord() && !response.hasInet6AddressRecord()) {
+ final String[] host = response.getServiceRecord().getServiceHost();
+ missingKnownAnswerRecords.add(new Pair<>(host, MdnsRecord.TYPE_A));
+ missingKnownAnswerRecords.add(new Pair<>(host, MdnsRecord.TYPE_AAAA));
+ }
+ }
+ numQuestions += missingKnownAnswerRecords.size();
+
+ if (numQuestions == 0) {
+ // No query to send
+ return null;
}
// Header.
@@ -109,28 +156,25 @@
packetWriter.writeUInt16(0); // number of authority entries
packetWriter.writeUInt16(0); // number of additional records
- // Question(s). There will be one question for each (fqdn+subtype, recordType)
- // combination,
- // as well as one for each (fqdn, recordType) combination.
-
- for (String subtype : subtypes) {
- String[] labels = new String[serviceTypeLabels.length + 2];
- labels[0] = MdnsConstants.SUBTYPE_PREFIX + subtype;
- labels[1] = MdnsConstants.SUBTYPE_LABEL;
- System.arraycopy(serviceTypeLabels, 0, labels, 2, serviceTypeLabels.length);
-
- packetWriter.writeLabels(labels);
- packetWriter.writeUInt16(MdnsRecord.TYPE_PTR);
- packetWriter.writeUInt16(
- MdnsConstants.QCLASS_INTERNET
- | (expectUnicastResponse ? MdnsConstants.QCLASS_UNICAST : 0));
+ // Question(s) for missing records on known answers
+ for (Pair<String[], Integer> question : missingKnownAnswerRecords) {
+ writeQuestion(question.first, question.second);
}
- packetWriter.writeLabels(serviceTypeLabels);
- packetWriter.writeUInt16(MdnsRecord.TYPE_PTR);
- packetWriter.writeUInt16(
- MdnsConstants.QCLASS_INTERNET
- | (expectUnicastResponse ? MdnsConstants.QCLASS_UNICAST : 0));
+ // Question(s) for discovering other services with the type. There will be one question
+ // for each (fqdn+subtype, recordType) combination, as well as one for each (fqdn,
+ // recordType) combination.
+ if (sendDiscoveryQueries) {
+ for (String subtype : subtypes) {
+ String[] labels = new String[serviceTypeLabels.length + 2];
+ labels[0] = MdnsConstants.SUBTYPE_PREFIX + subtype;
+ labels[1] = MdnsConstants.SUBTYPE_LABEL;
+ System.arraycopy(serviceTypeLabels, 0, labels, 2, serviceTypeLabels.length);
+
+ writeQuestion(labels, MdnsRecord.TYPE_PTR);
+ }
+ writeQuestion(serviceTypeLabels, MdnsRecord.TYPE_PTR);
+ }
if (requestSender instanceof MdnsMultinetworkSocketClient) {
sendPacketToIpv4AndIpv6(requestSender, MdnsConstants.MDNS_PORT, network);
@@ -159,6 +203,14 @@
}
}
+ private void writeQuestion(String[] labels, int type) throws IOException {
+ packetWriter.writeLabels(labels);
+ packetWriter.writeUInt16(type);
+ packetWriter.writeUInt16(
+ MdnsConstants.QCLASS_INTERNET
+ | (expectUnicastResponse ? MdnsConstants.QCLASS_UNICAST : 0));
+ }
+
private void sendPacketTo(MdnsSocketClientBase requestSender, InetSocketAddress address)
throws IOException {
DatagramPacket packet = packetWriter.getPacket(address);
diff --git a/service-t/src/com/android/server/connectivity/mdns/ISocketNetLinkMonitor.java b/service-t/src/com/android/server/connectivity/mdns/ISocketNetLinkMonitor.java
new file mode 100644
index 0000000..ef3928c
--- /dev/null
+++ b/service-t/src/com/android/server/connectivity/mdns/ISocketNetLinkMonitor.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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.server.connectivity.mdns;
+
+/**
+ * The interface for netlink monitor.
+ */
+public interface ISocketNetLinkMonitor {
+
+ /**
+ * Returns if the netlink monitor is supported or not. By default, it is not supported.
+ */
+ default boolean isSupported() {
+ return false;
+ }
+
+ /**
+ * Starts the monitor.
+ */
+ default void startMonitoring() {
+ }
+
+ /**
+ * Stops the monitor.
+ */
+ default void stopMonitoring() {
+ }
+}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
index 977478a..ec3e997 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
@@ -31,6 +31,7 @@
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
@@ -43,6 +44,9 @@
private static final String TAG = MdnsAdvertiser.class.getSimpleName();
static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+ // Top-level domain for link-local queries, as per RFC6762 3.
+ private static final String LOCAL_TLD = "local";
+
private final Looper mLooper;
private final AdvertiserCallback mCb;
@@ -60,6 +64,8 @@
private final SparseArray<Registration> mRegistrations = new SparseArray<>();
private final Dependencies mDeps;
+ private String[] mDeviceHostName;
+
/**
* Dependencies for {@link MdnsAdvertiser}, useful for testing.
*/
@@ -71,11 +77,32 @@
public MdnsInterfaceAdvertiser makeAdvertiser(@NonNull MdnsInterfaceSocket socket,
@NonNull List<LinkAddress> initialAddresses,
@NonNull Looper looper, @NonNull byte[] packetCreationBuffer,
- @NonNull MdnsInterfaceAdvertiser.Callback cb) {
+ @NonNull MdnsInterfaceAdvertiser.Callback cb,
+ @NonNull String[] deviceHostName) {
// Note NetworkInterface is final and not mockable
final String logTag = socket.getInterface().getName();
return new MdnsInterfaceAdvertiser(logTag, socket, initialAddresses, looper,
- packetCreationBuffer, cb);
+ packetCreationBuffer, cb, deviceHostName);
+ }
+
+ /**
+ * Generates a unique hostname to be used by the device.
+ */
+ @NonNull
+ public String[] generateHostname() {
+ // Generate a very-probably-unique hostname. This allows minimizing possible conflicts
+ // to the point that probing for it is no longer necessary (as per RFC6762 8.1 last
+ // paragraph), and does not leak more information than what could already be obtained by
+ // looking at the mDNS packets source address.
+ // This differs from historical behavior that just used "Android.local" for many
+ // devices, creating a lot of conflicts.
+ // Having a different hostname per interface is an acceptable option as per RFC6762 14.
+ // This hostname will change every time the interface is reconnected, so this does not
+ // allow tracking the device.
+ // TODO: consider deriving a hostname from other sources, such as the IPv6 addresses
+ // (reusing the same privacy-protecting mechanics).
+ return new String[] {
+ "Android_" + UUID.randomUUID().toString().replace("-", ""), LOCAL_TLD };
}
}
@@ -260,7 +287,7 @@
MdnsInterfaceAdvertiser advertiser = mAllAdvertisers.get(socket);
if (advertiser == null) {
advertiser = mDeps.makeAdvertiser(socket, addresses, mLooper, mPacketCreationBuffer,
- mInterfaceAdvertiserCb);
+ mInterfaceAdvertiserCb, mDeviceHostName);
mAllAdvertisers.put(socket, advertiser);
advertiser.start();
}
@@ -389,6 +416,7 @@
mCb = cb;
mSocketProvider = socketProvider;
mDeps = deps;
+ mDeviceHostName = deps.generateHostname();
}
private void checkThread() {
@@ -453,6 +481,10 @@
advertiser.removeService(id);
}
mRegistrations.remove(id);
+ // Regenerates host name when registrations removed.
+ if (mRegistrations.size() == 0) {
+ mDeviceHostName = mDeps.generateHostname();
+ }
}
private static <K, V> boolean any(@NonNull ArrayMap<K, V> map,
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
index cc6b98b..fb8af8d 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
@@ -16,19 +16,25 @@
package com.android.server.connectivity.mdns;
+import static com.android.server.connectivity.mdns.MdnsSocketProvider.isNetworkMatched;
+
import android.Manifest.permission;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.net.Network;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Pair;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.connectivity.mdns.util.MdnsLogger;
import java.io.IOException;
-import java.util.Arrays;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
/**
* This class keeps tracking the set of registered {@link MdnsServiceBrowserListener} instances, and
@@ -42,12 +48,62 @@
private final ExecutorProvider executorProvider;
private final MdnsSocketClientBase socketClient;
- private final Map<String, MdnsServiceTypeClient> serviceTypeClients = new ArrayMap<>();
+ @GuardedBy("this")
+ @NonNull private final PerNetworkServiceTypeClients perNetworkServiceTypeClients;
+
+ private static class PerNetworkServiceTypeClients {
+ private final ArrayMap<Pair<String, Network>, MdnsServiceTypeClient> clients =
+ new ArrayMap<>();
+
+ public void put(@NonNull String serviceType, @Nullable Network network,
+ @NonNull MdnsServiceTypeClient client) {
+ final Pair<String, Network> perNetworkServiceType = new Pair<>(serviceType, network);
+ clients.put(perNetworkServiceType, client);
+ }
+
+ @Nullable
+ public MdnsServiceTypeClient get(@NonNull String serviceType, @Nullable Network network) {
+ final Pair<String, Network> perNetworkServiceType = new Pair<>(serviceType, network);
+ return clients.getOrDefault(perNetworkServiceType, null);
+ }
+
+ public List<MdnsServiceTypeClient> getByServiceType(@NonNull String serviceType) {
+ final List<MdnsServiceTypeClient> list = new ArrayList<>();
+ for (int i = 0; i < clients.size(); i++) {
+ final Pair<String, Network> perNetworkServiceType = clients.keyAt(i);
+ if (serviceType.equals(perNetworkServiceType.first)) {
+ list.add(clients.valueAt(i));
+ }
+ }
+ return list;
+ }
+
+ public List<MdnsServiceTypeClient> getByMatchingNetwork(@Nullable Network network) {
+ final List<MdnsServiceTypeClient> list = new ArrayList<>();
+ for (int i = 0; i < clients.size(); i++) {
+ final Pair<String, Network> perNetworkServiceType = clients.keyAt(i);
+ if (isNetworkMatched(network, perNetworkServiceType.second)) {
+ list.add(clients.valueAt(i));
+ }
+ }
+ return list;
+ }
+
+ public void remove(@NonNull MdnsServiceTypeClient client) {
+ final int index = clients.indexOfValue(client);
+ clients.removeAt(index);
+ }
+
+ public boolean isEmpty() {
+ return clients.isEmpty();
+ }
+ }
public MdnsDiscoveryManager(@NonNull ExecutorProvider executorProvider,
@NonNull MdnsSocketClientBase socketClient) {
this.executorProvider = executorProvider;
this.socketClient = socketClient;
+ perNetworkServiceTypeClients = new PerNetworkServiceTypeClients();
}
/**
@@ -67,7 +123,7 @@
LOGGER.log(
"Registering listener for subtypes: %s",
TextUtils.join(",", searchOptions.getSubtypes()));
- if (serviceTypeClients.isEmpty()) {
+ if (perNetworkServiceTypeClients.isEmpty()) {
// First listener. Starts the socket client.
try {
socketClient.startDiscovery();
@@ -77,16 +133,18 @@
}
}
// Request the network for discovery.
- socketClient.notifyNetworkRequested(listener, searchOptions.getNetwork());
-
- // All listeners of the same service types shares the same MdnsServiceTypeClient.
- MdnsServiceTypeClient serviceTypeClient = serviceTypeClients.get(serviceType);
- if (serviceTypeClient == null) {
- serviceTypeClient = createServiceTypeClient(serviceType);
- serviceTypeClients.put(serviceType, serviceTypeClient);
- }
- // TODO(b/264634275): Wait for a socket to be created before sending packets.
- serviceTypeClient.startSendAndReceive(listener, searchOptions);
+ socketClient.notifyNetworkRequested(listener, searchOptions.getNetwork(), network -> {
+ synchronized (this) {
+ // All listeners of the same service types shares the same MdnsServiceTypeClient.
+ MdnsServiceTypeClient serviceTypeClient =
+ perNetworkServiceTypeClients.get(serviceType, network);
+ if (serviceTypeClient == null) {
+ serviceTypeClient = createServiceTypeClient(serviceType, network);
+ perNetworkServiceTypeClients.put(serviceType, network, serviceTypeClient);
+ }
+ serviceTypeClient.startSendAndReceive(listener, searchOptions);
+ }
+ });
}
/**
@@ -101,17 +159,21 @@
@NonNull String serviceType, @NonNull MdnsServiceBrowserListener listener) {
LOGGER.log("Unregistering listener for service type: %s", serviceType);
if (DBG) Log.d(TAG, "Unregistering listener for serviceType:" + serviceType);
- MdnsServiceTypeClient serviceTypeClient = serviceTypeClients.get(serviceType);
- if (serviceTypeClient == null) {
+ final List<MdnsServiceTypeClient> serviceTypeClients =
+ perNetworkServiceTypeClients.getByServiceType(serviceType);
+ if (serviceTypeClients.isEmpty()) {
return;
}
- if (serviceTypeClient.stopSendAndReceive(listener)) {
- // No listener is registered for the service type anymore, remove it from the list of
- // the service type clients.
- serviceTypeClients.remove(serviceType);
- if (serviceTypeClients.isEmpty()) {
- // No discovery request. Stops the socket client.
- socketClient.stopDiscovery();
+ for (int i = 0; i < serviceTypeClients.size(); i++) {
+ final MdnsServiceTypeClient serviceTypeClient = serviceTypeClients.get(i);
+ if (serviceTypeClient.stopSendAndReceive(listener)) {
+ // No listener is registered for the service type anymore, remove it from the list
+ // of the service type clients.
+ perNetworkServiceTypeClients.remove(serviceTypeClient);
+ if (perNetworkServiceTypeClients.isEmpty()) {
+ // No discovery request. Stops the socket client.
+ socketClient.stopDiscovery();
+ }
}
}
// Unrequested the network.
@@ -119,36 +181,28 @@
}
@Override
- public synchronized void onResponseReceived(@NonNull MdnsResponse response) {
- String[] name =
- response.getPointerRecords().isEmpty()
- ? null
- : response.getPointerRecords().get(0).getName();
- if (name != null) {
- for (MdnsServiceTypeClient serviceTypeClient : serviceTypeClients.values()) {
- String[] serviceType = serviceTypeClient.getServiceTypeLabels();
- if ((Arrays.equals(name, serviceType)
- || ((name.length == (serviceType.length + 2))
- && name[1].equals(MdnsConstants.SUBTYPE_LABEL)
- && MdnsRecord.labelsAreSuffix(serviceType, name)))) {
- serviceTypeClient.processResponse(response);
- return;
- }
- }
+ public synchronized void onResponseReceived(@NonNull MdnsPacket packet,
+ int interfaceIndex, Network network) {
+ for (MdnsServiceTypeClient serviceTypeClient
+ : perNetworkServiceTypeClients.getByMatchingNetwork(network)) {
+ serviceTypeClient.processResponse(packet, interfaceIndex, network);
}
}
@Override
- public synchronized void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode) {
- for (MdnsServiceTypeClient serviceTypeClient : serviceTypeClients.values()) {
+ public synchronized void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode,
+ Network network) {
+ for (MdnsServiceTypeClient serviceTypeClient
+ : perNetworkServiceTypeClients.getByMatchingNetwork(network)) {
serviceTypeClient.onFailedToParseMdnsResponse(receivedPacketNumber, errorCode);
}
}
@VisibleForTesting
- MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType) {
+ MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType,
+ @Nullable Network network) {
return new MdnsServiceTypeClient(
serviceType, socketClient,
- executorProvider.newServiceTypeClientSchedulerExecutor());
+ executorProvider.newServiceTypeClientSchedulerExecutor(), network);
}
}
\ No newline at end of file
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
index c616e01..79cddce 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
@@ -141,8 +141,9 @@
public static class Dependencies {
/** @see MdnsRecordRepository */
@NonNull
- public MdnsRecordRepository makeRecordRepository(@NonNull Looper looper) {
- return new MdnsRecordRepository(looper);
+ public MdnsRecordRepository makeRecordRepository(@NonNull Looper looper,
+ @NonNull String[] deviceHostName) {
+ return new MdnsRecordRepository(looper, deviceHostName);
}
/** @see MdnsReplySender */
@@ -169,17 +170,18 @@
public MdnsInterfaceAdvertiser(@NonNull String logTag,
@NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> initialAddresses,
- @NonNull Looper looper, @NonNull byte[] packetCreationBuffer, @NonNull Callback cb) {
+ @NonNull Looper looper, @NonNull byte[] packetCreationBuffer, @NonNull Callback cb,
+ @NonNull String[] deviceHostName) {
this(logTag, socket, initialAddresses, looper, packetCreationBuffer, cb,
- new Dependencies());
+ new Dependencies(), deviceHostName);
}
public MdnsInterfaceAdvertiser(@NonNull String logTag,
@NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> initialAddresses,
@NonNull Looper looper, @NonNull byte[] packetCreationBuffer, @NonNull Callback cb,
- @NonNull Dependencies deps) {
+ @NonNull Dependencies deps, @NonNull String[] deviceHostName) {
mTag = MdnsInterfaceAdvertiser.class.getSimpleName() + "/" + logTag;
- mRecordRepository = deps.makeRecordRepository(looper);
+ mRecordRepository = deps.makeRecordRepository(looper, deviceHostName);
mRecordRepository.updateAddresses(initialAddresses);
mSocket = socket;
mCb = cb;
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java b/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
index 119c7a8..31627f8 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceSocket.java
@@ -78,7 +78,7 @@
}
mPacketReader = new MulticastPacketReader(networkInterface.getName(), mFileDescriptor,
- new Handler(looper), packetReadBuffer);
+ new Handler(looper), packetReadBuffer, port);
mPacketReader.start();
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
index d959065..7af2231 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
@@ -33,7 +33,6 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
-import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -48,7 +47,6 @@
@NonNull private final Handler mHandler;
@NonNull private final MdnsSocketProvider mSocketProvider;
- @NonNull private final MdnsResponseDecoder mResponseDecoder;
private final Map<MdnsServiceBrowserListener, InterfaceSocketCallback> mRequestedNetworks =
new ArrayMap<>();
@@ -62,13 +60,17 @@
@NonNull MdnsSocketProvider provider) {
mHandler = new Handler(looper);
mSocketProvider = provider;
- mResponseDecoder = new MdnsResponseDecoder(
- new MdnsResponseDecoder.Clock(), null /* serviceType */);
}
private class InterfaceSocketCallback implements MdnsSocketProvider.SocketCallback {
+ private final SocketCreationCallback mSocketCreationCallback;
+
+ InterfaceSocketCallback(SocketCreationCallback socketCreationCallback) {
+ mSocketCreationCallback = socketCreationCallback;
+ }
+
@Override
- public void onSocketCreated(@NonNull Network network,
+ public void onSocketCreated(@Nullable Network network,
@NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> addresses) {
// The socket may be already created by other request before, try to get the stored
// ReadPacketHandler.
@@ -80,10 +82,11 @@
}
socket.addPacketHandler(handler);
mActiveNetworkSockets.put(socket, network);
+ mSocketCreationCallback.onSocketCreated(network);
}
@Override
- public void onInterfaceDestroyed(@NonNull Network network,
+ public void onInterfaceDestroyed(@Nullable Network network,
@NonNull MdnsInterfaceSocket socket) {
mSocketPacketHandlers.remove(socket);
mActiveNetworkSockets.remove(socket);
@@ -118,10 +121,11 @@
* @param listener the listener for discovery.
* @param network the target network for discovery. Null means discovery on all possible
* interfaces.
+ * @param socketCreationCallback the callback to notify socket creation.
*/
@Override
public void notifyNetworkRequested(@NonNull MdnsServiceBrowserListener listener,
- @Nullable Network network) {
+ @Nullable Network network, @NonNull SocketCreationCallback socketCreationCallback) {
ensureRunningOnHandlerThread(mHandler);
InterfaceSocketCallback callback = mRequestedNetworks.get(listener);
if (callback != null) {
@@ -129,7 +133,7 @@
}
if (DBG) Log.d(TAG, "notifyNetworkRequested: network=" + network);
- callback = new InterfaceSocketCallback();
+ callback = new InterfaceSocketCallback(socketCreationCallback);
mRequestedNetworks.put(listener, callback);
mSocketProvider.requestSocket(network, callback);
}
@@ -170,19 +174,21 @@
@NonNull Network network) {
int packetNumber = ++mReceivedPacketNumber;
- final List<MdnsResponse> responses = new ArrayList<>();
- final int errorCode = mResponseDecoder.decode(
- recvbuf, length, responses, interfaceIndex, network);
- if (errorCode == MdnsResponseDecoder.SUCCESS) {
- for (MdnsResponse response : responses) {
+ final MdnsPacket response;
+ try {
+ response = MdnsResponseDecoder.parseResponse(recvbuf, length);
+ } catch (MdnsPacket.ParseException e) {
+ if (e.code != MdnsResponseErrorCode.ERROR_NOT_RESPONSE_MESSAGE) {
+ Log.e(TAG, e.getMessage(), e);
if (mCallback != null) {
- mCallback.onResponseReceived(response);
+ mCallback.onFailedToParseMdnsResponse(packetNumber, e.code, network);
}
}
- } else if (errorCode != MdnsResponseErrorCode.ERROR_NOT_RESPONSE_MESSAGE) {
- if (mCallback != null) {
- mCallback.onFailedToParseMdnsResponse(packetNumber, errorCode);
- }
+ return;
+ }
+
+ if (mCallback != null) {
+ mCallback.onResponseReceived(response, interfaceIndex, network);
}
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java b/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java
index e975ab4..1329172 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java
@@ -47,7 +47,6 @@
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
-import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
@@ -90,15 +89,16 @@
@NonNull
private final Looper mLooper;
@NonNull
- private String[] mDeviceHostname;
+ private final String[] mDeviceHostname;
- public MdnsRecordRepository(@NonNull Looper looper) {
- this(looper, new Dependencies());
+ public MdnsRecordRepository(@NonNull Looper looper, @NonNull String[] deviceHostname) {
+ this(looper, new Dependencies(), deviceHostname);
}
@VisibleForTesting
- public MdnsRecordRepository(@NonNull Looper looper, @NonNull Dependencies deps) {
- mDeviceHostname = deps.getHostname();
+ public MdnsRecordRepository(@NonNull Looper looper, @NonNull Dependencies deps,
+ @NonNull String[] deviceHostname) {
+ mDeviceHostname = deviceHostname;
mLooper = looper;
}
@@ -107,25 +107,6 @@
*/
@VisibleForTesting
public static class Dependencies {
- /**
- * Get a unique hostname to be used by the device.
- */
- @NonNull
- public String[] getHostname() {
- // Generate a very-probably-unique hostname. This allows minimizing possible conflicts
- // to the point that probing for it is no longer necessary (as per RFC6762 8.1 last
- // paragraph), and does not leak more information than what could already be obtained by
- // looking at the mDNS packets source address.
- // This differs from historical behavior that just used "Android.local" for many
- // devices, creating a lot of conflicts.
- // Having a different hostname per interface is an acceptable option as per RFC6762 14.
- // This hostname will change every time the interface is reconnected, so this does not
- // allow tracking the device.
- // TODO: consider deriving a hostname from other sources, such as the IPv6 addresses
- // (reusing the same privacy-protecting mechanics).
- return new String[] {
- "Android_" + UUID.randomUUID().toString().replace("-", ""), LOCAL_TLD };
- }
/**
* @see NetworkInterface#getInetAddresses().
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java b/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java
index 3a41978..e0100f6 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java
@@ -16,16 +16,20 @@
package com.android.server.connectivity.mdns;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.Network;
import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
/** An mDNS response. */
public class MdnsResponse {
@@ -33,42 +37,77 @@
private final List<MdnsPointerRecord> pointerRecords;
private MdnsServiceRecord serviceRecord;
private MdnsTextRecord textRecord;
- private MdnsInetAddressRecord inet4AddressRecord;
- private MdnsInetAddressRecord inet6AddressRecord;
+ @NonNull private List<MdnsInetAddressRecord> inet4AddressRecords;
+ @NonNull private List<MdnsInetAddressRecord> inet6AddressRecords;
private long lastUpdateTime;
private final int interfaceIndex;
@Nullable private final Network network;
+ @NonNull private final String[] serviceName;
/** Constructs a new, empty response. */
- public MdnsResponse(long now, int interfaceIndex, @Nullable Network network) {
+ public MdnsResponse(long now, @NonNull String[] serviceName, int interfaceIndex,
+ @Nullable Network network) {
lastUpdateTime = now;
records = new LinkedList<>();
pointerRecords = new LinkedList<>();
+ inet4AddressRecords = new ArrayList<>();
+ inet6AddressRecords = new ArrayList<>();
this.interfaceIndex = interfaceIndex;
this.network = network;
+ this.serviceName = serviceName;
}
- // This generic typed helper compares records for equality.
- // Returns True if records are the same.
- private <T> boolean recordsAreSame(T a, T b) {
- return ((a == null) && (b == null)) || ((a != null) && (b != null) && a.equals(b));
+ public MdnsResponse(@NonNull MdnsResponse base) {
+ records = new ArrayList<>(base.records);
+ pointerRecords = new ArrayList<>(base.pointerRecords);
+ serviceRecord = base.serviceRecord;
+ textRecord = base.textRecord;
+ inet4AddressRecords = new ArrayList<>(base.inet4AddressRecords);
+ inet6AddressRecords = new ArrayList<>(base.inet6AddressRecords);
+ lastUpdateTime = base.lastUpdateTime;
+ serviceName = base.serviceName;
+ interfaceIndex = base.interfaceIndex;
+ network = base.network;
+ }
+
+ /**
+ * Compare records for equality, including their TTL.
+ *
+ * MdnsRecord#equals ignores TTL and receiptTimeMillis, but methods in this class need to update
+ * records when the TTL changes (especially for goodbye announcements).
+ */
+ private boolean recordsAreSame(MdnsRecord a, MdnsRecord b) {
+ if (!Objects.equals(a, b)) return false;
+ return a == null || a.getTtl() == b.getTtl();
+ }
+
+ private <T extends MdnsRecord> boolean addOrReplaceRecord(@NonNull T record,
+ @NonNull List<T> recordsList) {
+ final int existing = recordsList.indexOf(record);
+ if (existing >= 0) {
+ if (recordsAreSame(record, recordsList.get(existing))) {
+ return false;
+ }
+ final MdnsRecord existedRecord = recordsList.remove(existing);
+ records.remove(existedRecord);
+ }
+ recordsList.add(record);
+ records.add(record);
+ return true;
}
/**
* Adds a pointer record.
*
* @return <code>true</code> if the record was added, or <code>false</code> if a matching
- * pointer
- * record is already present in the response.
+ * pointer record is already present in the response with the same TTL.
*/
public synchronized boolean addPointerRecord(MdnsPointerRecord pointerRecord) {
- if (!pointerRecords.contains(pointerRecord)) {
- pointerRecords.add(pointerRecord);
- records.add(pointerRecord);
- return true;
+ if (!Arrays.equals(serviceName, pointerRecord.getPointer())) {
+ throw new IllegalArgumentException(
+ "Pointer records for different service names cannot be added");
}
-
- return false;
+ return addOrReplaceRecord(pointerRecord, pointerRecords);
}
/** Gets the pointer records. */
@@ -170,45 +209,41 @@
return textRecord != null;
}
- /** Sets the IPv4 address record. */
- public synchronized boolean setInet4AddressRecord(
- @Nullable MdnsInetAddressRecord newInet4AddressRecord) {
- if (recordsAreSame(this.inet4AddressRecord, newInet4AddressRecord)) {
- return false;
- }
- if (this.inet4AddressRecord != null) {
- records.remove(this.inet4AddressRecord);
- }
- if (newInet4AddressRecord != null && newInet4AddressRecord.getInet4Address() != null) {
- this.inet4AddressRecord = newInet4AddressRecord;
- records.add(this.inet4AddressRecord);
- }
- return true;
+ /** Add the IPv4 address record. */
+ public synchronized boolean addInet4AddressRecord(
+ @NonNull MdnsInetAddressRecord newInet4AddressRecord) {
+ return addOrReplaceRecord(newInet4AddressRecord, inet4AddressRecords);
}
- /** Gets the IPv4 address record. */
+ /** Gets the IPv4 address records. */
+ @NonNull
+ public synchronized List<MdnsInetAddressRecord> getInet4AddressRecords() {
+ return Collections.unmodifiableList(inet4AddressRecords);
+ }
+
+ /** Return the first IPv4 address record or null if no record. */
+ @Nullable
public synchronized MdnsInetAddressRecord getInet4AddressRecord() {
- return inet4AddressRecord;
+ return inet4AddressRecords.isEmpty() ? null : inet4AddressRecords.get(0);
}
+ /** Check whether response has IPv4 address record */
public synchronized boolean hasInet4AddressRecord() {
- return inet4AddressRecord != null;
+ return !inet4AddressRecords.isEmpty();
}
- /** Sets the IPv6 address record. */
- public synchronized boolean setInet6AddressRecord(
- @Nullable MdnsInetAddressRecord newInet6AddressRecord) {
- if (recordsAreSame(this.inet6AddressRecord, newInet6AddressRecord)) {
- return false;
+ /** Clear all IPv4 address records */
+ synchronized void clearInet4AddressRecords() {
+ for (MdnsInetAddressRecord record : inet4AddressRecords) {
+ records.remove(record);
}
- if (this.inet6AddressRecord != null) {
- records.remove(this.inet6AddressRecord);
- }
- if (newInet6AddressRecord != null && newInet6AddressRecord.getInet6Address() != null) {
- this.inet6AddressRecord = newInet6AddressRecord;
- records.add(this.inet6AddressRecord);
- }
- return true;
+ inet4AddressRecords.clear();
+ }
+
+ /** Sets the IPv6 address records. */
+ public synchronized boolean addInet6AddressRecord(
+ @NonNull MdnsInetAddressRecord newInet6AddressRecord) {
+ return addOrReplaceRecord(newInet6AddressRecord, inet6AddressRecords);
}
/**
@@ -227,13 +262,28 @@
return network;
}
- /** Gets the IPv6 address record. */
- public synchronized MdnsInetAddressRecord getInet6AddressRecord() {
- return inet6AddressRecord;
+ /** Gets all IPv6 address records. */
+ public synchronized List<MdnsInetAddressRecord> getInet6AddressRecords() {
+ return Collections.unmodifiableList(inet6AddressRecords);
}
+ /** Return the first IPv6 address record or null if no record. */
+ @Nullable
+ public synchronized MdnsInetAddressRecord getInet6AddressRecord() {
+ return inet6AddressRecords.isEmpty() ? null : inet6AddressRecords.get(0);
+ }
+
+ /** Check whether response has IPv6 address record */
public synchronized boolean hasInet6AddressRecord() {
- return inet6AddressRecord != null;
+ return !inet6AddressRecords.isEmpty();
+ }
+
+ /** Clear all IPv6 address records */
+ synchronized void clearInet6AddressRecords() {
+ for (MdnsInetAddressRecord record : inet6AddressRecords) {
+ records.remove(record);
+ }
+ inet6AddressRecords.clear();
}
/** Gets all of the records. */
@@ -242,101 +292,58 @@
}
/**
- * Merges any records that are present in another response into this one.
+ * Drop address records if they are for a hostname that does not match the service record.
*
- * @return <code>true</code> if any records were added or updated.
+ * @return True if the records were dropped.
*/
- public synchronized boolean mergeRecordsFrom(MdnsResponse other) {
- lastUpdateTime = other.lastUpdateTime;
+ public synchronized boolean dropUnmatchedAddressRecords() {
+ if (this.serviceRecord == null) return false;
+ boolean dropAddressRecords = false;
- boolean updated = false;
-
- List<MdnsPointerRecord> pointerRecords = other.getPointerRecords();
- if (pointerRecords != null) {
- for (MdnsPointerRecord pointerRecord : pointerRecords) {
- if (addPointerRecord(pointerRecord)) {
- updated = true;
- }
+ for (MdnsInetAddressRecord inetAddressRecord : getInet4AddressRecords()) {
+ if (!Arrays.equals(
+ this.serviceRecord.getServiceHost(), inetAddressRecord.getName())) {
+ dropAddressRecords = true;
+ }
+ }
+ for (MdnsInetAddressRecord inetAddressRecord : getInet6AddressRecords()) {
+ if (!Arrays.equals(
+ this.serviceRecord.getServiceHost(), inetAddressRecord.getName())) {
+ dropAddressRecords = true;
}
}
- MdnsServiceRecord serviceRecord = other.getServiceRecord();
- if (serviceRecord != null) {
- if (setServiceRecord(serviceRecord)) {
- updated = true;
- }
+ if (dropAddressRecords) {
+ clearInet4AddressRecords();
+ clearInet6AddressRecords();
+ return true;
}
-
- MdnsTextRecord textRecord = other.getTextRecord();
- if (textRecord != null) {
- if (setTextRecord(textRecord)) {
- updated = true;
- }
- }
-
- MdnsInetAddressRecord otherInet4AddressRecord = other.getInet4AddressRecord();
- if (otherInet4AddressRecord != null && otherInet4AddressRecord.getInet4Address() != null) {
- if (setInet4AddressRecord(otherInet4AddressRecord)) {
- updated = true;
- }
- }
-
- MdnsInetAddressRecord otherInet6AddressRecord = other.getInet6AddressRecord();
- if (otherInet6AddressRecord != null && otherInet6AddressRecord.getInet6Address() != null) {
- if (setInet6AddressRecord(otherInet6AddressRecord)) {
- updated = true;
- }
- }
-
- // If the hostname in the service record no longer matches the hostname in either of the
- // address records, then drop the address records.
- if (this.serviceRecord != null) {
- boolean dropAddressRecords = false;
-
- if (this.inet4AddressRecord != null) {
- if (!Arrays.equals(
- this.serviceRecord.getServiceHost(), this.inet4AddressRecord.getName())) {
- dropAddressRecords = true;
- }
- }
- if (this.inet6AddressRecord != null) {
- if (!Arrays.equals(
- this.serviceRecord.getServiceHost(), this.inet6AddressRecord.getName())) {
- dropAddressRecords = true;
- }
- }
-
- if (dropAddressRecords) {
- setInet4AddressRecord(null);
- setInet6AddressRecord(null);
- updated = true;
- }
- }
-
- return updated;
+ return false;
}
/**
- * Tests if the response is complete. A response is considered complete if it contains PTR, SRV,
- * TXT, and A (for IPv4) or AAAA (for IPv6) records.
+ * Tests if the response is complete. A response is considered complete if it contains SRV,
+ * TXT, and A (for IPv4) or AAAA (for IPv6) records. The service type->name mapping is always
+ * known when constructing a MdnsResponse, so this may return true when there is no PTR record.
*/
public synchronized boolean isComplete() {
- return !pointerRecords.isEmpty()
- && (serviceRecord != null)
+ return (serviceRecord != null)
&& (textRecord != null)
- && (inet4AddressRecord != null || inet6AddressRecord != null);
+ && (!inet4AddressRecords.isEmpty() || !inet6AddressRecords.isEmpty());
}
/**
* Returns the key for this response. The key uniquely identifies the response by its service
* name.
*/
- public synchronized String getServiceInstanceName() {
- if (pointerRecords.isEmpty()) {
- return null;
- }
- String[] pointers = pointerRecords.get(0).getPointer();
- return ((pointers != null) && (pointers.length > 0)) ? pointers[0] : null;
+ @Nullable
+ public String getServiceInstanceName() {
+ return serviceName.length > 0 ? serviceName[0] : null;
+ }
+
+ @NonNull
+ public String[] getServiceName() {
+ return serviceName;
}
/**
@@ -388,13 +395,13 @@
++count;
}
- if (inet4AddressRecord != null) {
- inet4AddressRecord.write(writer, now);
+ for (MdnsInetAddressRecord inetAddressRecord : inet4AddressRecords) {
+ inetAddressRecord.write(writer, now);
++count;
}
- if (inet6AddressRecord != null) {
- inet6AddressRecord.write(writer, now);
+ for (MdnsInetAddressRecord inetAddressRecord : inet6AddressRecords) {
+ inetAddressRecord.write(writer, now);
++count;
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java b/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
index 82da2e4..129db7e 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
@@ -20,18 +20,18 @@
import android.annotation.Nullable;
import android.net.Network;
import android.os.SystemClock;
+import android.util.ArraySet;
import com.android.server.connectivity.mdns.util.MdnsLogger;
import java.io.EOFException;
-import java.net.DatagramPacket;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
/** A class that decodes mDNS responses from UDP packets. */
public class MdnsResponseDecoder {
-
public static final int SUCCESS = 0;
private static final String TAG = "MdnsResponseDecoder";
private static final MdnsLogger LOGGER = new MdnsLogger(TAG);
@@ -50,14 +50,8 @@
List<MdnsResponse> responses, String[] pointer) {
if (responses != null) {
for (MdnsResponse response : responses) {
- List<MdnsPointerRecord> pointerRecords = response.getPointerRecords();
- if (pointerRecords == null) {
- continue;
- }
- for (MdnsPointerRecord pointerRecord : pointerRecords) {
- if (Arrays.equals(pointerRecord.getPointer(), pointer)) {
- return response;
- }
+ if (Arrays.equals(response.getServiceName(), pointer)) {
+ return response;
}
}
}
@@ -82,34 +76,16 @@
/**
* Decodes all mDNS responses for the desired service type from a packet. The class does not
- * check
- * the responses for completeness; the caller should do that.
- *
- * @param packet The packet to read from.
- * @param interfaceIndex the network interface index (or {@link
- * MdnsSocket#INTERFACE_INDEX_UNSPECIFIED} if not known) at which the packet was received
- * @param network the network at which the packet was received, or null if it is unknown.
- * @return A list of mDNS responses, or null if the packet contained no appropriate responses.
- */
- public int decode(@NonNull DatagramPacket packet, @NonNull List<MdnsResponse> responses,
- int interfaceIndex, @Nullable Network network) {
- return decode(packet.getData(), packet.getLength(), responses, interfaceIndex, network);
- }
-
- /**
- * Decodes all mDNS responses for the desired service type from a packet. The class does not
- * check
- * the responses for completeness; the caller should do that.
+ * check the responses for completeness; the caller should do that.
*
* @param recvbuf The received data buffer to read from.
* @param length The length of received data buffer.
- * @param interfaceIndex the network interface index (or {@link
- * MdnsSocket#INTERFACE_INDEX_UNSPECIFIED} if not known) at which the packet was received
- * @param network the network at which the packet was received, or null if it is unknown.
- * @return A list of mDNS responses, or null if the packet contained no appropriate responses.
+ * @return A decoded {@link MdnsPacket}.
+ * @throws MdnsPacket.ParseException if a response packet could not be parsed.
*/
- public int decode(@NonNull byte[] recvbuf, int length, @NonNull List<MdnsResponse> responses,
- int interfaceIndex, @Nullable Network network) {
+ @NonNull
+ public static MdnsPacket parseResponse(@NonNull byte[] recvbuf, int length)
+ throws MdnsPacket.ParseException {
MdnsPacketReader reader = new MdnsPacketReader(recvbuf, length);
final MdnsPacket mdnsPacket;
@@ -117,21 +93,37 @@
reader.readUInt16(); // transaction ID (not used)
int flags = reader.readUInt16();
if ((flags & MdnsConstants.FLAGS_RESPONSE_MASK) != MdnsConstants.FLAGS_RESPONSE) {
- return MdnsResponseErrorCode.ERROR_NOT_RESPONSE_MESSAGE;
+ throw new MdnsPacket.ParseException(
+ MdnsResponseErrorCode.ERROR_NOT_RESPONSE_MESSAGE, "Not a response", null);
}
mdnsPacket = MdnsPacket.parseRecordsSection(reader, flags);
if (mdnsPacket.answers.size() < 1) {
- return MdnsResponseErrorCode.ERROR_NO_ANSWERS;
+ throw new MdnsPacket.ParseException(
+ MdnsResponseErrorCode.ERROR_NO_ANSWERS, "Response has no answers",
+ null);
}
+ return mdnsPacket;
} catch (EOFException e) {
- LOGGER.e("Reached the end of the mDNS response unexpectedly.", e);
- return MdnsResponseErrorCode.ERROR_END_OF_FILE;
- } catch (MdnsPacket.ParseException e) {
- LOGGER.e(e.getMessage(), e);
- return e.code;
+ throw new MdnsPacket.ParseException(MdnsResponseErrorCode.ERROR_END_OF_FILE,
+ "Reached the end of the mDNS response unexpectedly.", e);
}
+ }
+ /**
+ * Augments a list of {@link MdnsResponse} with records from a packet. The class does not check
+ * the resulting responses for completeness; the caller should do that.
+ *
+ * @param mdnsPacket the response packet with the new records
+ * @param existingResponses list of existing responses. Will not be modified.
+ * @param interfaceIndex the network interface index (or
+ * {@link MdnsSocket#INTERFACE_INDEX_UNSPECIFIED} if not known) at which the packet was received
+ * @param network the network at which the packet was received, or null if it is unknown.
+ * @return The set of response instances that were modified or newly added.
+ */
+ public ArraySet<MdnsResponse> augmentResponses(@NonNull MdnsPacket mdnsPacket,
+ @NonNull Collection<MdnsResponse> existingResponses, int interfaceIndex,
+ @Nullable Network network) {
final ArrayList<MdnsRecord> records = new ArrayList<>(
mdnsPacket.questions.size() + mdnsPacket.answers.size()
+ mdnsPacket.authorityRecords.size() + mdnsPacket.additionalRecords.size());
@@ -139,6 +131,11 @@
records.addAll(mdnsPacket.authorityRecords);
records.addAll(mdnsPacket.additionalRecords);
+ final ArraySet<MdnsResponse> modified = new ArraySet<>();
+ final ArrayList<MdnsResponse> responses = new ArrayList<>(existingResponses.size());
+ for (MdnsResponse existing : existingResponses) {
+ responses.add(new MdnsResponse(existing));
+ }
// The response records are structured in a hierarchy, where some records reference
// others, as follows:
//
@@ -178,12 +175,14 @@
MdnsResponse response = findResponseWithPointer(responses,
pointerRecord.getPointer());
if (response == null) {
- response = new MdnsResponse(now, interfaceIndex, network);
+ response = new MdnsResponse(now, pointerRecord.getPointer(), interfaceIndex,
+ network);
responses.add(response);
}
- // Set interface index earlier because some responses have PTR record only.
- // Need to know every response is getting from which interface.
- response.addPointerRecord((MdnsPointerRecord) record);
+
+ if (response.addPointerRecord((MdnsPointerRecord) record)) {
+ modified.add(response);
+ }
}
}
}
@@ -193,47 +192,96 @@
if (record instanceof MdnsServiceRecord) {
MdnsServiceRecord serviceRecord = (MdnsServiceRecord) record;
MdnsResponse response = findResponseWithPointer(responses, serviceRecord.getName());
- if (response != null) {
- response.setServiceRecord(serviceRecord);
+ if (response != null && response.setServiceRecord(serviceRecord)) {
+ response.dropUnmatchedAddressRecords();
+ modified.add(response);
}
} else if (record instanceof MdnsTextRecord) {
MdnsTextRecord textRecord = (MdnsTextRecord) record;
MdnsResponse response = findResponseWithPointer(responses, textRecord.getName());
- if (response != null) {
- response.setTextRecord(textRecord);
+ if (response != null && response.setTextRecord(textRecord)) {
+ modified.add(response);
}
}
}
- // Loop 3: find A and AAAA records, which reference the host name in the SRV record.
+ // Loop 3-1: find A and AAAA records and clear addresses if the cache-flush bit set, which
+ // reference the host name in the SRV record.
+ final List<MdnsInetAddressRecord> inetRecords = new ArrayList<>();
for (MdnsRecord record : records) {
if (record instanceof MdnsInetAddressRecord) {
MdnsInetAddressRecord inetRecord = (MdnsInetAddressRecord) record;
+ inetRecords.add(inetRecord);
if (allowMultipleSrvRecordsPerHost) {
List<MdnsResponse> matchingResponses =
findResponsesWithHostName(responses, inetRecord.getName());
for (MdnsResponse response : matchingResponses) {
- assignInetRecord(response, inetRecord);
+ // Per RFC6762 10.2, clear all address records if the cache-flush bit set.
+ // This bit, the cache-flush bit, tells neighboring hosts
+ // that this is not a shared record type. Instead of merging this new
+ // record additively into the cache in addition to any previous records with
+ // the same name, rrtype, and rrclass.
+ // TODO: All old records with that name, rrtype, and rrclass that were
+ // received more than one second ago are declared invalid, and marked
+ // to expire from the cache in one second.
+ if (inetRecord.getCacheFlush()) {
+ response.clearInet4AddressRecords();
+ response.clearInet6AddressRecords();
+ }
}
} else {
MdnsResponse response =
findResponseWithHostName(responses, inetRecord.getName());
if (response != null) {
- assignInetRecord(response, inetRecord);
+ // Per RFC6762 10.2, clear all address records if the cache-flush bit set.
+ // This bit, the cache-flush bit, tells neighboring hosts
+ // that this is not a shared record type. Instead of merging this new
+ // record additively into the cache in addition to any previous records with
+ // the same name, rrtype, and rrclass.
+ // TODO: All old records with that name, rrtype, and rrclass that were
+ // received more than one second ago are declared invalid, and marked
+ // to expire from the cache in one second.
+ if (inetRecord.getCacheFlush()) {
+ response.clearInet4AddressRecords();
+ response.clearInet6AddressRecords();
+ }
}
}
}
}
- return SUCCESS;
+ // Loop 3-2: Assign addresses, which reference the host name in the SRV record.
+ for (MdnsInetAddressRecord inetRecord : inetRecords) {
+ if (allowMultipleSrvRecordsPerHost) {
+ List<MdnsResponse> matchingResponses =
+ findResponsesWithHostName(responses, inetRecord.getName());
+ for (MdnsResponse response : matchingResponses) {
+ if (assignInetRecord(response, inetRecord)) {
+ modified.add(response);
+ }
+ }
+ } else {
+ MdnsResponse response =
+ findResponseWithHostName(responses, inetRecord.getName());
+ if (response != null) {
+ if (assignInetRecord(response, inetRecord)) {
+ modified.add(response);
+ }
+ }
+ }
+ }
+
+ return modified;
}
- private static void assignInetRecord(MdnsResponse response, MdnsInetAddressRecord inetRecord) {
+ private static boolean assignInetRecord(
+ MdnsResponse response, MdnsInetAddressRecord inetRecord) {
if (inetRecord.getInet4Address() != null) {
- response.setInet4AddressRecord(inetRecord);
+ return response.addInet4AddressRecord(inetRecord);
} else if (inetRecord.getInet6Address() != null) {
- response.setInet6AddressRecord(inetRecord);
+ return response.addInet6AddressRecord(inetRecord);
}
+ return false;
}
private static List<MdnsResponse> findResponsesWithHostName(
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSearchOptions.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSearchOptions.java
index 583c4a9..3da6bd0 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSearchOptions.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSearchOptions.java
@@ -46,7 +46,8 @@
public MdnsSearchOptions createFromParcel(Parcel source) {
return new MdnsSearchOptions(source.createStringArrayList(),
source.readBoolean(), source.readBoolean(),
- source.readParcelable(null));
+ source.readParcelable(null),
+ source.readString());
}
@Override
@@ -56,6 +57,8 @@
};
private static MdnsSearchOptions defaultOptions;
private final List<String> subtypes;
+ @Nullable
+ private final String resolveInstanceName;
private final boolean isPassiveMode;
private final boolean removeExpiredService;
@@ -64,7 +67,7 @@
/** Parcelable constructs for a {@link MdnsSearchOptions}. */
MdnsSearchOptions(List<String> subtypes, boolean isPassiveMode, boolean removeExpiredService,
- @Nullable Network network) {
+ @Nullable Network network, @Nullable String resolveInstanceName) {
this.subtypes = new ArrayList<>();
if (subtypes != null) {
this.subtypes.addAll(subtypes);
@@ -72,6 +75,7 @@
this.isPassiveMode = isPassiveMode;
this.removeExpiredService = removeExpiredService;
mNetwork = network;
+ this.resolveInstanceName = resolveInstanceName;
}
/** Returns a {@link Builder} for {@link MdnsSearchOptions}. */
@@ -115,6 +119,15 @@
return mNetwork;
}
+ /**
+ * If non-null, queries should try to resolve all records of this specific service, rather than
+ * discovering all services.
+ */
+ @Nullable
+ public String getResolveInstanceName() {
+ return resolveInstanceName;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -126,6 +139,7 @@
out.writeBoolean(isPassiveMode);
out.writeBoolean(removeExpiredService);
out.writeParcelable(mNetwork, 0);
+ out.writeString(resolveInstanceName);
}
/** A builder to create {@link MdnsSearchOptions}. */
@@ -134,6 +148,7 @@
private boolean isPassiveMode = true;
private boolean removeExpiredService;
private Network mNetwork;
+ private String resolveInstanceName;
private Builder() {
subtypes = new ArraySet<>();
@@ -194,10 +209,22 @@
return this;
}
+ /**
+ * Set the instance name to resolve.
+ *
+ * If non-null, queries should try to resolve all records of this specific service,
+ * rather than discovering all services.
+ * @param name The instance name.
+ */
+ public Builder setResolveInstanceName(String name) {
+ resolveInstanceName = name;
+ return this;
+ }
+
/** Builds a {@link MdnsSearchOptions} with the arguments supplied to this builder. */
public MdnsSearchOptions build() {
return new MdnsSearchOptions(new ArrayList<>(subtypes), isPassiveMode,
- removeExpiredService, mNetwork);
+ removeExpiredService, mNetwork, resolveInstanceName);
}
}
}
\ No newline at end of file
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java
index 938fc3f..78df6df 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java
@@ -31,10 +31,10 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.TreeMap;
/**
* A class representing a discovered mDNS service instance.
@@ -57,8 +57,8 @@
source.createStringArrayList(),
source.createStringArray(),
source.readInt(),
- source.readString(),
- source.readString(),
+ source.createStringArrayList(),
+ source.createStringArrayList(),
source.createStringArrayList(),
source.createTypedArrayList(TextEntry.CREATOR),
source.readInt(),
@@ -76,10 +76,10 @@
private final List<String> subtypes;
private final String[] hostName;
private final int port;
- @Nullable
- private final String ipv4Address;
- @Nullable
- private final String ipv6Address;
+ @NonNull
+ private final List<String> ipv4Addresses;
+ @NonNull
+ private final List<String> ipv6Addresses;
final List<String> textStrings;
@Nullable
final List<TextEntry> textEntries;
@@ -105,8 +105,8 @@
subtypes,
hostName,
port,
- ipv4Address,
- ipv6Address,
+ List.of(ipv4Address),
+ List.of(ipv6Address),
textStrings,
/* textEntries= */ null,
/* interfaceIndex= */ INTERFACE_INDEX_UNSPECIFIED,
@@ -130,8 +130,8 @@
subtypes,
hostName,
port,
- ipv4Address,
- ipv6Address,
+ List.of(ipv4Address),
+ List.of(ipv6Address),
textStrings,
textEntries,
/* interfaceIndex= */ INTERFACE_INDEX_UNSPECIFIED,
@@ -160,8 +160,8 @@
subtypes,
hostName,
port,
- ipv4Address,
- ipv6Address,
+ List.of(ipv4Address),
+ List.of(ipv6Address),
textStrings,
textEntries,
interfaceIndex,
@@ -179,8 +179,8 @@
@Nullable List<String> subtypes,
String[] hostName,
int port,
- @Nullable String ipv4Address,
- @Nullable String ipv6Address,
+ @NonNull List<String> ipv4Addresses,
+ @NonNull List<String> ipv6Addresses,
@Nullable List<String> textStrings,
@Nullable List<TextEntry> textEntries,
int interfaceIndex,
@@ -193,8 +193,8 @@
}
this.hostName = hostName;
this.port = port;
- this.ipv4Address = ipv4Address;
- this.ipv6Address = ipv6Address;
+ this.ipv4Addresses = new ArrayList<>(ipv4Addresses);
+ this.ipv6Addresses = new ArrayList<>(ipv6Addresses);
this.textStrings = new ArrayList<>();
if (textStrings != null) {
this.textStrings.addAll(textStrings);
@@ -205,17 +205,14 @@
// compatibility. We should prefer only {@code textEntries} if it's not null.
List<TextEntry> entries =
(this.textEntries != null) ? this.textEntries : parseTextStrings(this.textStrings);
- Map<String, byte[]> attributes = new HashMap<>(entries.size());
+ // The map of attributes is case-insensitive.
+ final Map<String, byte[]> attributes = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (TextEntry entry : entries) {
- String key = entry.getKey().toLowerCase(Locale.ENGLISH);
-
// Per https://datatracker.ietf.org/doc/html/rfc6763#section-6.4, only the first entry
// of the same key should be accepted:
// If a client receives a TXT record containing the same key more than once, then the
// client MUST silently ignore all but the first occurrence of that attribute.
- if (!attributes.containsKey(key)) {
- attributes.put(key, entry.getValue());
- }
+ attributes.putIfAbsent(entry.getKey(), entry.getValue());
}
this.attributes = Collections.unmodifiableMap(attributes);
this.interfaceIndex = interfaceIndex;
@@ -263,16 +260,41 @@
return port;
}
- /** Returns the IPV4 address of this service instance. */
+ /** Returns the IPV4 addresses of this service instance. */
+ @NonNull
+ public List<String> getIpv4Addresses() {
+ return Collections.unmodifiableList(ipv4Addresses);
+ }
+
+ /**
+ * Returns the first IPV4 address of this service instance.
+ *
+ * @deprecated Use {@link #getIpv4Addresses()} to get the entire list of IPV4
+ * addresses for
+ * the host.
+ */
@Nullable
+ @Deprecated
public String getIpv4Address() {
- return ipv4Address;
+ return ipv4Addresses.isEmpty() ? null : ipv4Addresses.get(0);
}
/** Returns the IPV6 address of this service instance. */
+ @NonNull
+ public List<String> getIpv6Addresses() {
+ return Collections.unmodifiableList(ipv6Addresses);
+ }
+
+ /**
+ * Returns the first IPV6 address of this service instance.
+ *
+ * @deprecated Use {@link #getIpv6Addresses()} to get the entire list of IPV6 addresses for
+ * the host.
+ */
@Nullable
+ @Deprecated
public String getIpv6Address() {
- return ipv6Address;
+ return ipv6Addresses.isEmpty() ? null : ipv6Addresses.get(0);
}
/**
@@ -311,12 +333,12 @@
*/
@Nullable
public byte[] getAttributeAsBytes(@NonNull String key) {
- return attributes.get(key.toLowerCase(Locale.ENGLISH));
+ return attributes.get(key);
}
/** Returns an immutable map of all attributes. */
public Map<String, String> getAttributes() {
- Map<String, String> map = new HashMap<>(attributes.size());
+ Map<String, String> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (Map.Entry<String, byte[]> kv : attributes.entrySet()) {
final byte[] value = kv.getValue();
map.put(kv.getKey(), value == null ? null : new String(value, UTF_8));
@@ -336,8 +358,8 @@
out.writeStringList(subtypes);
out.writeStringArray(hostName);
out.writeInt(port);
- out.writeString(ipv4Address);
- out.writeString(ipv6Address);
+ out.writeStringList(ipv4Addresses);
+ out.writeStringList(ipv6Addresses);
out.writeStringList(textStrings);
out.writeTypedList(textEntries);
out.writeInt(interfaceIndex);
@@ -346,13 +368,16 @@
@Override
public String toString() {
- return String.format(
- Locale.ROOT,
- "Name: %s, subtypes: %s, ip: %s, port: %d",
- serviceInstanceName,
- TextUtils.join(",", subtypes),
- ipv4Address,
- port);
+ return "Name: " + serviceInstanceName
+ + ", type: " + TextUtils.join(".", serviceType)
+ + ", subtypes: " + TextUtils.join(",", subtypes)
+ + ", ip: " + ipv4Addresses
+ + ", ipv6: " + ipv6Addresses
+ + ", port: " + port
+ + ", interfaceIndex: " + interfaceIndex
+ + ", network: " + network
+ + ", textStrings: " + textStrings
+ + ", textEntries: " + textEntries;
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
index d26fbdb..5298aef 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
@@ -21,8 +21,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.Network;
-import android.os.SystemClock;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
@@ -33,12 +33,12 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
@@ -51,18 +51,24 @@
private static final int DEFAULT_MTU = 1500;
private static final MdnsLogger LOGGER = new MdnsLogger("MdnsServiceTypeClient");
+
private final String serviceType;
private final String[] serviceTypeLabels;
private final MdnsSocketClientBase socketClient;
+ private final MdnsResponseDecoder responseDecoder;
private final ScheduledExecutorService executor;
+ @Nullable private final Network network;
private final Object lock = new Object();
- private final Set<MdnsServiceBrowserListener> listeners = new ArraySet<>();
+ private final ArrayMap<MdnsServiceBrowserListener, MdnsSearchOptions> listeners =
+ new ArrayMap<>();
private final Map<String, MdnsResponse> instanceNameToResponse = new HashMap<>();
private final boolean removeServiceAfterTtlExpires =
MdnsConfigs.removeServiceAfterTtlExpires();
private final boolean allowSearchOptionsToRemoveExpiredService =
MdnsConfigs.allowSearchOptionsToRemoveExpiredService();
+ private final MdnsResponseDecoder.Clock clock;
+
@Nullable private MdnsSearchOptions searchOptions;
// The session ID increases when startSendAndReceive() is called where we schedule a
@@ -83,11 +89,25 @@
public MdnsServiceTypeClient(
@NonNull String serviceType,
@NonNull MdnsSocketClientBase socketClient,
- @NonNull ScheduledExecutorService executor) {
+ @NonNull ScheduledExecutorService executor,
+ @Nullable Network network) {
+ this(serviceType, socketClient, executor, new MdnsResponseDecoder.Clock(), network);
+ }
+
+ @VisibleForTesting
+ public MdnsServiceTypeClient(
+ @NonNull String serviceType,
+ @NonNull MdnsSocketClientBase socketClient,
+ @NonNull ScheduledExecutorService executor,
+ @NonNull MdnsResponseDecoder.Clock clock,
+ @Nullable Network network) {
this.serviceType = serviceType;
this.socketClient = socketClient;
this.executor = executor;
- serviceTypeLabels = TextUtils.split(serviceType, "\\.");
+ this.serviceTypeLabels = TextUtils.split(serviceType, "\\.");
+ this.responseDecoder = new MdnsResponseDecoder(clock, serviceTypeLabels);
+ this.clock = clock;
+ this.network = network;
}
private static MdnsServiceInfo buildMdnsServiceInfoFromResponse(
@@ -99,15 +119,19 @@
port = response.getServiceRecord().getServicePort();
}
- String ipv4Address = null;
- String ipv6Address = null;
+ final List<String> ipv4Addresses = new ArrayList<>();
+ final List<String> ipv6Addresses = new ArrayList<>();
if (response.hasInet4AddressRecord()) {
- Inet4Address inet4Address = response.getInet4AddressRecord().getInet4Address();
- ipv4Address = (inet4Address == null) ? null : inet4Address.getHostAddress();
+ for (MdnsInetAddressRecord inetAddressRecord : response.getInet4AddressRecords()) {
+ final Inet4Address inet4Address = inetAddressRecord.getInet4Address();
+ ipv4Addresses.add((inet4Address == null) ? null : inet4Address.getHostAddress());
+ }
}
if (response.hasInet6AddressRecord()) {
- Inet6Address inet6Address = response.getInet6AddressRecord().getInet6Address();
- ipv6Address = (inet6Address == null) ? null : inet6Address.getHostAddress();
+ for (MdnsInetAddressRecord inetAddressRecord : response.getInet6AddressRecords()) {
+ final Inet6Address inet6Address = inetAddressRecord.getInet6Address();
+ ipv6Addresses.add((inet6Address == null) ? null : inet6Address.getHostAddress());
+ }
}
String serviceInstanceName = response.getServiceInstanceName();
if (serviceInstanceName == null) {
@@ -127,8 +151,8 @@
response.getSubtypes(),
hostName,
port,
- ipv4Address,
- ipv6Address,
+ ipv4Addresses,
+ ipv6Addresses,
textStrings,
textEntries,
response.getInterfaceIndex(),
@@ -148,8 +172,9 @@
@NonNull MdnsSearchOptions searchOptions) {
synchronized (lock) {
this.searchOptions = searchOptions;
- if (listeners.add(listener)) {
+ if (listeners.put(listener, searchOptions) == null) {
for (MdnsResponse existingResponse : instanceNameToResponse.values()) {
+ if (!responseMatchesOptions(existingResponse, searchOptions)) continue;
final MdnsServiceInfo info =
buildMdnsServiceInfoFromResponse(existingResponse, serviceTypeLabels);
listener.onServiceNameDiscovered(info);
@@ -175,6 +200,13 @@
}
}
+ private boolean responseMatchesOptions(@NonNull MdnsResponse response,
+ @NonNull MdnsSearchOptions options) {
+ if (options.getResolveInstanceName() == null) return true;
+ // DNS is case-insensitive, so ignore case in the comparison
+ return options.getResolveInstanceName().equalsIgnoreCase(response.getServiceInstanceName());
+ }
+
/**
* Unregisters {@code listener} from receiving discovery event of mDNS service instances.
*
@@ -184,7 +216,9 @@
*/
public boolean stopSendAndReceive(@NonNull MdnsServiceBrowserListener listener) {
synchronized (lock) {
- listeners.remove(listener);
+ if (listeners.remove(listener) == null) {
+ return listeners.isEmpty();
+ }
if (listeners.isEmpty() && requestTaskFuture != null) {
requestTaskFuture.cancel(true);
requestTaskFuture = null;
@@ -197,65 +231,64 @@
return serviceTypeLabels;
}
- public synchronized void processResponse(@NonNull MdnsResponse response) {
- if (shouldRemoveServiceAfterTtlExpires()) {
- // Because {@link QueryTask} and {@link processResponse} are running in different
- // threads. We need to synchronize {@link lock} to protect
- // {@link instanceNameToResponse} won’t be modified at the same time.
- synchronized (lock) {
- if (response.isGoodbye()) {
- onGoodbyeReceived(response.getServiceInstanceName());
+ /**
+ * Process an incoming response packet.
+ */
+ public synchronized void processResponse(@NonNull MdnsPacket packet, int interfaceIndex,
+ Network network) {
+ synchronized (lock) {
+ // Augment the list of current known responses, and generated responses for resolve
+ // requests if there is no known response
+ final List<MdnsResponse> currentList = new ArrayList<>(instanceNameToResponse.values());
+ currentList.addAll(makeResponsesForResolveIfUnknown(interfaceIndex, network));
+ final ArraySet<MdnsResponse> modifiedResponses = responseDecoder.augmentResponses(
+ packet, currentList, interfaceIndex, network);
+
+ for (MdnsResponse modified : modifiedResponses) {
+ if (modified.isGoodbye()) {
+ onGoodbyeReceived(modified.getServiceInstanceName());
} else {
- onResponseReceived(response);
+ onResponseModified(modified);
}
}
- } else {
- if (response.isGoodbye()) {
- onGoodbyeReceived(response.getServiceInstanceName());
- } else {
- onResponseReceived(response);
- }
}
}
public synchronized void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode) {
- for (MdnsServiceBrowserListener listener : listeners) {
- listener.onFailedToParseMdnsResponse(receivedPacketNumber, errorCode);
+ for (int i = 0; i < listeners.size(); i++) {
+ listeners.keyAt(i).onFailedToParseMdnsResponse(receivedPacketNumber, errorCode);
}
}
- private void onResponseReceived(@NonNull MdnsResponse response) {
- MdnsResponse currentResponse;
- currentResponse = instanceNameToResponse.get(response.getServiceInstanceName());
+ private void onResponseModified(@NonNull MdnsResponse response) {
+ final MdnsResponse currentResponse =
+ instanceNameToResponse.get(response.getServiceInstanceName());
boolean newServiceFound = false;
- boolean existingServiceChanged = false;
boolean serviceBecomesComplete = false;
if (currentResponse == null) {
newServiceFound = true;
- currentResponse = response;
String serviceInstanceName = response.getServiceInstanceName();
if (serviceInstanceName != null) {
- instanceNameToResponse.put(serviceInstanceName, currentResponse);
+ instanceNameToResponse.put(serviceInstanceName, response);
}
} else {
boolean before = currentResponse.isComplete();
- existingServiceChanged = currentResponse.mergeRecordsFrom(response);
- boolean after = currentResponse.isComplete();
+ instanceNameToResponse.put(response.getServiceInstanceName(), response);
+ boolean after = response.isComplete();
serviceBecomesComplete = !before && after;
}
- if (!newServiceFound && !existingServiceChanged) {
- return;
- }
MdnsServiceInfo serviceInfo =
- buildMdnsServiceInfoFromResponse(currentResponse, serviceTypeLabels);
+ buildMdnsServiceInfoFromResponse(response, serviceTypeLabels);
- for (MdnsServiceBrowserListener listener : listeners) {
+ for (int i = 0; i < listeners.size(); i++) {
+ if (!responseMatchesOptions(response, listeners.valueAt(i))) continue;
+ final MdnsServiceBrowserListener listener = listeners.keyAt(i);
if (newServiceFound) {
listener.onServiceNameDiscovered(serviceInfo);
}
- if (currentResponse.isComplete()) {
+ if (response.isComplete()) {
if (newServiceFound || serviceBecomesComplete) {
listener.onServiceFound(serviceInfo);
} else {
@@ -270,7 +303,9 @@
if (response == null) {
return;
}
- for (MdnsServiceBrowserListener listener : listeners) {
+ for (int i = 0; i < listeners.size(); i++) {
+ if (!responseMatchesOptions(response, listeners.valueAt(i))) continue;
+ final MdnsServiceBrowserListener listener = listeners.keyAt(i);
final MdnsServiceInfo serviceInfo =
buildMdnsServiceInfoFromResponse(response, serviceTypeLabels);
if (response.isComplete()) {
@@ -389,6 +424,29 @@
}
}
+ private List<MdnsResponse> makeResponsesForResolveIfUnknown(int interfaceIndex,
+ @NonNull Network network) {
+ final List<MdnsResponse> resolveResponses = new ArrayList<>();
+ for (int i = 0; i < listeners.size(); i++) {
+ final String resolveName = listeners.valueAt(i).getResolveInstanceName();
+ if (resolveName == null) {
+ continue;
+ }
+ MdnsResponse knownResponse = instanceNameToResponse.get(resolveName);
+ if (knownResponse == null) {
+ final ArrayList<String> instanceFullName = new ArrayList<>(
+ serviceTypeLabels.length + 1);
+ instanceFullName.add(resolveName);
+ instanceFullName.addAll(Arrays.asList(serviceTypeLabels));
+ knownResponse = new MdnsResponse(
+ 0L /* lastUpdateTime */, instanceFullName.toArray(new String[0]),
+ interfaceIndex, network);
+ }
+ resolveResponses.add(knownResponse);
+ }
+ return resolveResponses;
+ }
+
// A FutureTask that enqueues a single query, and schedule a new FutureTask for the next task.
private class QueryTask implements Runnable {
@@ -400,6 +458,18 @@
@Override
public void run() {
+ final List<MdnsResponse> servicesToResolve;
+ final boolean sendDiscoveryQueries;
+ synchronized (lock) {
+ // The listener is requesting to resolve a service that has no info in
+ // cache. Use the provided name to generate a minimal response, so other records are
+ // queried to complete it.
+ // Only the names are used to know which queries to send, other parameters like
+ // interfaceIndex do not matter.
+ servicesToResolve = makeResponsesForResolveIfUnknown(
+ 0 /* interfaceIndex */, config.network);
+ sendDiscoveryQueries = servicesToResolve.size() < listeners.size();
+ }
Pair<Integer, List<String>> result;
try {
result =
@@ -410,7 +480,9 @@
config.subtypes,
config.expectUnicastResponse,
config.transactionId,
- config.network)
+ config.network,
+ sendDiscoveryQueries,
+ servicesToResolve)
.call();
} catch (RuntimeException e) {
LOGGER.e(String.format("Failed to run EnqueueMdnsQueryCallable for subtype: %s",
@@ -435,8 +507,8 @@
}
}
if ((result != null)) {
- for (MdnsServiceBrowserListener listener : listeners) {
- listener.onDiscoveryQuerySent(result.second, result.first);
+ for (int i = 0; i < listeners.size(); i++) {
+ listeners.keyAt(i).onDiscoveryQuerySent(result.second, result.first);
}
}
if (shouldRemoveServiceAfterTtlExpires()) {
@@ -446,10 +518,15 @@
if (existingResponse.hasServiceRecord()
&& existingResponse
.getServiceRecord()
- .getRemainingTTL(SystemClock.elapsedRealtime())
+ .getRemainingTTL(clock.elapsedRealtime())
== 0) {
iter.remove();
- for (MdnsServiceBrowserListener listener : listeners) {
+ for (int i = 0; i < listeners.size(); i++) {
+ if (!responseMatchesOptions(existingResponse,
+ listeners.valueAt(i))) {
+ continue;
+ }
+ final MdnsServiceBrowserListener listener = listeners.keyAt(i);
String serviceInstanceName =
existingResponse.getServiceInstanceName();
if (serviceInstanceName != null) {
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
index 907687e..783b18a 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
@@ -16,8 +16,6 @@
package com.android.server.connectivity.mdns;
-import static com.android.server.connectivity.mdns.MdnsSocketClientBase.Callback;
-
import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,7 +33,6 @@
import java.net.DatagramPacket;
import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Timer;
@@ -73,7 +70,6 @@
private final Context context;
private final byte[] multicastReceiverBuffer = new byte[RECEIVER_BUFFER_SIZE];
@Nullable private final byte[] unicastReceiverBuffer;
- private final MdnsResponseDecoder responseDecoder;
private final MulticastLock multicastLock;
private final boolean useSeparateSocketForUnicast =
MdnsConfigs.useSeparateSocketToSendUnicastQuery();
@@ -110,7 +106,6 @@
public MdnsSocketClient(@NonNull Context context, @NonNull MulticastLock multicastLock) {
this.context = context;
this.multicastLock = multicastLock;
- responseDecoder = new MdnsResponseDecoder(new MdnsResponseDecoder.Clock(), null);
if (useSeparateSocketForUnicast) {
unicastReceiverBuffer = new byte[RECEIVER_BUFFER_SIZE];
} else {
@@ -421,37 +416,27 @@
int interfaceIndex, @Nullable Network network) {
int packetNumber = ++receivedPacketNumber;
- List<MdnsResponse> responses = new LinkedList<>();
- int errorCode = responseDecoder.decode(packet, responses, interfaceIndex, network);
- if (errorCode == MdnsResponseDecoder.SUCCESS) {
- if (responseType.equals(MULTICAST_TYPE)) {
- receivedMulticastResponse = true;
- if (cannotReceiveMulticastResponse.getAndSet(false)) {
- // If we are already in the bad state, receiving a multicast response means
- // we are recovered.
- LOGGER.e(
- "Recovered from the state where the phone can't receive any multicast"
- + " response");
- }
- } else {
- receivedUnicastResponse = true;
- }
- for (MdnsResponse response : responses) {
- String serviceInstanceName = response.getServiceInstanceName();
- LOGGER.log("mDNS %s response received: %s at ifIndex %d", responseType,
- serviceInstanceName, interfaceIndex);
- if (callback != null) {
- callback.onResponseReceived(response);
- }
- }
- } else if (errorCode != MdnsResponseErrorCode.ERROR_NOT_RESPONSE_MESSAGE) {
+ final MdnsPacket response;
+ try {
+ response = MdnsResponseDecoder.parseResponse(packet.getData(), packet.getLength());
+ } catch (MdnsPacket.ParseException e) {
LOGGER.w(String.format("Error while decoding %s packet (%d): %d",
- responseType, packetNumber, errorCode));
+ responseType, packetNumber, e.code));
if (callback != null) {
- callback.onFailedToParseMdnsResponse(packetNumber, errorCode);
+ callback.onFailedToParseMdnsResponse(packetNumber, e.code, network);
}
+ return e.code;
}
- return errorCode;
+
+ if (response == null) {
+ return MdnsResponseErrorCode.ERROR_NOT_RESPONSE_MESSAGE;
+ }
+
+ if (callback != null) {
+ callback.onResponseReceived(response, interfaceIndex, network);
+ }
+
+ return MdnsResponseErrorCode.SUCCESS;
}
@VisibleForTesting
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
index 23504a0..ebafc49 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
@@ -64,7 +64,9 @@
/*** Notify that the given network is requested for mdns discovery / resolution */
default void notifyNetworkRequested(@NonNull MdnsServiceBrowserListener listener,
- @Nullable Network network) { }
+ @Nullable Network network, @NonNull SocketCreationCallback socketCreationCallback) {
+ socketCreationCallback.onSocketCreated(network);
+ }
/*** Notify that the network is unrequested */
default void notifyNetworkUnrequested(@NonNull MdnsServiceBrowserListener listener) { }
@@ -72,9 +74,17 @@
/*** Callback for mdns response */
interface Callback {
/*** Receive a mdns response */
- void onResponseReceived(@NonNull MdnsResponse response);
+ void onResponseReceived(@NonNull MdnsPacket packet, int interfaceIndex,
+ @Nullable Network network);
/*** Parse a mdns response failed */
- void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode);
+ void onFailedToParseMdnsResponse(int receivedPacketNumber, int errorCode,
+ @Nullable Network network);
+ }
+
+ /*** Callback for requested socket creation */
+ interface SocketCreationCallback {
+ /*** Notify requested socket is created */
+ void onSocketCreated(@Nullable Network network);
}
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
index 9298852..8017ee0 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
@@ -16,30 +16,32 @@
package com.android.server.connectivity.mdns;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
-import android.net.INetd;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.TetheringManager;
import android.net.TetheringManager.TetheringEventCallback;
import android.os.Handler;
import android.os.Looper;
-import android.system.OsConstants;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
-import com.android.net.module.util.ip.NetlinkMonitor;
-import com.android.net.module.util.netlink.NetlinkConstants;
-import com.android.net.module.util.netlink.NetlinkMessage;
+import com.android.net.module.util.SharedLog;
import com.android.server.connectivity.mdns.util.MdnsLogger;
import java.io.IOException;
@@ -65,23 +67,29 @@
// Note: mdnsresponder mDNSEmbeddedAPI.h uses 8940 for Ethernet jumbo frames.
private static final int READ_BUFFER_SIZE = 2048;
private static final MdnsLogger LOGGER = new MdnsLogger(TAG);
+ private static final int IFACE_IDX_NOT_EXIST = -1;
@NonNull private final Context mContext;
@NonNull private final Looper mLooper;
@NonNull private final Handler mHandler;
@NonNull private final Dependencies mDependencies;
@NonNull private final NetworkCallback mNetworkCallback;
@NonNull private final TetheringEventCallback mTetheringEventCallback;
- @NonNull private final NetlinkMonitor mNetlinkMonitor;
+ @NonNull private final ISocketNetLinkMonitor mSocketNetlinkMonitor;
private final ArrayMap<Network, SocketInfo> mNetworkSockets = new ArrayMap<>();
private final ArrayMap<String, SocketInfo> mTetherInterfaceSockets = new ArrayMap<>();
private final ArrayMap<Network, LinkProperties> mActiveNetworksLinkProperties =
new ArrayMap<>();
+ private final ArrayMap<Network, int[]> mActiveNetworksTransports = new ArrayMap<>();
private final ArrayMap<SocketCallback, Network> mCallbacksToRequestedNetworks =
new ArrayMap<>();
private final List<String> mLocalOnlyInterfaces = new ArrayList<>();
private final List<String> mTetheredInterfaces = new ArrayList<>();
+ // mIfaceIdxToLinkProperties should not be cleared in maybeStopMonitoringSockets() because
+ // the netlink monitor is never stop and the old states must be kept.
+ private final SparseArray<LinkProperties> mIfaceIdxToLinkProperties = new SparseArray<>();
private final byte[] mPacketReadBuffer = new byte[READ_BUFFER_SIZE];
private boolean mMonitoringSockets = false;
+ private boolean mRequestStop = false;
public MdnsSocketProvider(@NonNull Context context, @NonNull Looper looper) {
this(context, looper, new Dependencies());
@@ -97,7 +105,14 @@
@Override
public void onLost(Network network) {
mActiveNetworksLinkProperties.remove(network);
- removeSocket(network, null /* interfaceName */);
+ mActiveNetworksTransports.remove(network);
+ removeNetworkSocket(network);
+ }
+
+ @Override
+ public void onCapabilitiesChanged(@NonNull Network network,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ mActiveNetworksTransports.put(network, networkCapabilities.getTransportTypes());
}
@Override
@@ -117,7 +132,8 @@
}
};
- mNetlinkMonitor = new SocketNetlinkMonitor(mHandler);
+ mSocketNetlinkMonitor = mDependencies.createSocketNetlinkMonitor(mHandler, LOGGER.mLog,
+ new NetLinkMessageProcessor());
}
/**
@@ -132,19 +148,89 @@
return ni == null ? null : new NetworkInterfaceWrapper(ni);
}
- /*** Check whether given network interface can support mdns */
- public boolean canScanOnInterface(@NonNull NetworkInterfaceWrapper networkInterface) {
- return MulticastNetworkInterfaceProvider.canScanOnInterface(networkInterface);
- }
-
/*** Create a MdnsInterfaceSocket */
public MdnsInterfaceSocket createMdnsInterfaceSocket(
@NonNull NetworkInterface networkInterface, int port, @NonNull Looper looper,
@NonNull byte[] packetReadBuffer) throws IOException {
return new MdnsInterfaceSocket(networkInterface, port, looper, packetReadBuffer);
}
- }
+ /*** Get network interface by given interface name */
+ public int getNetworkInterfaceIndexByName(@NonNull final String ifaceName) {
+ final NetworkInterface iface;
+ try {
+ iface = NetworkInterface.getByName(ifaceName);
+ } catch (SocketException e) {
+ Log.e(TAG, "Error querying interface", e);
+ return IFACE_IDX_NOT_EXIST;
+ }
+ if (iface == null) {
+ Log.e(TAG, "Interface not found: " + ifaceName);
+ return IFACE_IDX_NOT_EXIST;
+ }
+ return iface.getIndex();
+ }
+ /*** Creates a SocketNetlinkMonitor */
+ public ISocketNetLinkMonitor createSocketNetlinkMonitor(@NonNull final Handler handler,
+ @NonNull final SharedLog log,
+ @NonNull final NetLinkMonitorCallBack cb) {
+ return SocketNetLinkMonitorFactory.createNetLinkMonitor(handler, log, cb);
+ }
+ }
+ /**
+ * The callback interface for the netlink monitor messages.
+ */
+ public interface NetLinkMonitorCallBack {
+ /**
+ * Handles the interface address add or update.
+ */
+ void addOrUpdateInterfaceAddress(int ifaceIdx, @NonNull LinkAddress newAddress);
+
+
+ /**
+ * Handles the interface address delete.
+ */
+ void deleteInterfaceAddress(int ifaceIdx, @NonNull LinkAddress deleteAddress);
+ }
+ private class NetLinkMessageProcessor implements NetLinkMonitorCallBack {
+
+ @Override
+ public void addOrUpdateInterfaceAddress(int ifaceIdx,
+ @NonNull final LinkAddress newAddress) {
+
+ LinkProperties linkProperties;
+ linkProperties = mIfaceIdxToLinkProperties.get(ifaceIdx);
+ if (linkProperties == null) {
+ linkProperties = new LinkProperties();
+ mIfaceIdxToLinkProperties.put(ifaceIdx, linkProperties);
+ }
+ boolean updated = linkProperties.addLinkAddress(newAddress);
+
+ if (!updated) {
+ return;
+ }
+ maybeUpdateTetheringSocketAddress(ifaceIdx, linkProperties.getLinkAddresses());
+ }
+
+ @Override
+ public void deleteInterfaceAddress(int ifaceIdx, @NonNull LinkAddress deleteAddress) {
+ LinkProperties linkProperties;
+ boolean updated = false;
+ linkProperties = mIfaceIdxToLinkProperties.get(ifaceIdx);
+ if (linkProperties != null) {
+ updated = linkProperties.removeLinkAddress(deleteAddress);
+ if (linkProperties.getLinkAddresses().isEmpty()) {
+ mIfaceIdxToLinkProperties.remove(ifaceIdx);
+ }
+ }
+
+ if (linkProperties == null || !updated) {
+ return;
+ }
+ maybeUpdateTetheringSocketAddress(ifaceIdx, linkProperties.getLinkAddresses());
+
+ }
+ }
/*** Data class for storing socket related info */
private static class SocketInfo {
final MdnsInterfaceSocket mSocket;
@@ -156,18 +242,6 @@
}
}
- private static class SocketNetlinkMonitor extends NetlinkMonitor {
- SocketNetlinkMonitor(Handler handler) {
- super(handler, LOGGER.mLog, TAG, OsConstants.NETLINK_ROUTE,
- NetlinkConstants.RTMGRP_IPV4_IFADDR | NetlinkConstants.RTMGRP_IPV6_IFADDR);
- }
-
- @Override
- public void processNetlinkMessage(NetlinkMessage nlMsg, long whenMs) {
- // TODO: Handle netlink message.
- }
- }
-
/*** Ensure that current running thread is same as given handler thread */
public static void ensureRunningOnHandlerThread(Handler handler) {
if (handler.getLooper().getThread() != Thread.currentThread()) {
@@ -179,6 +253,7 @@
/*** Start monitoring sockets by listening callbacks for sockets creation or removal */
public void startMonitoringSockets() {
ensureRunningOnHandlerThread(mHandler);
+ mRequestStop = false; // Reset stop request flag.
if (mMonitoringSockets) {
Log.d(TAG, "Already monitoring sockets.");
return;
@@ -191,31 +266,60 @@
final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
tetheringManager.registerTetheringEventCallback(mHandler::post, mTetheringEventCallback);
- mHandler.post(mNetlinkMonitor::start);
+ if (mSocketNetlinkMonitor.isSupported()) {
+ mHandler.post(mSocketNetlinkMonitor::startMonitoring);
+ }
mMonitoringSockets = true;
}
+ /**
+ * Start netlink monitor.
+ */
+ public void startNetLinkMonitor() {
+ ensureRunningOnHandlerThread(mHandler);
+ if (mSocketNetlinkMonitor.isSupported()) {
+ mSocketNetlinkMonitor.startMonitoring();
+ }
+ }
- /*** Stop monitoring sockets and unregister callbacks */
- public void stopMonitoringSockets() {
+ private void maybeStopMonitoringSockets() {
+ if (!mMonitoringSockets) return; // Already unregistered.
+ if (!mRequestStop) return; // No stop request.
+
+ // Only unregister the network callback if there is no socket request.
+ if (mCallbacksToRequestedNetworks.isEmpty()) {
+ mContext.getSystemService(ConnectivityManager.class)
+ .unregisterNetworkCallback(mNetworkCallback);
+
+ final TetheringManager tetheringManager = mContext.getSystemService(
+ TetheringManager.class);
+ tetheringManager.unregisterTetheringEventCallback(mTetheringEventCallback);
+ // Clear all saved status.
+ mActiveNetworksLinkProperties.clear();
+ mNetworkSockets.clear();
+ mTetherInterfaceSockets.clear();
+ mLocalOnlyInterfaces.clear();
+ mTetheredInterfaces.clear();
+ mMonitoringSockets = false;
+ }
+ // The netlink monitor is not stopped here because the MdnsSocketProvider need to listen
+ // to all the netlink updates when the system is up and running.
+ }
+
+ /*** Request to stop monitoring sockets and unregister callbacks */
+ public void requestStopWhenInactive() {
ensureRunningOnHandlerThread(mHandler);
if (!mMonitoringSockets) {
Log.d(TAG, "Monitoring sockets hasn't been started.");
return;
}
- if (DBG) Log.d(TAG, "Stop monitoring sockets.");
- mContext.getSystemService(ConnectivityManager.class)
- .unregisterNetworkCallback(mNetworkCallback);
-
- final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
- tetheringManager.unregisterTetheringEventCallback(mTetheringEventCallback);
-
- mHandler.post(mNetlinkMonitor::stop);
- mMonitoringSockets = false;
+ if (DBG) Log.d(TAG, "Try to stop monitoring sockets.");
+ mRequestStop = true;
+ maybeStopMonitoringSockets();
}
/*** Check whether the target network is matched current network */
public static boolean isNetworkMatched(@Nullable Network targetNetwork,
- @NonNull Network currentNetwork) {
+ @Nullable Network currentNetwork) {
return targetNetwork == null || targetNetwork.equals(currentNetwork);
}
@@ -238,25 +342,43 @@
return;
}
+ final NetworkAsKey networkKey = new NetworkAsKey(network);
final SocketInfo socketInfo = mNetworkSockets.get(network);
if (socketInfo == null) {
- createSocket(network, lp);
+ createSocket(networkKey, lp);
} else {
- // Update the addresses of this socket.
- final List<LinkAddress> addresses = lp.getLinkAddresses();
- socketInfo.mAddresses.clear();
- socketInfo.mAddresses.addAll(addresses);
- // Try to join the group again.
- socketInfo.mSocket.joinGroup(addresses);
-
- notifyAddressesChanged(network, socketInfo.mSocket, lp);
+ updateSocketInfoAddress(network, socketInfo, lp.getLinkAddresses());
+ }
+ }
+ private void maybeUpdateTetheringSocketAddress(int ifaceIndex,
+ @NonNull final List<LinkAddress> updatedAddresses) {
+ for (int i = 0; i < mTetherInterfaceSockets.size(); ++i) {
+ String tetheringInterfaceName = mTetherInterfaceSockets.keyAt(i);
+ if (mDependencies.getNetworkInterfaceIndexByName(tetheringInterfaceName)
+ == ifaceIndex) {
+ updateSocketInfoAddress(null /* network */,
+ mTetherInterfaceSockets.valueAt(i), updatedAddresses);
+ return;
+ }
}
}
- private static LinkProperties createLPForTetheredInterface(String interfaceName) {
- final LinkProperties linkProperties = new LinkProperties();
+ private void updateSocketInfoAddress(@Nullable final Network network,
+ @NonNull final SocketInfo socketInfo,
+ @NonNull final List<LinkAddress> addresses) {
+ // Update the addresses of this socket.
+ socketInfo.mAddresses.clear();
+ socketInfo.mAddresses.addAll(addresses);
+ // Try to join the group again.
+ socketInfo.mSocket.joinGroup(addresses);
+
+ notifyAddressesChanged(network, socketInfo.mSocket, addresses);
+ }
+ private LinkProperties createLPForTetheredInterface(@NonNull final String interfaceName,
+ int ifaceIndex) {
+ final LinkProperties linkProperties =
+ new LinkProperties(mIfaceIdxToLinkProperties.get(ifaceIndex));
linkProperties.setInterfaceName(interfaceName);
- // TODO: Use NetlinkMonitor to update addresses for tethering interfaces.
return linkProperties;
}
@@ -275,16 +397,17 @@
final CompareResult<String> interfaceDiff = new CompareResult<>(
current, updated);
for (String name : interfaceDiff.added) {
- createSocket(new Network(INetd.LOCAL_NET_ID), createLPForTetheredInterface(name));
+ int ifaceIndex = mDependencies.getNetworkInterfaceIndexByName(name);
+ createSocket(LOCAL_NET, createLPForTetheredInterface(name, ifaceIndex));
}
for (String name : interfaceDiff.removed) {
- removeSocket(new Network(INetd.LOCAL_NET_ID), name);
+ removeTetherInterfaceSocket(name);
}
current.clear();
current.addAll(updated);
}
- private void createSocket(Network network, LinkProperties lp) {
+ private void createSocket(NetworkKey networkKey, LinkProperties lp) {
final String interfaceName = lp.getInterfaceName();
if (interfaceName == null) {
Log.e(TAG, "Can not create socket with null interface name.");
@@ -294,46 +417,93 @@
try {
final NetworkInterfaceWrapper networkInterface =
mDependencies.getNetworkInterfaceByName(interfaceName);
- if (networkInterface == null || !mDependencies.canScanOnInterface(networkInterface)) {
+ // There are no transports for tethered interfaces. Other interfaces should always
+ // have transports since LinkProperties updates are always sent after
+ // NetworkCapabilities updates.
+ final int[] transports;
+ if (networkKey == LOCAL_NET) {
+ transports = new int[0];
+ } else {
+ transports = mActiveNetworksTransports.getOrDefault(
+ ((NetworkAsKey) networkKey).mNetwork, new int[0]);
+ }
+ if (networkInterface == null || !isMdnsCapableInterface(networkInterface, transports)) {
return;
}
if (DBG) {
- Log.d(TAG, "Create a socket on network:" + network
+ Log.d(TAG, "Create a socket on network:" + networkKey
+ " with interfaceName:" + interfaceName);
}
final MdnsInterfaceSocket socket = mDependencies.createMdnsInterfaceSocket(
networkInterface.getNetworkInterface(), MdnsConstants.MDNS_PORT, mLooper,
mPacketReadBuffer);
- final List<LinkAddress> addresses;
- if (network.netId == INetd.LOCAL_NET_ID) {
- addresses = CollectionUtils.map(
- networkInterface.getInterfaceAddresses(), LinkAddress::new);
+ final List<LinkAddress> addresses = lp.getLinkAddresses();
+ if (networkKey == LOCAL_NET) {
mTetherInterfaceSockets.put(interfaceName, new SocketInfo(socket, addresses));
} else {
- addresses = lp.getLinkAddresses();
- mNetworkSockets.put(network, new SocketInfo(socket, addresses));
+ mNetworkSockets.put(((NetworkAsKey) networkKey).mNetwork,
+ new SocketInfo(socket, addresses));
}
// Try to join IPv4/IPv6 group.
socket.joinGroup(addresses);
// Notify the listeners which need this socket.
- notifySocketCreated(network, socket, addresses);
+ if (networkKey == LOCAL_NET) {
+ notifySocketCreated(null /* network */, socket, addresses);
+ } else {
+ notifySocketCreated(((NetworkAsKey) networkKey).mNetwork, socket, addresses);
+ }
} catch (IOException e) {
Log.e(TAG, "Create a socket failed with interface=" + interfaceName, e);
}
}
- private void removeSocket(Network network, String interfaceName) {
- final SocketInfo socketInfo = network.netId == INetd.LOCAL_NET_ID
- ? mTetherInterfaceSockets.remove(interfaceName)
- : mNetworkSockets.remove(network);
+ private boolean isMdnsCapableInterface(
+ @NonNull NetworkInterfaceWrapper iface, @NonNull int[] transports) {
+ try {
+ // Never try mDNS on cellular, or on interfaces with incompatible flags
+ if (CollectionUtils.contains(transports, TRANSPORT_CELLULAR)
+ || iface.isLoopback()
+ || iface.isPointToPoint()
+ || iface.isVirtual()
+ || !iface.isUp()) {
+ return false;
+ }
+
+ // Otherwise, always try mDNS on non-VPN Wifi.
+ if (!CollectionUtils.contains(transports, TRANSPORT_VPN)
+ && CollectionUtils.contains(transports, TRANSPORT_WIFI)) {
+ return true;
+ }
+
+ // For other transports, or no transports (tethering downstreams), do mDNS based on the
+ // interface flags. This is not always reliable (for example some Wifi interfaces may
+ // not have the MULTICAST flag even though they can do mDNS, and some cellular
+ // interfaces may have the BROADCAST or MULTICAST flags), so checks are done based on
+ // transports above in priority.
+ return iface.supportsMulticast();
+ } catch (SocketException e) {
+ Log.e(TAG, "Error checking interface flags", e);
+ return false;
+ }
+ }
+
+ private void removeNetworkSocket(Network network) {
+ final SocketInfo socketInfo = mNetworkSockets.remove(network);
if (socketInfo == null) return;
socketInfo.mSocket.destroy();
notifyInterfaceDestroyed(network, socketInfo.mSocket);
}
+ private void removeTetherInterfaceSocket(String interfaceName) {
+ final SocketInfo socketInfo = mTetherInterfaceSockets.remove(interfaceName);
+ if (socketInfo == null) return;
+ socketInfo.mSocket.destroy();
+ notifyInterfaceDestroyed(null /* network */, socketInfo.mSocket);
+ }
+
private void notifySocketCreated(Network network, MdnsInterfaceSocket socket,
List<LinkAddress> addresses) {
for (int i = 0; i < mCallbacksToRequestedNetworks.size(); i++) {
@@ -354,12 +524,12 @@
}
private void notifyAddressesChanged(Network network, MdnsInterfaceSocket socket,
- LinkProperties lp) {
+ List<LinkAddress> addresses) {
for (int i = 0; i < mCallbacksToRequestedNetworks.size(); i++) {
final Network requestedNetwork = mCallbacksToRequestedNetworks.valueAt(i);
if (isNetworkMatched(requestedNetwork, network)) {
mCallbacksToRequestedNetworks.keyAt(i)
- .onAddressesChanged(network, socket, lp.getLinkAddresses());
+ .onAddressesChanged(network, socket, addresses);
}
}
}
@@ -373,7 +543,7 @@
if (DBG) Log.d(TAG, "There is no LinkProperties for this network:" + network);
return;
}
- createSocket(network, lp);
+ createSocket(new NetworkAsKey(network), lp);
} else {
// Notify the socket for requested network.
cb.onSocketCreated(network, socketInfo.mSocket, socketInfo.mAddresses);
@@ -383,12 +553,14 @@
private void retrieveAndNotifySocketFromInterface(String interfaceName, SocketCallback cb) {
final SocketInfo socketInfo = mTetherInterfaceSockets.get(interfaceName);
if (socketInfo == null) {
+ int ifaceIndex = mDependencies.getNetworkInterfaceIndexByName(interfaceName);
createSocket(
- new Network(INetd.LOCAL_NET_ID), createLPForTetheredInterface(interfaceName));
+ LOCAL_NET,
+ createLPForTetheredInterface(interfaceName, ifaceIndex));
} else {
// Notify the socket for requested network.
cb.onSocketCreated(
- new Network(INetd.LOCAL_NET_ID), socketInfo.mSocket, socketInfo.mAddresses);
+ null /* network */, socketInfo.mSocket, socketInfo.mAddresses);
}
}
@@ -447,21 +619,60 @@
final SocketInfo info = mTetherInterfaceSockets.valueAt(i);
info.mSocket.destroy();
// Still notify to unrequester for socket destroy.
- cb.onInterfaceDestroyed(new Network(INetd.LOCAL_NET_ID), info.mSocket);
+ cb.onInterfaceDestroyed(null /* network */, info.mSocket);
}
mTetherInterfaceSockets.clear();
+
+ // Try to unregister network callback.
+ maybeStopMonitoringSockets();
}
/*** Callbacks for listening socket changes */
public interface SocketCallback {
/*** Notify the socket is created */
- default void onSocketCreated(@NonNull Network network, @NonNull MdnsInterfaceSocket socket,
+ default void onSocketCreated(@Nullable Network network, @NonNull MdnsInterfaceSocket socket,
@NonNull List<LinkAddress> addresses) {}
/*** Notify the interface is destroyed */
- default void onInterfaceDestroyed(@NonNull Network network,
+ default void onInterfaceDestroyed(@Nullable Network network,
@NonNull MdnsInterfaceSocket socket) {}
/*** Notify the addresses is changed on the network */
- default void onAddressesChanged(@NonNull Network network,
+ default void onAddressesChanged(@Nullable Network network,
@NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> addresses) {}
}
+
+ private interface NetworkKey {
+ }
+
+ private static final NetworkKey LOCAL_NET = new NetworkKey() {
+ @Override
+ public String toString() {
+ return "NetworkKey:LOCAL_NET";
+ }
+ };
+
+ private static class NetworkAsKey implements NetworkKey {
+ private final Network mNetwork;
+
+ NetworkAsKey(Network network) {
+ this.mNetwork = network;
+ }
+
+ @Override
+ public int hashCode() {
+ return mNetwork.hashCode();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof NetworkAsKey)) {
+ return false;
+ }
+ return mNetwork.equals(((NetworkAsKey) other).mNetwork);
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkAsKey{ network=" + mNetwork + " }";
+ }
+ }
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MulticastNetworkInterfaceProvider.java b/service-t/src/com/android/server/connectivity/mdns/MulticastNetworkInterfaceProvider.java
index ade7b95..f248c98 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MulticastNetworkInterfaceProvider.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MulticastNetworkInterfaceProvider.java
@@ -148,7 +148,7 @@
}
/*** Check whether given network interface can support mdns */
- public static boolean canScanOnInterface(@Nullable NetworkInterfaceWrapper networkInterface) {
+ private static boolean canScanOnInterface(@Nullable NetworkInterfaceWrapper networkInterface) {
try {
if ((networkInterface == null)
|| networkInterface.isLoopback()
diff --git a/service-t/src/com/android/server/connectivity/mdns/MulticastPacketReader.java b/service-t/src/com/android/server/connectivity/mdns/MulticastPacketReader.java
index b597f0a..078c4dd 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MulticastPacketReader.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MulticastPacketReader.java
@@ -59,11 +59,12 @@
* Create a new {@link MulticastPacketReader}.
* @param socket Socket to read from. This will *not* be closed when the reader terminates.
* @param buffer Buffer to read packets into. Will only be used from the handler thread.
+ * @param port the port number for the socket
*/
protected MulticastPacketReader(@NonNull String interfaceTag,
@NonNull ParcelFileDescriptor socket, @NonNull Handler handler,
- @NonNull byte[] buffer) {
- super(handler, new RecvBuffer(buffer, new InetSocketAddress()));
+ @NonNull byte[] buffer, int port) {
+ super(handler, new RecvBuffer(buffer, new InetSocketAddress(port)));
mLogTag = MulticastPacketReader.class.getSimpleName() + "/" + interfaceTag;
mSocket = socket;
mHandler = handler;
diff --git a/service-t/src/com/android/server/connectivity/mdns/SocketNetLinkMonitorFactory.java b/service-t/src/com/android/server/connectivity/mdns/SocketNetLinkMonitorFactory.java
new file mode 100644
index 0000000..4650255
--- /dev/null
+++ b/service-t/src/com/android/server/connectivity/mdns/SocketNetLinkMonitorFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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.server.connectivity.mdns;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+
+import com.android.net.module.util.SharedLog;
+import com.android.server.connectivity.mdns.internal.SocketNetlinkMonitor;
+
+/**
+ * The factory class for creating the netlink monitor.
+ */
+public class SocketNetLinkMonitorFactory {
+
+ /**
+ * Creates a new netlink monitor.
+ */
+ public static ISocketNetLinkMonitor createNetLinkMonitor(@NonNull final Handler handler,
+ @NonNull SharedLog log, @NonNull MdnsSocketProvider.NetLinkMonitorCallBack cb) {
+ return new SocketNetlinkMonitor(handler, log, cb);
+ }
+
+ private SocketNetLinkMonitorFactory() {
+ }
+
+}
diff --git a/service-t/src/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitor.java b/service-t/src/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitor.java
new file mode 100644
index 0000000..6395b53
--- /dev/null
+++ b/service-t/src/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitor.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 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.server.connectivity.mdns.internal;
+
+import android.annotation.NonNull;
+import android.net.LinkAddress;
+import android.os.Handler;
+import android.system.OsConstants;
+import android.util.Log;
+
+import com.android.net.module.util.SharedLog;
+import com.android.net.module.util.ip.NetlinkMonitor;
+import com.android.net.module.util.netlink.NetlinkConstants;
+import com.android.net.module.util.netlink.NetlinkMessage;
+import com.android.net.module.util.netlink.RtNetlinkAddressMessage;
+import com.android.net.module.util.netlink.StructIfaddrMsg;
+import com.android.server.connectivity.mdns.ISocketNetLinkMonitor;
+import com.android.server.connectivity.mdns.MdnsSocketProvider;
+
+/**
+ * The netlink monitor for MdnsSocketProvider.
+ */
+public class SocketNetlinkMonitor extends NetlinkMonitor implements ISocketNetLinkMonitor {
+
+ public static final String TAG = SocketNetlinkMonitor.class.getSimpleName();
+
+ @NonNull
+ private final MdnsSocketProvider.NetLinkMonitorCallBack mCb;
+ public SocketNetlinkMonitor(@NonNull final Handler handler,
+ @NonNull SharedLog log,
+ @NonNull final MdnsSocketProvider.NetLinkMonitorCallBack cb) {
+ super(handler, log, TAG, OsConstants.NETLINK_ROUTE,
+ NetlinkConstants.RTMGRP_IPV4_IFADDR | NetlinkConstants.RTMGRP_IPV6_IFADDR);
+ mCb = cb;
+ }
+ @Override
+ public void processNetlinkMessage(NetlinkMessage nlMsg, long whenMs) {
+ if (nlMsg instanceof RtNetlinkAddressMessage) {
+ processRtNetlinkAddressMessage((RtNetlinkAddressMessage) nlMsg);
+ }
+ }
+
+ /**
+ * Process the RTM_NEWADDR and RTM_DELADDR netlink message.
+ */
+ private void processRtNetlinkAddressMessage(RtNetlinkAddressMessage msg) {
+ final StructIfaddrMsg ifaddrMsg = msg.getIfaddrHeader();
+ final LinkAddress la = new LinkAddress(msg.getIpAddress(), ifaddrMsg.prefixLen,
+ msg.getFlags(), ifaddrMsg.scope);
+ if (!la.isPreferred()) {
+ // Skip the unusable ip address.
+ return;
+ }
+ switch (msg.getHeader().nlmsg_type) {
+ case NetlinkConstants.RTM_NEWADDR:
+ mCb.addOrUpdateInterfaceAddress(ifaddrMsg.index, la);
+ break;
+ case NetlinkConstants.RTM_DELADDR:
+ mCb.deleteInterfaceAddress(ifaddrMsg.index, la);
+ break;
+ default:
+ Log.e(TAG, "Unknown rtnetlink address msg type " + msg.getHeader().nlmsg_type);
+ }
+ }
+
+ @Override
+ public boolean isSupported() {
+ return true;
+ }
+
+ @Override
+ public void startMonitoring() {
+ this.start();
+ }
+
+ @Override
+ public void stopMonitoring() {
+ this.stop();
+ }
+}
diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
index 51683de..eed9aeb 100644
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -469,9 +469,7 @@
// TODO: Update this logic to only do a restart if required. Although a restart may
// be required due to the capabilities or ipConfiguration values, not all
// capabilities changes require a restart.
- if (mIpClient != null) {
- restart();
- }
+ maybeRestart();
}
boolean isRestricted() {
@@ -549,7 +547,7 @@
// Send a callback in case a provisioning request was in progress.
return;
}
- restart();
+ maybeRestart();
}
private void ensureRunningOnEthernetHandlerThread() {
@@ -582,7 +580,7 @@
// If there is a better network, that will become default and apps
// will be able to use internet. If ethernet gets connected again,
// and has backhaul connectivity, it will become default.
- restart();
+ maybeRestart();
}
/** Returns true if state has been modified */
@@ -656,8 +654,16 @@
.build();
}
- void restart() {
- if (DBG) Log.d(TAG, "reconnecting Ethernet");
+ void maybeRestart() {
+ if (mIpClient == null) {
+ // If maybeRestart() is called from a provisioning failure, it is
+ // possible that link disappeared in the meantime. In that
+ // case, stop() has already been called and IpClient should not
+ // get restarted to prevent a provisioning failure loop.
+ Log.i(TAG, String.format("maybeRestart() called on stopped interface %s", name));
+ return;
+ }
+ if (DBG) Log.d(TAG, "restart IpClient");
stop();
start();
}
diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
index f6a55c8..e7af569 100644
--- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
+++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
@@ -92,7 +92,7 @@
@Override
public String[] getAvailableInterfaces() throws RemoteException {
PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
- return mTracker.getInterfaces(checkUseRestrictedNetworksPermission());
+ return mTracker.getClientModeInterfaces(checkUseRestrictedNetworksPermission());
}
/**
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index 852cf42..d520757 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -385,7 +385,7 @@
return mFactory.hasInterface(iface);
}
- String[] getInterfaces(boolean includeRestricted) {
+ String[] getClientModeInterfaces(boolean includeRestricted) {
return mFactory.getAvailableInterfaces(includeRestricted);
}
@@ -428,9 +428,12 @@
// Remote process has already died
return;
}
- for (String iface : getInterfaces(canUseRestrictedNetworks)) {
+ for (String iface : getClientModeInterfaces(canUseRestrictedNetworks)) {
unicastInterfaceStateChange(listener, iface);
}
+ if (mTetheringInterfaceMode == INTERFACE_MODE_SERVER) {
+ unicastInterfaceStateChange(listener, mTetheringInterface);
+ }
unicastEthernetStateChange(listener, mEthernetState);
});
diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java
index e0abdf1..5f66f47 100644
--- a/service-t/src/com/android/server/net/NetworkStatsFactory.java
+++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java
@@ -34,8 +34,6 @@
import java.io.IOException;
import java.net.ProtocolException;
-import java.util.Arrays;
-import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -86,12 +84,9 @@
* are expected to monotonically increase since device boot.
*/
@NonNull
- public NetworkStats getNetworkStatsDetail(int limitUid, @Nullable String[] limitIfaces,
- int limitTag) throws IOException {
+ public NetworkStats getNetworkStatsDetail() throws IOException {
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
- // TODO: remove both path and useBpfStats arguments.
- // The path is never used if useBpfStats is true.
- final int ret = nativeReadNetworkStatsDetail(stats, limitUid, limitIfaces, limitTag);
+ final int ret = nativeReadNetworkStatsDetail(stats);
if (ret != 0) {
throw new IOException("Failed to parse network stats");
}
@@ -147,36 +142,6 @@
}
/**
- * Get a set of interfaces containing specified ifaces and stacked interfaces.
- *
- * <p>The added stacked interfaces are ifaces stacked on top of the specified ones, or ifaces
- * on which the specified ones are stacked. Stacked interfaces are those noted with
- * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method
- * is called are guaranteed to be included.
- */
- public String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) {
- if (requiredIfaces == NetworkStats.INTERFACES_ALL) {
- return null;
- }
-
- HashSet<String> relatedIfaces = new HashSet<>(Arrays.asList(requiredIfaces));
- // ConcurrentHashMap's EntrySet iterators are "guaranteed to traverse
- // elements as they existed upon construction exactly once, and may
- // (but are not guaranteed to) reflect any modifications subsequent to construction".
- // This is enough here.
- for (Map.Entry<String, String> entry : mStackedIfaces.entrySet()) {
- if (relatedIfaces.contains(entry.getKey())) {
- relatedIfaces.add(entry.getValue());
- } else if (relatedIfaces.contains(entry.getValue())) {
- relatedIfaces.add(entry.getKey());
- }
- }
-
- String[] outArray = new String[relatedIfaces.size()];
- return relatedIfaces.toArray(outArray);
- }
-
- /**
* Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}.
* @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map)
*/
@@ -245,8 +210,7 @@
requestSwapActiveStatsMapLocked();
// Stats are always read from the inactive map, so they must be read after the
// swap
- final NetworkStats stats = mDeps.getNetworkStatsDetail(
- UID_ALL, INTERFACES_ALL, TAG_ALL);
+ final NetworkStats stats = mDeps.getNetworkStatsDetail();
// BPF stats are incremental; fold into mPersistSnapshot.
mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime());
mPersistSnapshot.combineAllValues(stats);
@@ -333,8 +297,7 @@
* are expected to monotonically increase since device boot.
*/
@VisibleForTesting
- public static native int nativeReadNetworkStatsDetail(NetworkStats stats, int limitUid,
- String[] limitIfaces, int limitTag);
+ public static native int nativeReadNetworkStatsDetail(NetworkStats stats);
@VisibleForTesting
public static native int nativeReadNetworkStatsDev(NetworkStats stats);
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 1606fd0..961337d 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -106,6 +106,7 @@
import android.net.TetherStatsParcel;
import android.net.TetheringManager;
import android.net.TrafficStats;
+import android.net.TransportInfo;
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
import android.net.netstats.IUsageCallback;
@@ -113,6 +114,7 @@
import android.net.netstats.provider.INetworkStatsProvider;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
+import android.net.wifi.WifiInfo;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -537,7 +539,8 @@
BroadcastOptions.makeBasic())
.setDeliveryGroupPolicy(
ConstantsShim.DELIVERY_GROUP_POLICY_MOST_RECENT)
- .setDeferUntilActive(true)
+ .setDeferralPolicy(
+ ConstantsShim.DEFERRAL_POLICY_UNTIL_ACTIVE)
.toBundle();
} catch (UnsupportedApiLevelException e) {
Log.wtf(TAG, "Using unsupported API" + e);
@@ -1729,11 +1732,7 @@
PermissionUtils.enforceNetworkStackPermission(mContext);
try {
final String[] ifaceArray = getAllIfacesSinceBoot(transport);
- // TODO(b/215633405) : mMobileIfaces and mWifiIfaces already contain the stacked
- // interfaces, so this is not useful, remove it.
- final String[] ifacesToQuery =
- mStatsFactory.augmentWithStackedInterfaces(ifaceArray);
- final NetworkStats stats = getNetworkStatsUidDetail(ifacesToQuery);
+ final NetworkStats stats = getNetworkStatsUidDetail(ifaceArray);
// Clear the interfaces of the stats before returning, so callers won't get this
// information. This is because no caller needs this information for now, and it
// makes it easier to change the implementation later by using the histories in the
@@ -2125,6 +2124,14 @@
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
isDefault, ratType);
+ // If WifiInfo contains a null network key then this identity should not be added into
+ // the network identity set. See b/266598304.
+ final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
+ .getTransportInfo();
+ if (transportInfo instanceof WifiInfo) {
+ final WifiInfo info = (WifiInfo) transportInfo;
+ if (info.getNetworkKey() == null) continue;
+ }
// Traffic occurring on the base interface is always counted for
// both total usage and UID details.
final String baseIface = snapshot.getLinkProperties().getInterfaceName();
@@ -2423,20 +2430,41 @@
xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
- EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
- xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
- uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- currentTime);
+ if (SdkLevel.isAtLeastU()) {
+ EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
+ xtTotal.rxBytes, xtTotal.txBytes, xtTotal.rxPackets, xtTotal.txPackets,
+ uidTotal.rxBytes, uidTotal.txBytes, uidTotal.rxPackets, uidTotal.txPackets,
+ currentTime);
+ } else {
+ // To keep the format of event log, here replaces the value of DevRecorder with the
+ // value of XtRecorder because they have the same content in old design.
+ EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
+ xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+ xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+ uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
+ currentTime);
+ }
// collect wifi sample
template = new NetworkTemplate.Builder(MATCH_WIFI).build();
xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
- EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
- xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
- uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
- currentTime);
+ if (SdkLevel.isAtLeastU()) {
+ EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
+ xtTotal.rxBytes, xtTotal.txBytes, xtTotal.rxPackets, xtTotal.txPackets,
+ uidTotal.rxBytes, uidTotal.txBytes, uidTotal.rxPackets, uidTotal.txPackets,
+ currentTime);
+ } else {
+ // To keep the format of event log, here replaces the value of DevRecorder with the
+ // value of XtRecorder because they have the same content in old design.
+ EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
+ xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+ xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
+ uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
+ currentTime);
+
+ }
}
// deleteKernelTagData can ignore ENOENT; otherwise we should log an error
diff --git a/service/Android.bp b/service/Android.bp
index c8d2fdd..e1376a1 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -138,6 +138,14 @@
name: "service-connectivity-pre-jarjar",
sdk_version: "system_server_current",
min_sdk_version: "30",
+ // NetworkStackApiShimSettingsForCurrentBranch provides the latest available shims depending on
+ // the branch to "service-connectivity".
+ // There are Tethering.apk and TetheringNext.apk variants for the tethering APEX,
+ // which use NetworkStackApiStableShims and NetworkStackApiCurrentShims respectively.
+ // Note that there can be no service-connectivity-next because it would need to be configured in
+ // default_art_config.mk which doesn't support conditionals, hence this scheme of using a
+ // variable here.
+ defaults: ["NetworkStackApiShimSettingsForCurrentBranch"],
srcs: [
"src/**/*.java",
":framework-connectivity-shared-srcs",
@@ -171,7 +179,7 @@
"androidx.annotation_annotation",
"connectivity-net-module-utils-bpf",
"connectivity_native_aidl_interface-lateststable-java",
- "dnsresolver_aidl_interface-V9-java",
+ "dnsresolver_aidl_interface-V11-java",
"modules-utils-shell-command-handler",
"net-utils-device-common",
"net-utils-device-common-bpf",
@@ -183,7 +191,6 @@
"PlatformProperties",
"service-connectivity-protos",
"service-connectivity-stats-protos",
- "NetworkStackApiStableShims",
],
apex_available: [
"com.android.tethering",
diff --git a/service/ServiceConnectivityResources/res/values-eu/strings.xml b/service/ServiceConnectivityResources/res/values-eu/strings.xml
index 9b39fd3..13f9eb4 100644
--- a/service/ServiceConnectivityResources/res/values-eu/strings.xml
+++ b/service/ServiceConnectivityResources/res/values-eu/strings.xml
@@ -36,7 +36,7 @@
<item msgid="3004933964374161223">"datu-konexioa"</item>
<item msgid="5624324321165953608">"Wifia"</item>
<item msgid="5667906231066981731">"Bluetootha"</item>
- <item msgid="346574747471703768">"Ethernet-a"</item>
+ <item msgid="346574747471703768">"Etherneta"</item>
<item msgid="5734728378097476003">"VPNa"</item>
</string-array>
<string name="network_switch_type_name_unknown" msgid="5116448402191972082">"sare mota ezezaguna"</string>
diff --git a/service/ServiceConnectivityResources/res/values-mcc310-mnc590/config.xml b/service/ServiceConnectivityResources/res/values-mcc310-mnc590/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc310-mnc590/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc310-mnc599/config.xml b/service/ServiceConnectivityResources/res/values-mcc310-mnc599/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc310-mnc599/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc270/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc270/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc311-mnc270/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc280/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc280/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc311-mnc280/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml
deleted file mode 100644
index 7e7025f..0000000
--- a/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<!-- Configuration values for ConnectivityService
- DO NOT EDIT THIS FILE for specific device configuration; instead, use a Runtime Resources
- Overlay package following the overlayable.xml configuration in the same directory:
- https://source.android.com/devices/architecture/rros -->
-<resources>
- <!-- Whether the device should automatically switch away from Wi-Fi networks that lose
- Internet access. Actual device behaviour is controlled by
- Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. -->
- <integer translatable="false" name="config_networkAvoidBadWifi">0</integer>
-</resources>
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml
new file mode 120000
index 0000000..2b8e406
--- /dev/null
+++ b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml
@@ -0,0 +1 @@
+../values-mcc310-mnc004/config.xml
\ No newline at end of file
diff --git a/service/jarjar-excludes.txt b/service/jarjar-excludes.txt
index b0d6763..7bd3862 100644
--- a/service/jarjar-excludes.txt
+++ b/service/jarjar-excludes.txt
@@ -1,9 +1,3 @@
# Classes loaded by SystemServer via their hardcoded name, so they can't be jarjared
com\.android\.server\.ConnectivityServiceInitializer(\$.+)?
com\.android\.server\.NetworkStatsServiceInitializer(\$.+)?
-
-# Do not jarjar com.android.server, as several unit tests fail because they lose
-# package-private visibility between jarjared and non-jarjared classes.
-# TODO: fix the tests and also jarjar com.android.server, or at least only exclude a package that
-# is specific to the module like com.android.server.connectivity
-com\.android\.server\..+
diff --git a/service/jni/com_android_server_BpfNetMaps.cpp b/service/jni/com_android_server_BpfNetMaps.cpp
index 05f50b0..77cffda 100644
--- a/service/jni/com_android_server_BpfNetMaps.cpp
+++ b/service/jni/com_android_server_BpfNetMaps.cpp
@@ -236,7 +236,7 @@
// clang-format on
int register_com_android_server_BpfNetMaps(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "com/android/server/BpfNetMaps",
+ return jniRegisterNativeMethods(env, "android/net/connectivity/com/android/server/BpfNetMaps",
gMethods, NELEM(gMethods));
}
diff --git a/service/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp
index f925732..3e4c4de 100644
--- a/service/jni/com_android_server_TestNetworkService.cpp
+++ b/service/jni/com_android_server_TestNetworkService.cpp
@@ -160,8 +160,9 @@
};
int register_com_android_server_TestNetworkService(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "com/android/server/TestNetworkService", gMethods,
- NELEM(gMethods));
+ return jniRegisterNativeMethods(env,
+ "android/net/connectivity/com/android/server/TestNetworkService", gMethods,
+ NELEM(gMethods));
}
}; // namespace android
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index 7060958..059b716 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -26,9 +26,14 @@
#include <nativehelper/JNIHelp.h>
#include <net/if.h>
#include <spawn.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/xattr.h>
#include <string>
+#include <unistd.h>
+#include <android-modules-utils/sdk_level.h>
#include <bpf/BpfMap.h>
#include <bpf/BpfUtils.h>
#include <netjniutils/netjniutils.h>
@@ -45,14 +50,110 @@
#define DEVICEPREFIX "v4-"
namespace android {
-static const char* kClatdPath = "/apex/com.android.tethering/bin/for-system/clatd";
+
+static bool fatal = false;
+
+#define ALOGF(s ...) do { ALOGE(s); fatal = true; } while(0)
+
+enum verify { VERIFY_DIR, VERIFY_BIN, VERIFY_PROG, VERIFY_MAP_RO, VERIFY_MAP_RW };
+
+static void verifyPerms(const char * const path,
+ const mode_t mode, const uid_t uid, const gid_t gid,
+ const char * const ctxt,
+ const verify vtype) {
+ struct stat s = {};
+
+ if (lstat(path, &s)) ALOGF("lstat '%s' errno=%d", path, errno);
+ if (s.st_mode != mode) ALOGF("'%s' mode is 0%o != 0%o", path, s.st_mode, mode);
+ if (s.st_uid != uid) ALOGF("'%s' uid is %d != %d", path, s.st_uid, uid);
+ if (s.st_gid != gid) ALOGF("'%s' gid is %d != %d", path, s.st_gid, gid);
+
+ char b[255] = {};
+ int v = lgetxattr(path, "security.selinux", &b, sizeof(b));
+ if (v < 0) ALOGF("lgetxattr '%s' errno=%d", path, errno);
+ if (strncmp(ctxt, b, sizeof(b))) ALOGF("context of '%s' is '%s' != '%s'", path, b, ctxt);
+
+ int fd = -1;
+
+ switch (vtype) {
+ case VERIFY_DIR: return;
+ case VERIFY_BIN: return;
+ case VERIFY_PROG: fd = bpf::retrieveProgram(path); break;
+ case VERIFY_MAP_RO: fd = bpf::mapRetrieveRO(path); break;
+ case VERIFY_MAP_RW: fd = bpf::mapRetrieveRW(path); break;
+ }
+
+ if (fd < 0) ALOGF("bpf_obj_get '%s' failed, errno=%d", path, errno);
+
+ if (fd >= 0) close(fd);
+}
+
+#undef ALOGF
+
+bool isGsiImage() {
+ // this implementation matches 2 other places in the codebase (same function name too)
+ return !access("/system/system_ext/etc/init/init.gsi.rc", F_OK);
+}
+
+static const char* kClatdDir = "/apex/com.android.tethering/bin/for-system";
+static const char* kClatdBin = "/apex/com.android.tethering/bin/for-system/clatd";
+
+#define V(path, md, uid, gid, ctx, vtype) \
+ verifyPerms((path), (md), AID_ ## uid, AID_ ## gid, "u:object_r:" ctx ":s0", VERIFY_ ## vtype)
+
+static void verifyClatPerms() {
+ // We might run as part of tests instead of as part of system server
+ if (getuid() != AID_SYSTEM) return;
+
+ // First verify the clatd directory and binary,
+ // since this is built into the apex file system image,
+ // failures here are 99% likely to be build problems.
+ V(kClatdDir, S_IFDIR|0750, ROOT, SYSTEM, "system_file", DIR);
+ V(kClatdBin, S_IFREG|S_ISUID|S_ISGID|0755, CLAT, CLAT, "clatd_exec", BIN);
+
+ // Move on to verifying that the bpf programs and maps are as expected.
+ // This relies on the kernel and bpfloader.
+
+ // Clat BPF was only mainlined during T.
+ if (!modules::sdklevel::IsAtLeastT()) return;
+
+ V("/sys/fs/bpf", S_IFDIR|S_ISVTX|0777, ROOT, ROOT, "fs_bpf", DIR);
+ V("/sys/fs/bpf/net_shared", S_IFDIR|S_ISVTX|0777, ROOT, ROOT, "fs_bpf_net_shared", DIR);
+
+ // pre-U we do not have selinux privs to getattr on bpf maps/progs
+ // so while the below *should* be as listed, we have no way to actually verify
+ if (!modules::sdklevel::IsAtLeastU()) return;
+
+#define V2(path, md, vtype) \
+ V("/sys/fs/bpf/net_shared/" path, (md), ROOT, SYSTEM, "fs_bpf_net_shared", vtype)
+
+ V2("prog_clatd_schedcls_egress4_clat_rawip", S_IFREG|0440, PROG);
+ V2("prog_clatd_schedcls_ingress6_clat_rawip", S_IFREG|0440, PROG);
+ V2("prog_clatd_schedcls_ingress6_clat_ether", S_IFREG|0440, PROG);
+ V2("map_clatd_clat_egress4_map", S_IFREG|0660, MAP_RW);
+ V2("map_clatd_clat_ingress6_map", S_IFREG|0660, MAP_RW);
+
+#undef V2
+
+ // HACK: Some old vendor kernels lack ~5.10 backport of 'bpffs selinux genfscon' support.
+ // This is *NOT* supported, but let's allow, at least for now, U+ GSI to boot on them.
+ // (without this hack pixel5 R vendor + U gsi breaks)
+ if (isGsiImage() && !bpf::isAtLeastKernelVersion(5, 10, 0)) {
+ ALOGE("GSI with *BAD* pre-5.10 kernel lacking bpffs selinux genfscon support.");
+ return;
+ }
+
+ if (fatal) abort();
+}
+
+#undef V
static void throwIOException(JNIEnv* env, const char* msg, int error) {
jniThrowExceptionFmt(env, "java/io/IOException", "%s: %s", msg, strerror(error));
}
jstring com_android_server_connectivity_ClatCoordinator_selectIpv4Address(JNIEnv* env,
- jobject clazz,
+ jclass clazz,
jstring v4addr,
jint prefixlen) {
ScopedUtfChars address(env, v4addr);
@@ -84,7 +185,7 @@
// Picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix.
jstring com_android_server_connectivity_ClatCoordinator_generateIpv6Address(
- JNIEnv* env, jobject clazz, jstring ifaceStr, jstring v4Str, jstring prefix64Str,
+ JNIEnv* env, jclass clazz, jstring ifaceStr, jstring v4Str, jstring prefix64Str,
jint mark) {
ScopedUtfChars iface(env, ifaceStr);
ScopedUtfChars addr4(env, v4Str);
@@ -125,7 +226,7 @@
}
static jint com_android_server_connectivity_ClatCoordinator_createTunInterface(JNIEnv* env,
- jobject clazz,
+ jclass clazz,
jstring tuniface) {
ScopedUtfChars v4interface(env, tuniface);
@@ -138,7 +239,7 @@
}
struct ifreq ifr = {
- .ifr_flags = IFF_TUN,
+ .ifr_flags = static_cast<short>(IFF_TUN | IFF_TUN_EXCL),
};
strlcpy(ifr.ifr_name, v4interface.c_str(), sizeof(ifr.ifr_name));
@@ -152,7 +253,7 @@
return fd;
}
-static jint com_android_server_connectivity_ClatCoordinator_detectMtu(JNIEnv* env, jobject clazz,
+static jint com_android_server_connectivity_ClatCoordinator_detectMtu(JNIEnv* env, jclass clazz,
jstring platSubnet,
jint plat_suffix, jint mark) {
ScopedUtfChars platSubnetStr(env, platSubnet);
@@ -174,25 +275,32 @@
}
static jint com_android_server_connectivity_ClatCoordinator_openPacketSocket(JNIEnv* env,
- jobject clazz) {
+ jclass clazz) {
// Will eventually be bound to htons(ETH_P_IPV6) protocol,
// but only after appropriate bpf filter is attached.
- int sock = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ const int sock = socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC, 0);
if (sock < 0) {
throwIOException(env, "packet socket failed", errno);
return -1;
}
- int on = 1;
+ const int on = 1;
+ // enable tpacket_auxdata cmsg delivery, which includes L2 header length
if (setsockopt(sock, SOL_PACKET, PACKET_AUXDATA, &on, sizeof(on))) {
throwIOException(env, "packet socket auxdata enablement failed", errno);
close(sock);
return -1;
}
+ // needed for virtio_net_hdr prepending, which includes checksum metadata
+ if (setsockopt(sock, SOL_PACKET, PACKET_VNET_HDR, &on, sizeof(on))) {
+ throwIOException(env, "packet socket vnet_hdr enablement failed", errno);
+ close(sock);
+ return -1;
+ }
return sock;
}
static jint com_android_server_connectivity_ClatCoordinator_openRawSocket6(JNIEnv* env,
- jobject clazz,
+ jclass clazz,
jint mark) {
int sock = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_RAW);
if (sock < 0) {
@@ -211,7 +319,7 @@
}
static void com_android_server_connectivity_ClatCoordinator_addAnycastSetsockopt(
- JNIEnv* env, jobject clazz, jobject javaFd, jstring addr6, jint ifindex) {
+ JNIEnv* env, jclass clazz, jobject javaFd, jstring addr6, jint ifindex) {
int sock = netjniutils::GetNativeFileDescriptor(env, javaFd);
if (sock < 0) {
jniThrowExceptionFmt(env, "java/io/IOException", "Invalid file descriptor");
@@ -237,7 +345,7 @@
}
static void com_android_server_connectivity_ClatCoordinator_configurePacketSocket(
- JNIEnv* env, jobject clazz, jobject javaFd, jstring addr6, jint ifindex) {
+ JNIEnv* env, jclass clazz, jobject javaFd, jstring addr6, jint ifindex) {
ScopedUtfChars addrStr(env, addr6);
int sock = netjniutils::GetNativeFileDescriptor(env, javaFd);
@@ -261,7 +369,7 @@
}
static jint com_android_server_connectivity_ClatCoordinator_startClatd(
- JNIEnv* env, jobject clazz, jobject tunJavaFd, jobject readSockJavaFd,
+ JNIEnv* env, jclass clazz, jobject tunJavaFd, jobject readSockJavaFd,
jobject writeSockJavaFd, jstring iface, jstring pfx96, jstring v4, jstring v6) {
ScopedUtfChars ifaceStr(env, iface);
ScopedUtfChars pfx96Str(env, pfx96);
@@ -358,7 +466,7 @@
// 5. actually perform vfork/dup2/execve
pid_t pid;
- if (int ret = posix_spawn(&pid, kClatdPath, &fa, &attr, (char* const*)args, nullptr)) {
+ if (int ret = posix_spawn(&pid, kClatdBin, &fa, &attr, (char* const*)args, nullptr)) {
posix_spawnattr_destroy(&attr);
posix_spawn_file_actions_destroy(&fa);
throwIOException(env, "posix_spawn failed", ret);
@@ -398,7 +506,9 @@
if (ret == 0) {
ALOGE("Failed to SIGTERM clatd pid=%d, try SIGKILL", pid);
// TODO: fix that kill failed or waitpid doesn't return.
- kill(pid, SIGKILL);
+ if (kill(pid, SIGKILL)) {
+ ALOGE("Failed to SIGKILL clatd pid=%d: %s", pid, strerror(errno));
+ }
ret = waitpid(pid, &status, 0);
}
if (ret == -1) {
@@ -408,7 +518,7 @@
}
}
-static void com_android_server_connectivity_ClatCoordinator_stopClatd(JNIEnv* env, jobject clazz,
+static void com_android_server_connectivity_ClatCoordinator_stopClatd(JNIEnv* env, jclass clazz,
jstring iface, jstring pfx96,
jstring v4, jstring v6,
jint pid) {
@@ -426,7 +536,7 @@
}
static jlong com_android_server_connectivity_ClatCoordinator_getSocketCookie(
- JNIEnv* env, jobject clazz, jobject sockJavaFd) {
+ JNIEnv* env, jclass clazz, jobject sockJavaFd) {
int sockFd = netjniutils::GetNativeFileDescriptor(env, sockJavaFd);
if (sockFd < 0) {
jniThrowExceptionFmt(env, "java/io/IOException", "Invalid socket file descriptor");
@@ -434,7 +544,7 @@
}
uint64_t sock_cookie = bpf::getSocketCookie(sockFd);
- if (sock_cookie == bpf::NONEXISTENT_COOKIE) {
+ if (!sock_cookie) {
throwIOException(env, "get socket cookie failed", errno);
return -1;
}
@@ -477,8 +587,10 @@
};
int register_com_android_server_connectivity_ClatCoordinator(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "com/android/server/connectivity/ClatCoordinator",
- gMethods, NELEM(gMethods));
+ verifyClatPerms();
+ return jniRegisterNativeMethods(env,
+ "android/net/connectivity/com/android/server/connectivity/ClatCoordinator",
+ gMethods, NELEM(gMethods));
}
}; // namespace android
diff --git a/service/libconnectivity/src/connectivity_native.cpp b/service/libconnectivity/src/connectivity_native.cpp
index 9545ed1..a476498 100644
--- a/service/libconnectivity/src/connectivity_native.cpp
+++ b/service/libconnectivity/src/connectivity_native.cpp
@@ -23,8 +23,8 @@
static std::shared_ptr<IConnectivityNative> getBinder() {
- static ndk::SpAIBinder sBinder = ndk::SpAIBinder(reinterpret_cast<AIBinder*>(
- AServiceManager_getService("connectivity_native")));
+ ndk::SpAIBinder sBinder = ndk::SpAIBinder(reinterpret_cast<AIBinder*>(
+ AServiceManager_checkService("connectivity_native")));
return aidl::android::net::connectivity::aidl::IConnectivityNative::fromBinder(sBinder);
}
@@ -45,21 +45,33 @@
int AConnectivityNative_blockPortForBind(in_port_t port) {
std::shared_ptr<IConnectivityNative> c = getBinder();
+ if (!c) {
+ return EAGAIN;
+ }
return getErrno(c->blockPortForBind(port));
}
int AConnectivityNative_unblockPortForBind(in_port_t port) {
std::shared_ptr<IConnectivityNative> c = getBinder();
+ if (!c) {
+ return EAGAIN;
+ }
return getErrno(c->unblockPortForBind(port));
}
int AConnectivityNative_unblockAllPortsForBind() {
std::shared_ptr<IConnectivityNative> c = getBinder();
+ if (!c) {
+ return EAGAIN;
+ }
return getErrno(c->unblockAllPortsForBind());
}
int AConnectivityNative_getPortsBlockedForBind(in_port_t *ports, size_t *count) {
std::shared_ptr<IConnectivityNative> c = getBinder();
+ if (!c) {
+ return EAGAIN;
+ }
std::vector<int32_t> actualBlockedPorts;
int err = getErrno(c->getPortsBlockedForBind(&actualBlockedPorts));
if (err) {
diff --git a/service/native/libs/libclat/Android.bp b/service/native/libs/libclat/Android.bp
index 54d40ac..996706e 100644
--- a/service/native/libs/libclat/Android.bp
+++ b/service/native/libs/libclat/Android.bp
@@ -23,6 +23,9 @@
"clatutils.cpp",
],
stl: "libc++_static",
+ header_libs: [
+ "bpf_headers",
+ ],
static_libs: [
"libip_checksum",
],
diff --git a/service/native/libs/libclat/clatutils.cpp b/service/native/libs/libclat/clatutils.cpp
index 64e5b91..6c5c9e3 100644
--- a/service/native/libs/libclat/clatutils.cpp
+++ b/service/native/libs/libclat/clatutils.cpp
@@ -25,22 +25,19 @@
#include <string.h>
#include <unistd.h>
+#include <bpf/BpfClassic.h>
+
extern "C" {
#include "checksum.h"
}
-// Sync from system/netd/include/netid_client.h.
-#define MARK_UNSET 0u
-
namespace android {
namespace net {
namespace clat {
-bool isIpv4AddressFree(in_addr_t addr) {
- int s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (s == -1) {
- return 0;
- }
+bool isIpv4AddressFree(const in_addr_t addr) {
+ const int s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (s == -1) return 0;
// Attempt to connect to the address. If the connection succeeds and getsockname returns the
// same then the address is already assigned to the system and we can't use it.
@@ -50,9 +47,10 @@
.sin_addr = {addr},
};
socklen_t len = sizeof(sin);
- bool inuse = connect(s, (struct sockaddr*)&sin, sizeof(sin)) == 0 &&
- getsockname(s, (struct sockaddr*)&sin, &len) == 0 && (size_t)len >= sizeof(sin) &&
- sin.sin_addr.s_addr == addr;
+ const bool inuse = !connect(s, (struct sockaddr*)&sin, sizeof(sin)) &&
+ !getsockname(s, (struct sockaddr*)&sin, &len) &&
+ len == (socklen_t)sizeof(sin) &&
+ sin.sin_addr.s_addr == addr;
close(s);
return !inuse;
@@ -62,36 +60,30 @@
// ip - the IP address from the configuration file
// prefixlen - the length of the prefix from which addresses may be selected.
// returns: the IPv4 address, or INADDR_NONE if no addresses were available
-in_addr_t selectIpv4Address(const in_addr ip, int16_t prefixlen) {
+in_addr_t selectIpv4Address(const in_addr ip, const int16_t prefixlen) {
return selectIpv4AddressInternal(ip, prefixlen, isIpv4AddressFree);
}
// Only allow testing to use this function directly. Otherwise call selectIpv4Address(ip, pfxlen)
// which has applied valid isIpv4AddressFree function pointer.
-in_addr_t selectIpv4AddressInternal(const in_addr ip, int16_t prefixlen,
- isIpv4AddrFreeFn isIpv4AddressFreeFunc) {
+in_addr_t selectIpv4AddressInternal(const in_addr ip, const int16_t prefixlen,
+ const isIpv4AddrFreeFn isIpv4AddressFreeFunc) {
// Impossible! Only test allows to apply fn.
- if (isIpv4AddressFreeFunc == nullptr) {
- return INADDR_NONE;
- }
+ if (isIpv4AddressFreeFunc == nullptr) return INADDR_NONE;
// Don't accept prefixes that are too large because we scan addresses one by one.
- if (prefixlen < 16 || prefixlen > 32) {
- return INADDR_NONE;
- }
+ if (prefixlen < 16 || prefixlen > 32) return INADDR_NONE;
// All these are in host byte order.
- in_addr_t mask = 0xffffffff >> (32 - prefixlen) << (32 - prefixlen);
- in_addr_t ipv4 = ntohl(ip.s_addr);
- in_addr_t first_ipv4 = ipv4;
- in_addr_t prefix = ipv4 & mask;
+ const uint32_t mask = 0xffffffff >> (32 - prefixlen) << (32 - prefixlen);
+ uint32_t ipv4 = ntohl(ip.s_addr);
+ const uint32_t first_ipv4 = ipv4;
+ const uint32_t prefix = ipv4 & mask;
// Pick the first IPv4 address in the pool, wrapping around if necessary.
// So, for example, 192.0.0.4 -> 192.0.0.5 -> 192.0.0.6 -> 192.0.0.7 -> 192.0.0.0.
do {
- if (isIpv4AddressFreeFunc(htonl(ipv4))) {
- return htonl(ipv4);
- }
+ if (isIpv4AddressFreeFunc(htonl(ipv4))) return htonl(ipv4);
ipv4 = prefix | ((ipv4 + 1) & ~mask);
} while (ipv4 != first_ipv4);
@@ -99,7 +91,7 @@
}
// Alters the bits in the IPv6 address to make them checksum neutral with v4 and nat64Prefix.
-void makeChecksumNeutral(in6_addr* v6, const in_addr v4, const in6_addr& nat64Prefix) {
+void makeChecksumNeutral(in6_addr* const v6, const in_addr v4, const in6_addr& nat64Prefix) {
// Fill last 8 bytes of IPv6 address with random bits.
arc4random_buf(&v6->s6_addr[8], 8);
@@ -121,33 +113,35 @@
}
// Picks a random interface ID that is checksum neutral with the IPv4 address and the NAT64 prefix.
-int generateIpv6Address(const char* iface, const in_addr v4, const in6_addr& nat64Prefix,
- in6_addr* v6, uint32_t mark) {
- int s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+int generateIpv6Address(const char* const iface, const in_addr v4, const in6_addr& nat64Prefix,
+ in6_addr* const v6, const uint32_t mark) {
+ const int s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (s == -1) return -errno;
// Socket's mark affects routing decisions (network selection)
// An fwmark is necessary for clat to bypass the VPN during initialization.
- if ((mark != MARK_UNSET) && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
- int ret = errno;
- ALOGE("setsockopt(SOL_SOCKET, SO_MARK) failed: %s", strerror(errno));
+ if (setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
+ const int err = errno;
+ ALOGE("setsockopt(SOL_SOCKET, SO_MARK) failed: %s", strerror(err));
close(s);
- return -ret;
+ return -err;
}
- if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1) == -1) {
+ if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1)) {
+ const int err = errno;
+ ALOGE("setsockopt(SOL_SOCKET, SO_BINDTODEVICE, '%s') failed: %s", iface, strerror(err));
close(s);
- return -errno;
+ return -err;
}
sockaddr_in6 sin6 = {.sin6_family = AF_INET6, .sin6_addr = nat64Prefix};
- if (connect(s, reinterpret_cast<struct sockaddr*>(&sin6), sizeof(sin6)) == -1) {
+ if (connect(s, reinterpret_cast<struct sockaddr*>(&sin6), sizeof(sin6))) {
close(s);
return -errno;
}
socklen_t len = sizeof(sin6);
- if (getsockname(s, reinterpret_cast<struct sockaddr*>(&sin6), &len) == -1) {
+ if (getsockname(s, reinterpret_cast<struct sockaddr*>(&sin6), &len)) {
close(s);
return -errno;
}
@@ -166,21 +160,22 @@
return 0;
}
-int detect_mtu(const struct in6_addr* plat_subnet, uint32_t plat_suffix, uint32_t mark) {
+int detect_mtu(const struct in6_addr* const plat_subnet, const uint32_t plat_suffix,
+ const uint32_t mark) {
// Create an IPv6 UDP socket.
- int s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ const int s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (s < 0) {
- int ret = errno;
- ALOGE("socket(AF_INET6, SOCK_DGRAM, 0) failed: %s", strerror(errno));
- return -ret;
+ const int err = errno;
+ ALOGE("socket(AF_INET6, SOCK_DGRAM, 0) failed: %s", strerror(err));
+ return -err;
}
// Socket's mark affects routing decisions (network selection)
- if ((mark != MARK_UNSET) && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
- int ret = errno;
- ALOGE("setsockopt(SOL_SOCKET, SO_MARK) failed: %s", strerror(errno));
+ if (setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark))) {
+ const int err = errno;
+ ALOGE("setsockopt(SOL_SOCKET, SO_MARK) failed: %s", strerror(err));
close(s);
- return -ret;
+ return -err;
}
// Try to connect udp socket to plat_subnet(96 bits):plat_suffix(32 bits)
@@ -190,20 +185,20 @@
};
dst.sin6_addr.s6_addr32[3] = plat_suffix;
if (connect(s, (struct sockaddr*)&dst, sizeof(dst))) {
- int ret = errno;
- ALOGE("connect() failed: %s", strerror(errno));
+ const int err = errno;
+ ALOGE("connect() failed: %s", strerror(err));
close(s);
- return -ret;
+ return -err;
}
// Fetch the socket's IPv6 mtu - this is effectively fetching mtu from routing table
int mtu;
socklen_t sz_mtu = sizeof(mtu);
if (getsockopt(s, SOL_IPV6, IPV6_MTU, &mtu, &sz_mtu)) {
- int ret = errno;
- ALOGE("getsockopt(SOL_IPV6, IPV6_MTU) failed: %s", strerror(errno));
+ const int err = errno;
+ ALOGE("getsockopt(SOL_IPV6, IPV6_MTU) failed: %s", strerror(err));
close(s);
- return -ret;
+ return -err;
}
if (sz_mtu != sizeof(mtu)) {
ALOGE("getsockopt(SOL_IPV6, IPV6_MTU) returned unexpected size: %d", sz_mtu);
@@ -222,34 +217,26 @@
* ifindex - index of interface to add the filter to
* returns: 0 on success, -errno on failure
*/
-int configure_packet_socket(int sock, in6_addr* addr, int ifindex) {
- uint32_t* ipv6 = addr->s6_addr32;
-
+int configure_packet_socket(const int sock, const in6_addr* const addr, const int ifindex) {
// clang-format off
struct sock_filter filter_code[] = {
- // Load the first four bytes of the IPv6 destination address (starts 24 bytes in).
- // Compare it against the first four bytes of our IPv6 address, in host byte order (BPF loads
- // are always in host byte order). If it matches, continue with next instruction (JMP 0). If it
- // doesn't match, jump ahead to statement that returns 0 (ignore packet). Repeat for the other
- // three words of the IPv6 address, and if they all match, return full packet (accept packet).
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 24),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(ipv6[0]), 0, 7),
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 28),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(ipv6[1]), 0, 5),
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 32),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(ipv6[2]), 0, 3),
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 36),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(ipv6[3]), 0, 1),
- BPF_STMT(BPF_RET | BPF_K, 0xFFFFFFFF),
- BPF_STMT(BPF_RET | BPF_K, 0),
+ BPF_LOAD_IPV6_BE32(daddr.s6_addr32[0]),
+ BPF2_REJECT_IF_NOT_EQUAL(ntohl(addr->s6_addr32[0])),
+ BPF_LOAD_IPV6_BE32(daddr.s6_addr32[1]),
+ BPF2_REJECT_IF_NOT_EQUAL(ntohl(addr->s6_addr32[1])),
+ BPF_LOAD_IPV6_BE32(daddr.s6_addr32[2]),
+ BPF2_REJECT_IF_NOT_EQUAL(ntohl(addr->s6_addr32[2])),
+ BPF_LOAD_IPV6_BE32(daddr.s6_addr32[3]),
+ BPF2_REJECT_IF_NOT_EQUAL(ntohl(addr->s6_addr32[3])),
+ BPF_ACCEPT,
};
// clang-format on
struct sock_fprog filter = {sizeof(filter_code) / sizeof(filter_code[0]), filter_code};
if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) {
- int res = errno;
- ALOGE("attach packet filter failed: %s", strerror(errno));
- return -res;
+ const int err = errno;
+ ALOGE("attach packet filter failed: %s", strerror(err));
+ return -err;
}
struct sockaddr_ll sll = {
@@ -260,9 +247,9 @@
PACKET_OTHERHOST, // The 464xlat IPv6 address is not assigned to the kernel.
};
if (bind(sock, (struct sockaddr*)&sll, sizeof(sll))) {
- int res = errno;
- ALOGE("binding packet socket: %s", strerror(errno));
- return -res;
+ const int err = errno;
+ ALOGE("binding packet socket: %s", strerror(err));
+ return -err;
}
return 0;
diff --git a/service/native/libs/libclat/clatutils_test.cpp b/service/native/libs/libclat/clatutils_test.cpp
index abd4e81..f4f97db 100644
--- a/service/native/libs/libclat/clatutils_test.cpp
+++ b/service/native/libs/libclat/clatutils_test.cpp
@@ -165,7 +165,7 @@
TunInterface v6Iface;
ASSERT_EQ(0, v6Iface.init());
- int s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, htons(ETH_P_IPV6));
+ const int s = socket(AF_PACKET, SOCK_RAW | SOCK_CLOEXEC, htons(ETH_P_IPV6));
EXPECT_LE(0, s);
struct in6_addr addr6;
EXPECT_EQ(1, inet_pton(AF_INET6, "2001:db8::f00", &addr6));
diff --git a/service/native/libs/libclat/include/libclat/clatutils.h b/service/native/libs/libclat/include/libclat/clatutils.h
index 991b193..6e17e67 100644
--- a/service/native/libs/libclat/include/libclat/clatutils.h
+++ b/service/native/libs/libclat/include/libclat/clatutils.h
@@ -20,17 +20,19 @@
namespace net {
namespace clat {
-bool isIpv4AddressFree(in_addr_t addr);
-in_addr_t selectIpv4Address(const in_addr ip, int16_t prefixlen);
-void makeChecksumNeutral(in6_addr* v6, const in_addr v4, const in6_addr& nat64Prefix);
-int generateIpv6Address(const char* iface, const in_addr v4, const in6_addr& nat64Prefix,
- in6_addr* v6, uint32_t mark);
-int detect_mtu(const struct in6_addr* plat_subnet, uint32_t plat_suffix, uint32_t mark);
-int configure_packet_socket(int sock, in6_addr* addr, int ifindex);
+bool isIpv4AddressFree(const in_addr_t addr);
+in_addr_t selectIpv4Address(const in_addr ip, const int16_t prefixlen);
+void makeChecksumNeutral(in6_addr* const v6, const in_addr v4, const in6_addr& nat64Prefix);
+int generateIpv6Address(const char* const iface, const in_addr v4, const in6_addr& nat64Prefix,
+ in6_addr* const v6, const uint32_t mark);
+int detect_mtu(const struct in6_addr* const plat_subnet, const uint32_t plat_suffix,
+ const uint32_t mark);
+int configure_packet_socket(const int sock, const in6_addr* const addr, const int ifindex);
// For testing
-typedef bool (*isIpv4AddrFreeFn)(in_addr_t);
-in_addr_t selectIpv4AddressInternal(const in_addr ip, int16_t prefixlen, isIpv4AddrFreeFn fn);
+typedef bool (*isIpv4AddrFreeFn)(const in_addr_t);
+in_addr_t selectIpv4AddressInternal(const in_addr ip, const int16_t prefixlen,
+ const isIpv4AddrFreeFn fn);
} // namespace clat
} // namespace net
diff --git a/service/proguard.flags b/service/proguard.flags
index 864a28b..cf25f05 100644
--- a/service/proguard.flags
+++ b/service/proguard.flags
@@ -7,7 +7,7 @@
*;
}
--keepclassmembers class com.android.server.**,android.net.**,com.android.networkstack.** {
+-keepclassmembers class android.net.**,com.android.networkstack.** {
static final % POLICY_*;
static final % NOTIFY_TYPE_*;
static final % TRANSPORT_*;
diff --git a/service/src/com/android/metrics/stats.proto b/service/src/com/android/metrics/stats.proto
index 48b8316..006d20a 100644
--- a/service/src/com/android/metrics/stats.proto
+++ b/service/src/com/android/metrics/stats.proto
@@ -284,3 +284,152 @@
// The latency of selection issued in milli-second
optional int32 selection_issued_latency_milli = 5;
}
+
+message NetworkSliceRequestCountSample {
+ // Bitfield representing the network's capability(e.g. NET_CAPABILITY_PRIORITIZE_LATENCY),
+ // defined in packages/modules/Connectivity/framework/src/android/net/NetworkCapabilities.java
+ optional int64 slice_id = 1;
+
+ // Bitfield representing the network's enterprise capability identifier
+ // (e.g. NET_ENTERPRISE_ID_1), defined in
+ // packages/modules/Connectivity/framework/src/android/net/NetworkCapabilities.java
+ optional int32 enterprise_id = 2;
+
+ // number of request for this slice
+ optional int32 request_count = 3;
+
+ // number of apps with outstanding request(s) for this slice
+ optional int32 distinct_app_count = 4;
+}
+
+message NetworkSliceSessionEnded {
+ // Bitfield representing the network's capability(e.g. NET_CAPABILITY_PRIORITIZE_LATENCY),
+ // defined in packages/modules/Connectivity/framework/src/android/net/NetworkCapabilities.java
+ optional int64 slice_id = 1;
+
+ // Bitfield representing the network's enterprise capability identifier
+ // (e.g. NET_ENTERPRISE_ID_1), defined in
+ // packages/modules/Connectivity/framework/src/android/net/NetworkCapabilities.java
+ optional int32 enterprise_id = 2;
+
+ // Number of bytes received at the device on this slice id
+ optional int64 rx_bytes = 3;
+
+ // Number of bytes transmitted by the device on this slice id
+ optional int64 tx_bytes = 4;
+
+ // Number of apps that have used this slice
+ optional int32 number_of_apps = 5;
+
+ // How long(in seconds) this slice has been connected
+ optional int32 slice_connection_duration_sec = 6;
+}
+
+message NetworkSliceDailyDataUsageReported {
+ // Bitfield representing the network's capability(e.g. NET_CAPABILITY_PRIORITIZE_LATENCY),
+ // defined in packages/modules/Connectivity/framework/src/android/net/NetworkCapabilities.java
+ optional int64 slice_id = 1;
+
+ // Bitfield representing the network's enterprise capability identifier
+ // (e.g. NET_ENTERPRISE_ID_1), defined in
+ // packages/modules/Connectivity/framework/src/android/net/NetworkCapabilities.java
+ optional int32 enterprise_id = 2;
+
+ // Number of bytes received at the device on this slice id
+ optional int64 rx_bytes = 3;
+
+ // Number of bytes transmitted by the device on this slice id
+ optional int64 tx_bytes = 4;
+
+ // Number of apps that have used this slice
+ optional int32 number_of_apps = 5;
+
+ // How long(in seconds) this slice has been connected
+ optional int32 slice_connection_duration_sec = 6;
+}
+
+/**
+ * Logs DailykeepaliveInfoReported
+ *
+ * Logs from: packages/modules/Connectivity/service/src/com/android/
+ * server/connectivity/AutomaticOnOffKeepaliveTracker.
+ */
+message DailykeepaliveInfoReported{
+ // Daily duration per number of concurrent keepalive
+ optional DurationPerNumOfKeepalive duration_per_num_of_keepalive = 1;
+
+ // Daily keepalive registered/active duration on each list of keepalive session, in
+ // milli-seconds
+ optional KeepaliveLifetimePerCarrier keepalive_lifetime_per_carrier = 2;
+
+ // Daily number of keepalive requests
+ optional int32 keepalive_requests = 3;
+
+ // Daily number of automatic keepalive requests
+ optional int32 automatic_keepalive_requests = 4;
+
+ // Daily number of distinct apps that requested keepalives
+ optional int32 distinct_user_count = 5;
+
+ // Daily distinct apps uid list that requested keepalives
+ repeated int32 uid = 6;
+}
+
+/**
+ * Daily duration per number of concurrent keepalive
+ *
+ * Logs from: packages/modules/Connectivity/service/src/com/android/
+ * server/connectivity/AutomaticOnOffKeepaliveTracker.
+ */
+message DurationPerNumOfKeepalive {
+ repeated DurationForNumOfKeepalive duration_for_num_of_keepalive = 1;
+}
+
+message DurationForNumOfKeepalive {
+ // The number of concurrent keepalives is in the device
+ optional int32 num_of_keepalive = 1;
+
+ // How many milliseconds the device has keepalive registration number is num_of_keepalive
+ optional int32 keepalive_registered_durations_msec = 2;
+
+ // How many milliseconds the device has keepalive active(not paused) number is num_of_keepalive
+ optional int32 keepalive_active_durations_msec = 3;
+}
+
+/**
+ * Daily keepalive registered/active duration on each list of Keepalive session, in milli-seconds
+ *
+ * Logs from: packages/modules/Connectivity/service/src/com/android/
+ * server/connectivity/AutomaticOnOffKeepaliveTracker.
+ */
+message KeepaliveLifetimePerCarrier {
+ // The number of network count on each list of carriers
+ repeated KeepaliveLifetimeForCarrier keepalive_lifetime_for_carrier = 1;
+}
+
+/**
+ * Logs the keepalive registered/active duration in milli-seconds and carrier
+ * info(carrier id, transport, keepalive interval).
+ *
+ * Logs from: packages/modules/Connectivity/service/src/com/android/
+ * server/connectivity/AutomaticOnOffKeepaliveTracker.
+ */
+message KeepaliveLifetimeForCarrier {
+ // The carrier ID for each keepalive, or TelephonyManager.UNKNOWN_CARRIER_ID(-1) if not cell
+ optional int32 carrier_id = 1;
+
+ // The transport types of the underlying network for each keepalive. A network may include
+ // multiple transport types. Each transfer type is represented by a different bit, defined in
+ // packages/modules/Connectivity/framework/src/android/net/NetworkCapabilities.java
+ optional int32 transport_types = 2;
+
+ // The keepalive interval for each keepalive
+ optional int32 intervals_msec = 3;
+
+ // The lifetime of the keepalive registered today
+ optional int32 lifetime_msec = 4;
+
+ // The duration for which the keepalive was active (not suspended)
+ optional int32 active_lifetime_msec = 5;
+}
+
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index 26ec37a..b4fce37 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -721,6 +721,31 @@
}
/**
+ * Get firewall rule of specified firewall chain on specified uid.
+ *
+ * @param childChain target chain
+ * @param uid target uid
+ * @return either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
+ * @throws UnsupportedOperationException if called on pre-T devices.
+ * @throws ServiceSpecificException in case of failure, with an error code indicating the
+ * cause of the failure.
+ */
+ public int getUidRule(final int childChain, final int uid) {
+ throwIfPreT("isUidChainEnabled is not available on pre-T devices");
+
+ final long match = getMatchByFirewallChain(childChain);
+ final boolean isAllowList = isFirewallAllowList(childChain);
+ try {
+ final UidOwnerValue uidMatch = sUidOwnerMap.getValue(new S32(uid));
+ final boolean isMatchEnabled = uidMatch != null && (uidMatch.rule & match) != 0;
+ return isMatchEnabled == isAllowList ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DENY;
+ } catch (ErrnoException e) {
+ throw new ServiceSpecificException(e.errno,
+ "Unable to get uid rule status: " + Os.strerror(e.errno));
+ }
+ }
+
+ /**
* Add ingress interface filtering rules to a list of UIDs
*
* For a given uid, once a filtering rule is added, the kernel will only allow packets from the
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index eef4a0e..ba503e0 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -98,6 +98,7 @@
import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME;
import static com.android.net.module.util.NetworkMonitorUtils.isPrivateDnsValidationRequired;
+import static com.android.net.module.util.PermissionUtils.checkAnyPermissionOf;
import static com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf;
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermission;
import static com.android.net.module.util.PermissionUtils.enforceNetworkStackPermissionOr;
@@ -107,11 +108,13 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
+import android.app.compat.CompatChanges;
import android.app.usage.NetworkStatsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -120,6 +123,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
import android.net.CaptivePortal;
import android.net.CaptivePortalData;
@@ -194,6 +198,7 @@
import android.net.Uri;
import android.net.VpnManager;
import android.net.VpnTransportInfo;
+import android.net.connectivity.ConnectivityCompatChanges;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.netd.aidl.NativeUidRangeConfig;
@@ -268,8 +273,10 @@
import com.android.networkstack.apishim.ConstantsShim;
import com.android.networkstack.apishim.common.BroadcastOptionsShim;
import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+import com.android.server.connectivity.ApplicationSelfCertifiedNetworkCapabilities;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
+import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker.AutomaticOnOffKeepalive;
import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
import com.android.server.connectivity.ClatCoordinator;
import com.android.server.connectivity.ConnectivityFlags;
@@ -277,6 +284,7 @@
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
import com.android.server.connectivity.DscpPolicyTracker;
import com.android.server.connectivity.FullScore;
+import com.android.server.connectivity.InvalidTagException;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
import com.android.server.connectivity.MockableSystemProperties;
@@ -298,6 +306,8 @@
import libcore.io.IoUtils;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
@@ -454,7 +464,11 @@
private String mCurrentTcpBufferSizes;
private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
- new Class[] { ConnectivityService.class, NetworkAgent.class, NetworkAgentInfo.class });
+ new Class[] {
+ ConnectivityService.class,
+ NetworkAgent.class,
+ NetworkAgentInfo.class,
+ AutomaticOnOffKeepaliveTracker.class });
private enum ReapUnvalidatedNetworks {
// Tear down networks that have no chance (e.g. even if validated) of becoming
@@ -764,6 +778,11 @@
private static final int EVENT_SET_VPN_NETWORK_PREFERENCE = 59;
/**
+ * Event to use low TCP polling timer used in automatic on/off keepalive temporarily.
+ */
+ private static final int EVENT_SET_LOW_TCP_POLLING_UNTIL = 60;
+
+ /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
*/
@@ -781,6 +800,12 @@
private static final long MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS = 5 * 60 * 1000L;
/**
+ * The maximum alive time to decrease TCP polling timer in automatic on/off keepalive for
+ * testing.
+ */
+ private static final long MAX_TEST_LOW_TCP_POLLING_UNTIL_MS = 5 * 60 * 1000L;
+
+ /**
* The priority of the tc police rate limiter -- smaller value is higher priority.
* This value needs to be coordinated with PRIO_CLAT, PRIO_TETHER4, and PRIO_TETHER6.
*/
@@ -889,6 +914,13 @@
// Only the handler thread is allowed to access this field.
private long mIngressRateLimit = -1;
+ // This is the cache for the packageName -> ApplicationSelfCertifiedNetworkCapabilities. This
+ // value can be accessed from both handler thread and any random binder thread. Therefore,
+ // accessing this value requires holding a lock. The cache is the same across all the users.
+ @GuardedBy("mSelfCertifiedCapabilityCache")
+ private final Map<String, ApplicationSelfCertifiedNetworkCapabilities>
+ mSelfCertifiedCapabilityCache = new HashMap<>();
+
/**
* Implements support for the legacy "one network per network type" model.
*
@@ -1303,6 +1335,14 @@
}
/**
+ * @see AutomaticOnOffKeepaliveTracker
+ */
+ public AutomaticOnOffKeepaliveTracker makeAutomaticOnOffKeepaliveTracker(
+ @NonNull Context c, @NonNull Handler h) {
+ return new AutomaticOnOffKeepaliveTracker(c, h);
+ }
+
+ /**
* @see BatteryStatsManager
*/
public void reportNetworkInterfaceForTransports(Context context, String iface,
@@ -1431,6 +1471,20 @@
public BroadcastOptionsShim makeBroadcastOptionsShim(BroadcastOptions options) {
return BroadcastOptionsShimImpl.newInstance(options);
}
+
+ /**
+ * Wrapper method for
+ * {@link android.app.compat.CompatChanges#isChangeEnabled(long, String, UserHandle)}.
+ *
+ * @param changeId The ID of the compatibility change in question.
+ * @param packageName The package name of the app in question.
+ * @param user The user that the operation is done for.
+ * @return {@code true} if the change is enabled for the specified package.
+ */
+ public boolean isChangeEnabled(long changeId, @NonNull final String packageName,
+ @NonNull final UserHandle user) {
+ return CompatChanges.isChangeEnabled(changeId, packageName, user);
+ }
}
public ConnectivityService(Context context) {
@@ -1565,7 +1619,7 @@
mSettingsObserver = new SettingsObserver(mContext, mHandler);
registerSettingsCallbacks();
- mKeepaliveTracker = new AutomaticOnOffKeepaliveTracker(mContext, mHandler);
+ mKeepaliveTracker = mDeps.makeAutomaticOnOffKeepaliveTracker(mContext, mHandler);
mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager);
mQosCallbackTracker = new QosCallbackTracker(mHandler, mNetworkRequestCounter);
@@ -2275,11 +2329,12 @@
if (newNc.getNetworkSpecifier() != null) {
newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
}
- if (!checkAnyPermissionOf(callerPid, callerUid, android.Manifest.permission.NETWORK_STACK,
+ if (!checkAnyPermissionOf(mContext, callerPid, callerUid,
+ android.Manifest.permission.NETWORK_STACK,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)) {
newNc.setAdministratorUids(new int[0]);
}
- if (!checkAnyPermissionOf(
+ if (!checkAnyPermissionOf(mContext,
callerPid, callerUid, android.Manifest.permission.NETWORK_FACTORY)) {
newNc.setAllowedUids(new ArraySet<>());
newNc.setSubscriptionIds(Collections.emptySet());
@@ -2788,15 +2843,6 @@
setUidBlockedReasons(uid, blockedReasons);
}
- private boolean checkAnyPermissionOf(int pid, int uid, String... permissions) {
- for (String permission : permissions) {
- if (mContext.checkPermission(permission, pid, uid) == PERMISSION_GRANTED) {
- return true;
- }
- }
- return false;
- }
-
private void enforceInternetPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERNET,
@@ -2861,9 +2907,10 @@
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
}
- private void enforceSettingsOrUseRestrictedNetworksPermission() {
+ private void enforceSettingsOrSetupWizardOrUseRestrictedNetworksPermission() {
enforceAnyPermissionOf(mContext,
android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS);
}
@@ -2954,13 +3001,13 @@
}
private boolean checkNetworkStackPermission(int pid, int uid) {
- return checkAnyPermissionOf(pid, uid,
+ return checkAnyPermissionOf(mContext, pid, uid,
android.Manifest.permission.NETWORK_STACK,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
}
private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) {
- return checkAnyPermissionOf(pid, uid,
+ return checkAnyPermissionOf(mContext, pid, uid,
android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_SETTINGS);
@@ -3037,6 +3084,8 @@
sendStickyBroadcast(makeGeneralIntent(info, bcastType));
}
+ // TODO(b/193460475): Remove when tooling supports SystemApi to public API.
+ @SuppressLint("NewApi")
// TODO: Set the mini sdk to 31 and remove @TargetApi annotation when b/205923322 is addressed.
@TargetApi(Build.VERSION_CODES.S)
private void sendStickyBroadcast(Intent intent) {
@@ -3081,7 +3130,7 @@
optsShim.setDeliveryGroupPolicy(ConstantsShim.DELIVERY_GROUP_POLICY_MOST_RECENT);
optsShim.setDeliveryGroupMatchingKey(ConnectivityManager.CONNECTIVITY_ACTION,
createDeliveryGroupKeyForConnectivityAction(info));
- optsShim.setDeferUntilActive(true);
+ optsShim.setDeferralPolicy(ConstantsShim.DEFERRAL_POLICY_UNTIL_ACTIVE);
} catch (UnsupportedApiLevelException e) {
Log.wtf(TAG, "Using unsupported API" + e);
}
@@ -4403,7 +4452,7 @@
mQosCallbackTracker.handleNetworkReleased(nai.network);
for (String iface : nai.linkProperties.getAllInterfaceNames()) {
// Disable wakeup packet monitoring for each interface.
- wakeupModifyInterface(iface, nai.networkCapabilities, false);
+ wakeupModifyInterface(iface, nai, false);
}
nai.networkMonitor().notifyNetworkDisconnected();
mNetworkAgentInfos.remove(nai);
@@ -4956,7 +5005,7 @@
}
private RequestInfoPerUidCounter getRequestCounter(NetworkRequestInfo nri) {
- return checkAnyPermissionOf(
+ return checkAnyPermissionOf(mContext,
nri.mPid, nri.mUid, NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
? mSystemNetworkRequestCounter : mNetworkRequestCounter;
}
@@ -4997,6 +5046,19 @@
mHandler.obtainMessage(EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL, timeMs));
}
+ @Override
+ public void setTestLowTcpPollingTimerForKeepalive(long timeMs) {
+ enforceSettingsPermission();
+
+ if (timeMs > System.currentTimeMillis() + MAX_TEST_LOW_TCP_POLLING_UNTIL_MS) {
+ throw new IllegalArgumentException("Argument should not exceed "
+ + MAX_TEST_LOW_TCP_POLLING_UNTIL_MS + "ms from now");
+ }
+
+ mHandler.sendMessage(
+ mHandler.obtainMessage(EVENT_SET_LOW_TCP_POLLING_UNTIL, timeMs));
+ }
+
private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
if (DBG) log("handleSetAcceptUnvalidated network=" + network +
" accept=" + accept + " always=" + always);
@@ -5540,21 +5602,25 @@
handleConfigureAlwaysOnNetworks();
break;
}
- // Sent by KeepaliveTracker to process an app request on the state machine thread.
- case NetworkAgent.CMD_START_SOCKET_KEEPALIVE: {
+ // Sent by AutomaticOnOffKeepaliveTracker to process an app request on the
+ // handler thread.
+ case AutomaticOnOffKeepaliveTracker.CMD_REQUEST_START_KEEPALIVE: {
mKeepaliveTracker.handleStartKeepalive(msg);
break;
}
- case NetworkAgent.CMD_MONITOR_AUTOMATIC_KEEPALIVE: {
- final Network network = (Network) msg.obj;
- final int slot = msg.arg1;
+ case AutomaticOnOffKeepaliveTracker.CMD_MONITOR_AUTOMATIC_KEEPALIVE: {
+ final AutomaticOnOffKeepalive ki =
+ mKeepaliveTracker.getKeepaliveForBinder((IBinder) msg.obj);
+ if (null == ki) return; // The callback was unregistered before the alarm fired
+ final Network underpinnedNetwork = ki.getUnderpinnedNetwork();
+ final Network network = ki.getNetwork();
boolean networkFound = false;
- final ArrayList<NetworkAgentInfo> vpnsRunningOnThisNetwork = new ArrayList<>();
+ boolean underpinnedNetworkFound = false;
for (NetworkAgentInfo n : mNetworkAgentInfos) {
if (n.network.equals(network)) networkFound = true;
- if (n.isVPN() && n.everConnected() && hasUnderlyingNetwork(n, network)) {
- vpnsRunningOnThisNetwork.add(n);
+ if (n.everConnected() && n.network.equals(underpinnedNetwork)) {
+ underpinnedNetworkFound = true;
}
}
@@ -5562,22 +5628,25 @@
// cleaned up already. There is no point trying to resume keepalives.
if (!networkFound) return;
- if (!vpnsRunningOnThisNetwork.isEmpty()) {
- mKeepaliveTracker.handleMonitorAutomaticKeepalive(network, slot,
- // TODO: check all the VPNs running on top of this network
- vpnsRunningOnThisNetwork.get(0).network.netId);
+ if (underpinnedNetworkFound) {
+ mKeepaliveTracker.handleMonitorAutomaticKeepalive(ki,
+ underpinnedNetwork.netId);
} else {
- // If no VPN, then make sure the keepalive is running.
- mKeepaliveTracker.handleMaybeResumeKeepalive(network, slot);
+ // If no underpinned network, then make sure the keepalive is running.
+ mKeepaliveTracker.handleMaybeResumeKeepalive(ki);
}
break;
}
// Sent by KeepaliveTracker to process an app request on the state machine thread.
case NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE: {
- NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj);
- int slot = msg.arg1;
- int reason = msg.arg2;
- mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
+ final AutomaticOnOffKeepalive ki = mKeepaliveTracker.getKeepaliveForBinder(
+ (IBinder) msg.obj);
+ if (ki == null) {
+ Log.e(TAG, "Attempt to stop an already stopped keepalive");
+ return;
+ }
+ final int reason = msg.arg2;
+ mKeepaliveTracker.handleStopKeepalive(ki, reason);
break;
}
case EVENT_REPORT_NETWORK_CONNECTIVITY: {
@@ -5632,6 +5701,11 @@
case EVENT_SET_VPN_NETWORK_PREFERENCE:
handleSetVpnNetworkPreference((VpnNetworkPreferenceInfo) msg.obj);
break;
+ case EVENT_SET_LOW_TCP_POLLING_UNTIL: {
+ final long time = ((Long) msg.obj).longValue();
+ mKeepaliveTracker.handleSetTestLowTcpPollingTimer(time);
+ break;
+ }
}
}
}
@@ -6268,6 +6342,11 @@
if (isMappedInOemNetworkPreference(packageName)) {
handleSetOemNetworkPreference(mOemNetworkPreferences, null);
}
+
+ // Invalidates cache entry when the package is updated.
+ synchronized (mSelfCertifiedCapabilityCache) {
+ mSelfCertifiedCapabilityCache.remove(packageName);
+ }
}
private final BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
@@ -6604,8 +6683,6 @@
@Override
public void binderDied() {
- log("ConnectivityService NetworkRequestInfo binderDied(" +
- "uid/pid:" + mUid + "/" + mPid + ", " + mRequests + ", " + mBinder + ")");
// As an immutable collection, mRequests cannot change by the time the
// lambda is evaluated on the handler thread so calling .get() from a binder thread
// is acceptable. Use handleReleaseNetworkRequest and not directly
@@ -6798,7 +6875,7 @@
enforceAccessPermission();
break;
case TRACK_SYSTEM_DEFAULT:
- enforceSettingsOrUseRestrictedNetworksPermission();
+ enforceSettingsOrSetupWizardOrUseRestrictedNetworksPermission();
networkCapabilities = new NetworkCapabilities(defaultNc);
break;
case BACKGROUND_REQUEST:
@@ -6896,8 +6973,72 @@
asUid, requests, nr, msgr, binder, callbackFlags, callingAttributionTag);
}
+ private boolean shouldCheckCapabilitiesDeclaration(
+ @NonNull final NetworkCapabilities networkCapabilities, final int callingUid,
+ @NonNull final String callingPackageName) {
+ final UserHandle user = UserHandle.getUserHandleForUid(callingUid);
+ // Only run the check if the change is enabled.
+ if (!mDeps.isChangeEnabled(
+ ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION,
+ callingPackageName, user)) {
+ return false;
+ }
+
+ return networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ || networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
+ }
+
+ private void enforceRequestCapabilitiesDeclaration(@NonNull final String callerPackageName,
+ @NonNull final NetworkCapabilities networkCapabilities) {
+ // This check is added to fix the linter error for "current min is 30", which is not going
+ // to happen because Connectivity service always run in S+.
+ if (!SdkLevel.isAtLeastS()) {
+ Log.wtf(TAG, "Connectivity service should always run in at least SDK S");
+ return;
+ }
+ ApplicationSelfCertifiedNetworkCapabilities applicationNetworkCapabilities;
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSelfCertifiedCapabilityCache) {
+ applicationNetworkCapabilities = mSelfCertifiedCapabilityCache.get(
+ callerPackageName);
+ if (applicationNetworkCapabilities == null) {
+ final PackageManager packageManager = mContext.getPackageManager();
+ final PackageManager.Property networkSliceProperty = packageManager.getProperty(
+ ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
+ callerPackageName
+ );
+ final XmlResourceParser parser = packageManager
+ .getResourcesForApplication(callerPackageName)
+ .getXml(networkSliceProperty.getResourceId());
+ applicationNetworkCapabilities =
+ ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser);
+ mSelfCertifiedCapabilityCache.put(callerPackageName,
+ applicationNetworkCapabilities);
+ }
+
+ }
+ } catch (PackageManager.NameNotFoundException ne) {
+ throw new SecurityException(
+ "Cannot find " + ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES
+ + " property");
+ } catch (XmlPullParserException | IOException | InvalidTagException e) {
+ throw new SecurityException(e.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
+ applicationNetworkCapabilities.enforceSelfCertifiedNetworkCapabilitiesDeclared(
+ networkCapabilities);
+ }
private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities,
String callingPackageName, String callingAttributionTag, final int callingUid) {
+ if (shouldCheckCapabilitiesDeclaration(networkCapabilities, callingUid,
+ callingPackageName)) {
+ enforceRequestCapabilitiesDeclaration(callingPackageName, networkCapabilities);
+ }
if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
// For T+ devices, callers with carrier privilege could request with CBS capabilities.
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
@@ -7655,7 +7796,7 @@
// the LinkProperties for the network are accurate.
networkAgent.clatd.fixupLinkProperties(oldLp, newLp);
- updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities);
+ updateInterfaces(newLp, oldLp, netId, networkAgent);
// update filtering rules, need to happen after the interface update so netd knows about the
// new interface (the interface name -> index map becomes initialized)
@@ -7763,10 +7904,16 @@
return captivePortalBuilder.build();
}
- private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) {
+ private String makeNflogPrefix(String iface, long networkHandle) {
+ // This needs to be kept in sync and backwards compatible with the decoding logic in
+ // NetdEventListenerService, which is non-mainline code.
+ return SdkLevel.isAtLeastU() ? (networkHandle + ":" + iface) : ("iface:" + iface);
+ }
+
+ private void wakeupModifyInterface(String iface, NetworkAgentInfo nai, boolean add) {
// Marks are only available on WiFi interfaces. Checking for
// marks on unsupported interfaces is harmless.
- if (!caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+ if (!nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return;
}
@@ -7779,7 +7926,7 @@
return;
}
- final String prefix = "iface:" + iface;
+ final String prefix = makeNflogPrefix(iface, nai.network.getNetworkHandle());
try {
if (add) {
mNetd.wakeupAddInterface(iface, prefix, mark, mask);
@@ -7789,12 +7936,11 @@
} catch (Exception e) {
loge("Exception modifying wakeup packet monitoring: " + e);
}
-
}
private void updateInterfaces(final @NonNull LinkProperties newLp,
final @Nullable LinkProperties oldLp, final int netId,
- final @NonNull NetworkCapabilities caps) {
+ final @NonNull NetworkAgentInfo nai) {
final CompareResult<String> interfaceDiff = new CompareResult<>(
oldLp != null ? oldLp.getAllInterfaceNames() : null, newLp.getAllInterfaceNames());
if (!interfaceDiff.added.isEmpty()) {
@@ -7802,9 +7948,9 @@
try {
if (DBG) log("Adding iface " + iface + " to network " + netId);
mNetd.networkAddInterface(netId, iface);
- wakeupModifyInterface(iface, caps, true);
+ wakeupModifyInterface(iface, nai, true);
mDeps.reportNetworkInterfaceForTransports(mContext, iface,
- caps.getTransportTypes());
+ nai.networkCapabilities.getTransportTypes());
} catch (Exception e) {
logw("Exception adding interface: " + e);
}
@@ -7813,7 +7959,7 @@
for (final String iface : interfaceDiff.removed) {
try {
if (DBG) log("Removing iface " + iface + " from network " + netId);
- wakeupModifyInterface(iface, caps, false);
+ wakeupModifyInterface(iface, nai, false);
mNetd.networkRemoveInterface(netId, iface);
} catch (Exception e) {
loge("Exception removing interface: " + e);
@@ -8322,6 +8468,7 @@
exemptUids[1] = nai.networkCapabilities.getOwnerUid();
UidRangeParcel[] ranges = toUidRangeStableParcels(uidRanges);
+ // Close sockets before modifying uid ranges so that RST packets can reach to the server.
maybeCloseSockets(nai, ranges, exemptUids);
try {
if (add) {
@@ -8335,6 +8482,7 @@
loge("Exception while " + (add ? "adding" : "removing") + " uid ranges " + uidRanges +
" on netId " + nai.network.netId + ". " + e);
}
+ // Close sockets that established connection while requesting netd.
maybeCloseSockets(nai, ranges, exemptUids);
}
@@ -8511,6 +8659,8 @@
// else not handled
}
+ // TODO(b/193460475): Remove when tooling supports SystemApi to public API.
+ @SuppressLint("NewApi")
private void sendIntent(PendingIntent pendingIntent, Intent intent) {
mPendingIntentWakeLock.acquire();
try {
@@ -8801,6 +8951,9 @@
}
private void updateProfileAllowedNetworks() {
+ // Netd command is not implemented before U.
+ if (!SdkLevel.isAtLeastU()) return;
+
ensureRunningOnConnectivityServiceThread();
final ArrayList<NativeUidRangeConfig> configs = new ArrayList<>();
final List<UserHandle> users = mContext.getSystemService(UserManager.class)
@@ -8831,8 +8984,10 @@
mNetd.setNetworkAllowlist(configs.toArray(new NativeUidRangeConfig[0]));
} catch (ServiceSpecificException e) {
// Has the interface disappeared since the network was built?
+ Log.wtf(TAG, "Unexpected ServiceSpecificException", e);
} catch (RemoteException e) {
- // Netd died. This usually causes a runtime restart anyway.
+ // Netd died. This will cause a runtime restart anyway.
+ Log.wtf(TAG, "Unexpected RemoteException", e);
}
}
@@ -9816,21 +9971,22 @@
getNetworkAgentInfoForNetwork(network), null /* fd */,
intervalSeconds, cb, srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT,
// Keep behavior of the deprecated method as it is. Set automaticOnOffKeepalives to
- // false because there is no way and no plan to configure automaticOnOffKeepalives
- // in this deprecated method.
- false /* automaticOnOffKeepalives */);
+ // false and set the underpinned network to null because there is no way and no
+ // plan to configure automaticOnOffKeepalives or underpinnedNetwork in this
+ // deprecated method.
+ false /* automaticOnOffKeepalives */, null /* underpinnedNetwork */);
}
@Override
public void startNattKeepaliveWithFd(Network network, ParcelFileDescriptor pfd, int resourceId,
int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr,
- String dstAddr, boolean automaticOnOffKeepalives) {
+ String dstAddr, boolean automaticOnOffKeepalives, Network underpinnedNetwork) {
try {
final FileDescriptor fd = pfd.getFileDescriptor();
mKeepaliveTracker.startNattKeepalive(
getNetworkAgentInfoForNetwork(network), fd, resourceId,
- intervalSeconds, cb,
- srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT, automaticOnOffKeepalives);
+ intervalSeconds, cb, srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT,
+ automaticOnOffKeepalives, underpinnedNetwork);
} finally {
// FileDescriptors coming from AIDL calls must be manually closed to prevent leaks.
// startNattKeepalive calls Os.dup(fd) before returning, so we can close immediately.
@@ -9858,9 +10014,10 @@
}
@Override
- public void stopKeepalive(Network network, int slot) {
+ public void stopKeepalive(@NonNull final ISocketKeepaliveCallback cb) {
mHandler.sendMessage(mHandler.obtainMessage(
- NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, slot, SocketKeepalive.SUCCESS, network));
+ NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, 0, SocketKeepalive.SUCCESS,
+ Objects.requireNonNull(cb).asBinder()));
}
@Override
@@ -10575,6 +10732,18 @@
callback));
}
+ private boolean hasUnderlyingTestNetworks(NetworkCapabilities nc) {
+ final List<Network> underlyingNetworks = nc.getUnderlyingNetworks();
+ if (underlyingNetworks == null) return false;
+
+ for (Network network : underlyingNetworks) {
+ if (getNetworkCapabilitiesInternal(network).hasTransport(TRANSPORT_TEST)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public void simulateDataStall(int detectionMethod, long timestampMillis,
@NonNull Network network, @NonNull PersistableBundle extras) {
@@ -10585,14 +10754,18 @@
android.Manifest.permission.MANAGE_TEST_NETWORKS,
android.Manifest.permission.NETWORK_STACK);
final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network);
- if (!nc.hasTransport(TRANSPORT_TEST)) {
- throw new SecurityException("Data Stall simulation is only possible for test networks");
+ if (!nc.hasTransport(TRANSPORT_TEST) && !hasUnderlyingTestNetworks(nc)) {
+ throw new SecurityException(
+ "Data Stall simulation is only possible for test networks or networks built on"
+ + " top of test networks");
}
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
- if (nai == null || nai.creatorUid != mDeps.getCallingUid()) {
- throw new SecurityException("Data Stall simulation is only possible for network "
- + "creators");
+ if (nai == null
+ || (nai.creatorUid != mDeps.getCallingUid()
+ && nai.creatorUid != Process.SYSTEM_UID)) {
+ throw new SecurityException(
+ "Data Stall simulation is only possible for network " + "creators");
}
// Instead of passing the data stall directly to the ConnectivityDiagnostics handler, treat
@@ -11692,6 +11865,12 @@
}
}
+ @Override
+ public int getUidFirewallRule(final int chain, final int uid) {
+ enforceNetworkStackOrSettingsPermission();
+ return mBpfNetMaps.getUidRule(chain, uid);
+ }
+
private int getFirewallRuleType(int chain, int rule) {
final int defaultRule;
switch (chain) {
diff --git a/service/src/com/android/server/TestNetworkService.java b/service/src/com/android/server/TestNetworkService.java
index 5549fbe..843b7b3 100644
--- a/service/src/com/android/server/TestNetworkService.java
+++ b/service/src/com/android/server/TestNetworkService.java
@@ -310,9 +310,11 @@
NetworkStackConstants.IPV6_ADDR_ANY, 0), null, iface));
}
+ // For testing purpose, fill legacy type for NetworkStatsService since it does not
+ // support transport types.
final TestNetworkAgent agent = new TestNetworkAgent(context, looper, nc, lp,
- new NetworkAgentConfig.Builder().build(), callingUid, binder,
- mNetworkProvider);
+ new NetworkAgentConfig.Builder().setLegacyType(ConnectivityManager.TYPE_TEST)
+ .build(), callingUid, binder, mNetworkProvider);
agent.register();
agent.markConnected();
return agent;
diff --git a/service/src/com/android/server/connectivity/ApplicationSelfCertifiedNetworkCapabilities.java b/service/src/com/android/server/connectivity/ApplicationSelfCertifiedNetworkCapabilities.java
new file mode 100644
index 0000000..76e966f
--- /dev/null
+++ b/service/src/com/android/server/connectivity/ApplicationSelfCertifiedNetworkCapabilities.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2023 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.server.connectivity;
+
+
+import android.annotation.NonNull;
+import android.net.NetworkCapabilities;
+import android.util.Log;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayDeque;
+
+
+/**
+ * The class for parsing and checking the self-declared application network capabilities.
+ *
+ * ApplicationSelfCertifiedNetworkCapabilities is an immutable class that
+ * can parse the self-declared application network capabilities in the application resources. The
+ * class also provides a helper method to check whether the requested network capabilities
+ * already self-declared.
+ */
+public final class ApplicationSelfCertifiedNetworkCapabilities {
+
+ public static final String PRIORITIZE_LATENCY = "NET_CAPABILITY_PRIORITIZE_LATENCY";
+ public static final String PRIORITIZE_BANDWIDTH = "NET_CAPABILITY_PRIORITIZE_BANDWIDTH";
+
+ private static final String TAG =
+ ApplicationSelfCertifiedNetworkCapabilities.class.getSimpleName();
+ private static final String NETWORK_CAPABILITIES_DECLARATION_TAG =
+ "network-capabilities-declaration";
+ private static final String USES_NETWORK_CAPABILITY_TAG = "uses-network-capability";
+ private static final String NAME_TAG = "name";
+
+ private long mRequestedNetworkCapabilities = 0;
+
+ /**
+ * Creates {@link ApplicationSelfCertifiedNetworkCapabilities} from a xml parser.
+ *
+ * <p> Here is an example of the xml syntax:
+ *
+ * <pre>
+ * {@code
+ * <network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ * <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ * <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+ * </network-capabilities-declaration>
+ * }
+ * </pre>
+ * <p>
+ *
+ * @param xmlParser The underlying {@link XmlPullParser} that will read the xml.
+ * @return An ApplicationSelfCertifiedNetworkCapabilities object.
+ * @throws InvalidTagException if the capabilities in xml config contains invalid tag.
+ * @throws XmlPullParserException if xml parsing failed.
+ * @throws IOException if unable to read the xml file properly.
+ */
+ @NonNull
+ public static ApplicationSelfCertifiedNetworkCapabilities createFromXml(
+ @NonNull final XmlPullParser xmlParser)
+ throws InvalidTagException, XmlPullParserException, IOException {
+ return new ApplicationSelfCertifiedNetworkCapabilities(parseXml(xmlParser));
+ }
+
+ private static long parseXml(@NonNull final XmlPullParser xmlParser)
+ throws InvalidTagException, XmlPullParserException, IOException {
+ long requestedNetworkCapabilities = 0;
+ final ArrayDeque<String> openTags = new ArrayDeque<>();
+
+ while (checkedNextTag(xmlParser, openTags) != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ // Validates the tag is "network-capabilities-declaration"
+ if (!xmlParser.getName().equals(NETWORK_CAPABILITIES_DECLARATION_TAG)) {
+ throw new InvalidTagException("Invalid tag: " + xmlParser.getName());
+ }
+
+ checkedNextTag(xmlParser, openTags);
+ int eventType = xmlParser.getEventType();
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ switch (eventType) {
+ case XmlPullParser.START_TAG:
+ // USES_NETWORK_CAPABILITY_TAG should directly be declared under
+ // NETWORK_CAPABILITIES_DECLARATION_TAG.
+ if (xmlParser.getName().equals(USES_NETWORK_CAPABILITY_TAG)
+ && openTags.size() == 1) {
+ int capability = parseDeclarationTag(xmlParser);
+ if (capability >= 0) {
+ requestedNetworkCapabilities |= 1L << capability;
+ }
+ } else {
+ Log.w(TAG, "Unknown tag: " + xmlParser.getName() + " ,tags stack size: "
+ + openTags.size());
+ }
+ break;
+ default:
+ break;
+ }
+ eventType = checkedNextTag(xmlParser, openTags);
+ }
+ // Checks all the tags are parsed.
+ if (!openTags.isEmpty()) {
+ throw new InvalidTagException("Unbalanced tag: " + openTags.peek());
+ }
+ return requestedNetworkCapabilities;
+ }
+
+ private static int parseDeclarationTag(@NonNull final XmlPullParser xmlParser) {
+ String name = null;
+ for (int i = 0; i < xmlParser.getAttributeCount(); i++) {
+ final String attrName = xmlParser.getAttributeName(i);
+ if (attrName.equals(NAME_TAG)) {
+ name = xmlParser.getAttributeValue(i);
+ } else {
+ Log.w(TAG, "Unknown attribute name: " + attrName);
+ }
+ }
+ if (name != null) {
+ switch (name) {
+ case PRIORITIZE_BANDWIDTH:
+ return NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH;
+ case PRIORITIZE_LATENCY:
+ return NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY;
+ default:
+ Log.w(TAG, "Unknown capability declaration name: " + name);
+ }
+ } else {
+ Log.w(TAG, "uses-network-capability name must be specified");
+ }
+ // Invalid capability
+ return -1;
+ }
+
+ private static int checkedNextTag(@NonNull final XmlPullParser xmlParser,
+ @NonNull final ArrayDeque<String> openTags)
+ throws XmlPullParserException, IOException, InvalidTagException {
+ if (xmlParser.getEventType() == XmlPullParser.START_TAG) {
+ openTags.addFirst(xmlParser.getName());
+ } else if (xmlParser.getEventType() == XmlPullParser.END_TAG) {
+ if (!openTags.isEmpty() && openTags.peekFirst().equals(xmlParser.getName())) {
+ openTags.removeFirst();
+ } else {
+ throw new InvalidTagException("Unbalanced tag: " + xmlParser.getName());
+ }
+ }
+ return xmlParser.next();
+ }
+
+ private ApplicationSelfCertifiedNetworkCapabilities(long requestedNetworkCapabilities) {
+ mRequestedNetworkCapabilities = requestedNetworkCapabilities;
+ }
+
+ /**
+ * Enforces self-certified capabilities are declared.
+ *
+ * @param networkCapabilities the input NetworkCapabilities to check against.
+ * @throws SecurityException if the capabilities are not properly self-declared.
+ */
+ public void enforceSelfCertifiedNetworkCapabilitiesDeclared(
+ @NonNull final NetworkCapabilities networkCapabilities) {
+ if (networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ && !hasPrioritizeBandwidth()) {
+ throw new SecurityException(
+ "Missing " + ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_BANDWIDTH
+ + " declaration");
+ }
+ if (networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ && !hasPrioritizeLatency()) {
+ throw new SecurityException(
+ "Missing " + ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_LATENCY
+ + " declaration");
+ }
+ }
+
+ /**
+ * Checks if NET_CAPABILITY_PRIORITIZE_LATENCY is declared.
+ */
+ private boolean hasPrioritizeLatency() {
+ return (mRequestedNetworkCapabilities & (1L
+ << NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)) != 0;
+ }
+
+ /**
+ * Checks if NET_CAPABILITY_PRIORITIZE_BANDWIDTH is declared.
+ */
+ private boolean hasPrioritizeBandwidth() {
+ return (mRequestedNetworkCapabilities & (1L
+ << NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)) != 0;
+ }
+}
diff --git a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
index 27be545..881c92d 100644
--- a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
@@ -16,10 +16,10 @@
package com.android.server.connectivity;
-import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET;
-import static android.net.SocketKeepalive.SUCCESS;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
+import static android.net.SocketKeepalive.MIN_INTERVAL_SEC;
+import static android.net.SocketKeepalive.SUCCESS_PAUSED;
+import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.SOL_SOCKET;
@@ -34,17 +34,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.net.INetd;
import android.net.ISocketKeepaliveCallback;
import android.net.MarkMaskParcel;
import android.net.Network;
-import android.net.NetworkAgent;
-import android.net.SocketKeepalive;
import android.net.SocketKeepalive.InvalidSocketException;
import android.os.FileUtils;
import android.os.Handler;
@@ -54,18 +48,21 @@
import android.os.SystemClock;
import android.system.ErrnoException;
import android.system.Os;
+import android.system.OsConstants;
import android.system.StructTimeval;
+import android.util.LocalLog;
import android.util.Log;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.modules.utils.build.SdkLevel;
+import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.DeviceConfigUtils;
import com.android.net.module.util.HexDump;
import com.android.net.module.util.SocketUtils;
import com.android.net.module.util.netlink.InetDiagMessage;
+import com.android.net.module.util.netlink.NetlinkMessage;
import com.android.net.module.util.netlink.NetlinkUtils;
import com.android.net.module.util.netlink.StructNlAttr;
@@ -84,25 +81,47 @@
* Manages automatic on/off socket keepalive requests.
*
* Provides methods to stop and start automatic keepalive requests, and keeps track of keepalives
- * across all networks. For non-automatic on/off keepalive request, this class just forwards the
- * requests to KeepaliveTracker. This class is tightly coupled to ConnectivityService. It is not
+ * across all networks. This class is tightly coupled to ConnectivityService. It is not
* thread-safe and its handle* methods must be called only from the ConnectivityService handler
* thread.
*/
public class AutomaticOnOffKeepaliveTracker {
private static final String TAG = "AutomaticOnOffKeepaliveTracker";
private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET6, AF_INET};
- private static final String ACTION_TCP_POLLING_ALARM =
- "com.android.server.connectivity.KeepaliveTracker.TCP_POLLING_ALARM";
- private static final String EXTRA_NETWORK = "network_id";
- private static final String EXTRA_SLOT = "slot";
- private static final long DEFAULT_TCP_POLLING_INTERVAL_MS = 120_000L;
+ private static final long LOW_TCP_POLLING_INTERVAL_MS = 1_000L;
+ private static final int ADJUST_TCP_POLLING_DELAY_MS = 2000;
private static final String AUTOMATIC_ON_OFF_KEEPALIVE_VERSION =
"automatic_on_off_keepalive_version";
+
+ // ConnectivityService parses message constants from itself and AutomaticOnOffKeepaliveTracker
+ // with MessageUtils for debugging purposes, and crashes if some messages have the same values.
+ private static final int BASE = 2000;
+ /**
+ * Sent by AutomaticOnOffKeepaliveTracker periodically (when relevant) to trigger monitor
+ * automatic keepalive request.
+ *
+ * NATT keepalives have an automatic mode where the system only sends keepalive packets when
+ * TCP sockets are open over a VPN. The system will check periodically for presence of
+ * such open sockets, and this message is what triggers the re-evaluation.
+ *
+ * obj = A Binder object associated with the keepalive.
+ */
+ public static final int CMD_MONITOR_AUTOMATIC_KEEPALIVE = BASE + 1;
+
+ /**
+ * Sent by AutomaticOnOffKeepaliveTracker to ConnectivityService to start a keepalive.
+ *
+ * obj = AutomaticKeepaliveInfo object
+ */
+ public static final int CMD_REQUEST_START_KEEPALIVE = BASE + 2;
+
/**
* States for {@code #AutomaticOnOffKeepalive}.
*
- * A new AutomaticOnOffKeepalive starts with STATE_ENABLED. The system will monitor
+ * If automatic mode is off for this keepalive, the state is STATE_ALWAYS_ON and it stays
+ * so for the entire lifetime of this object.
+ *
+ * If enabled, a new AutomaticOnOffKeepalive starts with STATE_ENABLED. The system will monitor
* the TCP sockets on VPN networks running on top of the specified network, and turn off
* keepalive if there is no TCP socket any of the VPN networks. Conversely, it will turn
* keepalive back on if any TCP socket is open on any of the VPN networks.
@@ -118,10 +137,12 @@
*/
private static final int STATE_ENABLED = 0;
private static final int STATE_SUSPENDED = 1;
+ private static final int STATE_ALWAYS_ON = 2;
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "STATE_" }, value = {
STATE_ENABLED,
- STATE_SUSPENDED
+ STATE_SUSPENDED,
+ STATE_ALWAYS_ON
})
private @interface AutomaticOnOffState {}
@@ -150,64 +171,121 @@
* This should be only updated in ConnectivityService handler thread.
*/
private final ArrayList<AutomaticOnOffKeepalive> mAutomaticOnOffKeepalives = new ArrayList<>();
+ // TODO: Remove this when TCP polling design is replaced with callback.
+ private long mTestLowTcpPollingTimerUntilMs = 0;
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (ACTION_TCP_POLLING_ALARM.equals(intent.getAction())) {
- Log.d(TAG, "Received TCP polling intent");
- final Network network = intent.getParcelableExtra(EXTRA_NETWORK);
- final int slot = intent.getIntExtra(EXTRA_SLOT, -1);
- mConnectivityServiceHandler.obtainMessage(
- NetworkAgent.CMD_MONITOR_AUTOMATIC_KEEPALIVE,
- slot, 0 , network).sendToTarget();
- }
- }
- };
+ private static final int MAX_EVENTS_LOGS = 40;
+ private final LocalLog mEventLog = new LocalLog(MAX_EVENTS_LOGS);
- private static class AutomaticOnOffKeepalive {
+ /**
+ * Information about a managed keepalive.
+ *
+ * The keepalive in mKi is managed by this object. This object can be in one of three states
+ * (in mAutomatiOnOffState) :
+ * • STATE_ALWAYS_ON : this keepalive is always on
+ * • STATE_ENABLED : this keepalive is currently on, and monitored for possibly being turned
+ * off if no TCP socket is open on the VPN.
+ * • STATE_SUSPENDED : this keepalive is currently off, and monitored for possibly being
+ * resumed if a TCP socket is open on the VPN.
+ * See the documentation for the states for more detail.
+ */
+ public class AutomaticOnOffKeepalive implements IBinder.DeathRecipient {
@NonNull
private final KeepaliveTracker.KeepaliveInfo mKi;
@NonNull
+ private final ISocketKeepaliveCallback mCallback;
+ @Nullable
private final FileDescriptor mFd;
- @NonNull
- private final PendingIntent mTcpPollingAlarm;
- private final int mSlot;
+ @Nullable
+ private final AlarmManager.OnAlarmListener mAlarmListener;
@AutomaticOnOffState
- private int mAutomaticOnOffState = STATE_ENABLED;
+ private int mAutomaticOnOffState;
+ @Nullable
+ private final Network mUnderpinnedNetwork;
- AutomaticOnOffKeepalive(@NonNull KeepaliveTracker.KeepaliveInfo ki,
- @NonNull Context context) throws InvalidSocketException {
+ AutomaticOnOffKeepalive(@NonNull final KeepaliveTracker.KeepaliveInfo ki,
+ final boolean autoOnOff, @Nullable Network underpinnedNetwork)
+ throws InvalidSocketException {
this.mKi = Objects.requireNonNull(ki);
- // A null fd is acceptable in KeepaliveInfo for backward compatibility of
- // PacketKeepalive API, but it should not happen here because legacy API cannot setup
- // automatic keepalive.
- Objects.requireNonNull(ki.mFd);
-
- // Get the slot from keepalive because the slot information may be missing when the
- // keepalive is stopped.
- this.mSlot = ki.getSlot();
- try {
- this.mFd = Os.dup(ki.mFd);
- } catch (ErrnoException e) {
- Log.e(TAG, "Cannot dup fd: ", e);
- throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
+ mCallback = ki.mCallback;
+ mUnderpinnedNetwork = underpinnedNetwork;
+ if (autoOnOff && mDependencies.isFeatureEnabled(AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
+ true /* defaultEnabled */)) {
+ mAutomaticOnOffState = STATE_ENABLED;
+ if (null == ki.mFd) {
+ throw new IllegalArgumentException("fd can't be null with automatic "
+ + "on/off keepalives");
+ }
+ try {
+ mFd = Os.dup(ki.mFd);
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Cannot dup fd: ", e);
+ throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
+ }
+ mAlarmListener = () -> mConnectivityServiceHandler.obtainMessage(
+ CMD_MONITOR_AUTOMATIC_KEEPALIVE, mCallback.asBinder())
+ .sendToTarget();
+ } else {
+ mAutomaticOnOffState = STATE_ALWAYS_ON;
+ // A null fd is acceptable in KeepaliveInfo for backward compatibility of
+ // PacketKeepalive API, but it must never happen with automatic keepalives.
+ // TODO : remove mFd from KeepaliveInfo or from this class.
+ mFd = ki.mFd;
+ mAlarmListener = null;
}
- mTcpPollingAlarm = createTcpPollingAlarmIntent(
- context, ki.getNai().network(), ki.getSlot());
+ }
+
+ @VisibleForTesting
+ public ISocketKeepaliveCallback getCallback() {
+ return mCallback;
+ }
+
+ public Network getNetwork() {
+ return mKi.getNai().network;
+ }
+
+ @Nullable
+ public Network getUnderpinnedNetwork() {
+ return mUnderpinnedNetwork;
}
public boolean match(Network network, int slot) {
- return this.mKi.getNai().network().equals(network) && this.mSlot == slot;
+ return mKi.getNai().network().equals(network) && mKi.getSlot() == slot;
}
- private static PendingIntent createTcpPollingAlarmIntent(@NonNull Context context,
- @NonNull Network network, int slot) {
- final Intent intent = new Intent(ACTION_TCP_POLLING_ALARM);
- intent.putExtra(EXTRA_NETWORK, network);
- intent.putExtra(EXTRA_SLOT, slot);
- return PendingIntent.getBroadcast(
- context, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE);
+ @Override
+ public void binderDied() {
+ mEventLog.log("Binder died : " + mCallback);
+ mConnectivityServiceHandler.post(() -> cleanupAutoOnOffKeepalive(this));
+ }
+
+ /** Close this automatic on/off keepalive */
+ public void close() {
+ // Close the duplicated fd that maintains the lifecycle of socket. If this fd was
+ // not duplicated this is a no-op.
+ FileUtils.closeQuietly(mFd);
+ }
+
+ private String getAutomaticOnOffStateName(int state) {
+ switch (state) {
+ case STATE_ENABLED:
+ return "STATE_ENABLED";
+ case STATE_SUSPENDED:
+ return "STATE_SUSPENDED";
+ case STATE_ALWAYS_ON:
+ return "STATE_ALWAYS_ON";
+ default:
+ Log.e(TAG, "Get unexpected state:" + state);
+ return Integer.toString(state);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "AutomaticOnOffKeepalive [ "
+ + mKi
+ + ", state=" + getAutomaticOnOffStateName(mAutomaticOnOffState)
+ + " ]";
}
}
@@ -225,62 +303,67 @@
mKeepaliveTracker = mDependencies.newKeepaliveTracker(
mContext, mConnectivityServiceHandler);
- if (SdkLevel.isAtLeastU()) {
- mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_TCP_POLLING_ALARM),
- null, handler);
- }
- mAlarmManager = mContext.getSystemService(AlarmManager.class);
+ mAlarmManager = mDependencies.getAlarmManager(context);
}
- private void startTcpPollingAlarm(@NonNull PendingIntent alarm) {
+ private void startTcpPollingAlarm(@NonNull AutomaticOnOffKeepalive ki) {
+ if (ki.mAlarmListener == null) return;
+
final long triggerAtMillis =
- SystemClock.elapsedRealtime() + DEFAULT_TCP_POLLING_INTERVAL_MS;
+ mDependencies.getElapsedRealtime() + getTcpPollingIntervalMs(ki);
// Setup a non-wake up alarm.
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, triggerAtMillis, alarm);
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, triggerAtMillis, null /* tag */,
+ ki.mAlarmListener, mConnectivityServiceHandler);
}
/**
* Determine if any state transition is needed for the specific automatic keepalive.
*/
- public void handleMonitorAutomaticKeepalive(@NonNull Network network, int slot, int vpnNetId) {
- final AutomaticOnOffKeepalive autoKi = findAutomaticOnOffKeepalive(network, slot);
- // This may happen if the keepalive is removed by the app, and the alarm is fired at the
- // same time.
- if (autoKi == null) return;
+ public void handleMonitorAutomaticKeepalive(@NonNull final AutomaticOnOffKeepalive ki,
+ final int vpnNetId) {
+ // Might happen if the automatic keepalive was removed by the app just as the alarm fires.
+ if (!mAutomaticOnOffKeepalives.contains(ki)) return;
+ if (STATE_ALWAYS_ON == ki.mAutomaticOnOffState) {
+ throw new IllegalStateException("Should not monitor non-auto keepalive");
+ }
- handleMonitorTcpConnections(autoKi, vpnNetId);
+ handleMonitorTcpConnections(ki, vpnNetId);
}
/**
* Determine if disable or re-enable keepalive is needed or not based on TCP sockets status.
*/
private void handleMonitorTcpConnections(@NonNull AutomaticOnOffKeepalive ki, int vpnNetId) {
+ // Might happen if the automatic keepalive was removed by the app just as the alarm fires.
+ if (!mAutomaticOnOffKeepalives.contains(ki)) return;
+ if (STATE_ALWAYS_ON == ki.mAutomaticOnOffState) {
+ throw new IllegalStateException("Should not monitor non-auto keepalive");
+ }
if (!isAnyTcpSocketConnected(vpnNetId)) {
// No TCP socket exists. Stop keepalive if ENABLED, and remain SUSPENDED if currently
// SUSPENDED.
if (ki.mAutomaticOnOffState == STATE_ENABLED) {
ki.mAutomaticOnOffState = STATE_SUSPENDED;
- handleSuspendKeepalive(ki.mKi.mNai, ki.mSlot, SUCCESS);
+ handlePauseKeepalive(ki.mKi);
}
} else {
handleMaybeResumeKeepalive(ki);
}
// TODO: listen to socket status instead of periodically check.
- startTcpPollingAlarm(ki.mTcpPollingAlarm);
+ startTcpPollingAlarm(ki);
}
/**
- * Resume keepalive for this slot on this network, if it wasn't already resumed.
+ * Resume an auto on/off keepalive, unless it's already resumed
+ * @param autoKi the keepalive to resume
*/
- public void handleMaybeResumeKeepalive(@NonNull final Network network, final int slot) {
- final AutomaticOnOffKeepalive autoKi = findAutomaticOnOffKeepalive(network, slot);
- // This may happen if the keepalive is removed by the app, and the alarm is fired at
- // the same time.
- if (autoKi == null) return;
- handleMaybeResumeKeepalive(autoKi);
- }
-
- private void handleMaybeResumeKeepalive(@NonNull AutomaticOnOffKeepalive autoKi) {
+ public void handleMaybeResumeKeepalive(@NonNull AutomaticOnOffKeepalive autoKi) {
+ mEventLog.log("Resume keepalive " + autoKi.mCallback + " on " + autoKi.getNetwork());
+ // Might happen if the automatic keepalive was removed by the app just as the alarm fires.
+ if (!mAutomaticOnOffKeepalives.contains(autoKi)) return;
+ if (STATE_ALWAYS_ON == autoKi.mAutomaticOnOffState) {
+ throw new IllegalStateException("Should not resume non-auto keepalive");
+ }
if (autoKi.mAutomaticOnOffState == STATE_ENABLED) return;
KeepaliveTracker.KeepaliveInfo newKi;
try {
@@ -289,35 +372,23 @@
newKi = autoKi.mKi.withFd(autoKi.mFd);
} catch (InvalidSocketException | IllegalArgumentException | SecurityException e) {
Log.e(TAG, "Fail to construct keepalive", e);
- mKeepaliveTracker.notifyErrorCallback(autoKi.mKi.mCallback, ERROR_INVALID_SOCKET);
+ mKeepaliveTracker.notifyErrorCallback(autoKi.mCallback, ERROR_INVALID_SOCKET);
return;
}
autoKi.mAutomaticOnOffState = STATE_ENABLED;
- handleResumeKeepalive(mConnectivityServiceHandler.obtainMessage(
- NetworkAgent.CMD_START_SOCKET_KEEPALIVE,
- autoKi.mAutomaticOnOffState, 0, newKi));
+ handleResumeKeepalive(newKi);
}
- private int findAutomaticOnOffKeepaliveIndex(@NonNull Network network, int slot) {
- ensureRunningOnHandlerThread();
-
- int index = 0;
- for (AutomaticOnOffKeepalive ki : mAutomaticOnOffKeepalives) {
- if (ki.match(network, slot)) {
- return index;
- }
- index++;
- }
- return -1;
- }
-
+ /**
+ * Find the AutomaticOnOffKeepalive associated with a given callback.
+ * @return the keepalive associated with this callback, or null if none
+ */
@Nullable
- private AutomaticOnOffKeepalive findAutomaticOnOffKeepalive(@NonNull Network network,
- int slot) {
+ public AutomaticOnOffKeepalive getKeepaliveForBinder(@NonNull final IBinder token) {
ensureRunningOnHandlerThread();
- final int index = findAutomaticOnOffKeepaliveIndex(network, slot);
- return (index >= 0) ? mAutomaticOnOffKeepalives.get(index) : null;
+ return CollectionUtils.findFirst(mAutomaticOnOffKeepalives,
+ it -> it.mCallback.asBinder().equals(token));
}
/**
@@ -333,6 +404,7 @@
* Handle stop all keepalives on the specific network.
*/
public void handleStopAllKeepalives(NetworkAgentInfo nai, int reason) {
+ mEventLog.log("Stop all keepalives on " + nai.network + " because " + reason);
mKeepaliveTracker.handleStopAllKeepalives(nai, reason);
final List<AutomaticOnOffKeepalive> matches =
CollectionUtils.filter(mAutomaticOnOffKeepalives, it -> it.mKi.getNai() == nai);
@@ -347,64 +419,63 @@
* The message is expected to contain a KeepaliveTracker.KeepaliveInfo.
*/
public void handleStartKeepalive(Message message) {
- mKeepaliveTracker.handleStartKeepalive(message);
+ final AutomaticOnOffKeepalive autoKi = (AutomaticOnOffKeepalive) message.obj;
+ mEventLog.log("Start keepalive " + autoKi.mCallback + " on " + autoKi.getNetwork());
+ mKeepaliveTracker.handleStartKeepalive(autoKi.mKi);
// Add automatic on/off request into list to track its life cycle.
- final boolean automaticOnOff = message.arg1 != 0
- && mDependencies.isFeatureEnabled(AUTOMATIC_ON_OFF_KEEPALIVE_VERSION);
- if (automaticOnOff) {
- final KeepaliveTracker.KeepaliveInfo ki = (KeepaliveTracker.KeepaliveInfo) message.obj;
- AutomaticOnOffKeepalive autoKi;
- try {
- // CAREFUL : mKeepaliveTracker.handleStartKeepalive will assign |ki.mSlot| after
- // pulling |ki| from the message. The constructor below will read this member
- // (through ki.getSlot()) and therefore actively relies on handleStartKeepalive
- // having assigned this member before this is called.
- // TODO : clean this up by assigning the slot at the start of this method instead
- // and ideally removing the mSlot member from KeepaliveInfo.
- autoKi = new AutomaticOnOffKeepalive(ki, mContext);
- } catch (SocketKeepalive.InvalidSocketException | IllegalArgumentException e) {
- Log.e(TAG, "Fail to construct keepalive", e);
- mKeepaliveTracker.notifyErrorCallback(ki.mCallback, ERROR_INVALID_SOCKET);
- return;
- }
- mAutomaticOnOffKeepalives.add(autoKi);
- startTcpPollingAlarm(autoKi.mTcpPollingAlarm);
+ try {
+ autoKi.mKi.mCallback.asBinder().linkToDeath(autoKi, 0);
+ } catch (RemoteException e) {
+ // The underlying keepalive performs its own cleanup
+ autoKi.binderDied();
+ return;
+ }
+ mAutomaticOnOffKeepalives.add(autoKi);
+ if (STATE_ALWAYS_ON != autoKi.mAutomaticOnOffState) {
+ startTcpPollingAlarm(autoKi);
}
}
- private void handleResumeKeepalive(Message message) {
- mKeepaliveTracker.handleStartKeepalive(message);
+ private void handleResumeKeepalive(@NonNull final KeepaliveTracker.KeepaliveInfo ki) {
+ mKeepaliveTracker.handleStartKeepalive(ki);
+ mEventLog.log("Resumed successfully keepalive " + ki.mCallback + " on " + ki.mNai);
}
- private void handleSuspendKeepalive(NetworkAgentInfo nai, int slot, int reason) {
- mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
+ private void handlePauseKeepalive(@NonNull final KeepaliveTracker.KeepaliveInfo ki) {
+ mEventLog.log("Suspend keepalive " + ki.mCallback + " on " + ki.mNai);
+ // TODO : mKT.handleStopKeepalive should take a KeepaliveInfo instead
+ mKeepaliveTracker.handleStopKeepalive(ki.getNai(), ki.getSlot(), SUCCESS_PAUSED);
}
/**
* Handle stop keepalives on the specific network with given slot.
*/
- public void handleStopKeepalive(NetworkAgentInfo nai, int slot, int reason) {
- final AutomaticOnOffKeepalive autoKi = findAutomaticOnOffKeepalive(nai.network, slot);
-
- // Let the original keepalive do the stop first, and then clean up the keepalive if it's an
- // automatic keepalive.
- if (autoKi == null || autoKi.mAutomaticOnOffState == STATE_ENABLED) {
- mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
+ public void handleStopKeepalive(@NonNull final AutomaticOnOffKeepalive autoKi, int reason) {
+ mEventLog.log("Stop keepalive " + autoKi.mCallback + " because " + reason);
+ // Stop the keepalive unless it was suspended. This includes the case where it's managed
+ // but enabled, and the case where it's always on.
+ if (autoKi.mAutomaticOnOffState != STATE_SUSPENDED) {
+ final KeepaliveTracker.KeepaliveInfo ki = autoKi.mKi;
+ mKeepaliveTracker.handleStopKeepalive(ki.getNai(), ki.getSlot(), reason);
+ } else {
+ mKeepaliveTracker.finalizePausedKeepalive(autoKi.mKi);
}
- // Not an AutomaticOnOffKeepalive.
- if (autoKi == null) return;
-
cleanupAutoOnOffKeepalive(autoKi);
}
private void cleanupAutoOnOffKeepalive(@NonNull final AutomaticOnOffKeepalive autoKi) {
ensureRunningOnHandlerThread();
- mAlarmManager.cancel(autoKi.mTcpPollingAlarm);
- // Close the duplicated fd that maintains the lifecycle of socket.
- FileUtils.closeQuietly(autoKi.mFd);
- mAutomaticOnOffKeepalives.remove(autoKi);
+ autoKi.close();
+ if (null != autoKi.mAlarmListener) mAlarmManager.cancel(autoKi.mAlarmListener);
+
+ // If the KI is not in the array, it's because it was already removed, or it was never
+ // added ; the only ways this can happen is if the keepalive is stopped by the app and the
+ // app dies immediately, or if the app died before the link to death could be registered.
+ if (!mAutomaticOnOffKeepalives.remove(autoKi)) return;
+
+ autoKi.mKi.mCallback.asBinder().unlinkToDeath(autoKi, 0);
}
/**
@@ -420,13 +491,22 @@
@NonNull String srcAddrString,
int srcPort,
@NonNull String dstAddrString,
- int dstPort, boolean automaticOnOffKeepalives) {
+ int dstPort, boolean automaticOnOffKeepalives, @Nullable Network underpinnedNetwork) {
final KeepaliveTracker.KeepaliveInfo ki = mKeepaliveTracker.makeNattKeepaliveInfo(nai, fd,
intervalSeconds, cb, srcAddrString, srcPort, dstAddrString, dstPort);
- if (null != ki) {
- mConnectivityServiceHandler.obtainMessage(NetworkAgent.CMD_START_SOCKET_KEEPALIVE,
- // TODO : move ConnectivityService#encodeBool to a static lib.
- automaticOnOffKeepalives ? 1 : 0, 0, ki).sendToTarget();
+ if (null == ki) return;
+ try {
+ final AutomaticOnOffKeepalive autoKi = new AutomaticOnOffKeepalive(ki,
+ automaticOnOffKeepalives, underpinnedNetwork);
+ mEventLog.log("Start natt keepalive " + cb + " on " + nai.network
+ + " " + srcAddrString + ":" + srcPort
+ + " → " + dstAddrString + ":" + dstPort
+ + " auto=" + autoKi
+ + " underpinned=" + underpinnedNetwork);
+ mConnectivityServiceHandler.obtainMessage(CMD_REQUEST_START_KEEPALIVE, autoKi)
+ .sendToTarget();
+ } catch (InvalidSocketException e) {
+ mKeepaliveTracker.notifyErrorCallback(cb, e.error);
}
}
@@ -444,13 +524,23 @@
@NonNull String srcAddrString,
@NonNull String dstAddrString,
int dstPort,
- boolean automaticOnOffKeepalives) {
+ boolean automaticOnOffKeepalives,
+ @Nullable Network underpinnedNetwork) {
final KeepaliveTracker.KeepaliveInfo ki = mKeepaliveTracker.makeNattKeepaliveInfo(nai, fd,
resourceId, intervalSeconds, cb, srcAddrString, dstAddrString, dstPort);
- if (null != ki) {
- mConnectivityServiceHandler.obtainMessage(NetworkAgent.CMD_START_SOCKET_KEEPALIVE,
- // TODO : move ConnectivityService#encodeBool to a static lib.
- automaticOnOffKeepalives ? 1 : 0, 0, ki).sendToTarget();
+ if (null == ki) return;
+ try {
+ final AutomaticOnOffKeepalive autoKi = new AutomaticOnOffKeepalive(ki,
+ automaticOnOffKeepalives, underpinnedNetwork);
+ mEventLog.log("Start natt keepalive " + cb + " on " + nai.network
+ + " " + srcAddrString
+ + " → " + dstAddrString + ":" + dstPort
+ + " auto=" + autoKi
+ + " underpinned=" + underpinnedNetwork);
+ mConnectivityServiceHandler.obtainMessage(CMD_REQUEST_START_KEEPALIVE, autoKi)
+ .sendToTarget();
+ } catch (InvalidSocketException e) {
+ mKeepaliveTracker.notifyErrorCallback(cb, e.error);
}
}
@@ -471,9 +561,15 @@
@NonNull ISocketKeepaliveCallback cb) {
final KeepaliveTracker.KeepaliveInfo ki = mKeepaliveTracker.makeTcpKeepaliveInfo(nai, fd,
intervalSeconds, cb);
- if (null != ki) {
- mConnectivityServiceHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, ki)
+ if (null == ki) return;
+ try {
+ final AutomaticOnOffKeepalive autoKi = new AutomaticOnOffKeepalive(ki,
+ false /* autoOnOff, tcp keepalives are never auto on/off */,
+ null /* underpinnedNetwork, tcp keepalives do not refer to this */);
+ mConnectivityServiceHandler.obtainMessage(CMD_REQUEST_START_KEEPALIVE, autoKi)
.sendToTarget();
+ } catch (InvalidSocketException e) {
+ mKeepaliveTracker.notifyErrorCallback(cb, e.error);
}
}
@@ -481,8 +577,24 @@
* Dump AutomaticOnOffKeepaliveTracker state.
*/
public void dump(IndentingPrintWriter pw) {
- // TODO: Dump the necessary information for automatic on/off keepalive.
mKeepaliveTracker.dump(pw);
+ // Reading DeviceConfig will check if the calling uid and calling package name are the same.
+ // Clear calling identity to align the calling uid and package so that it won't fail if cts
+ // would like to do the dump()
+ final boolean featureEnabled = BinderUtils.withCleanCallingIdentity(
+ () -> mDependencies.isFeatureEnabled(AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
+ true /* defaultEnabled */));
+ pw.println("AutomaticOnOff enabled: " + featureEnabled);
+ pw.increaseIndent();
+ for (AutomaticOnOffKeepalive autoKi : mAutomaticOnOffKeepalives) {
+ pw.println(autoKi.toString());
+ }
+ pw.decreaseIndent();
+
+ pw.println("Events (most recent first):");
+ pw.increaseIndent();
+ mEventLog.reverseDump(pw);
+ pw.decreaseIndent();
}
/**
@@ -552,6 +664,16 @@
bytes.position(startPos + SOCKDIAG_MSG_HEADER_SIZE);
if (isTargetTcpSocket(bytes, nlmsgLen, networkMark, networkMask)) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ bytes.position(startPos);
+ final InetDiagMessage diagMsg = (InetDiagMessage) NetlinkMessage.parse(
+ bytes, OsConstants.NETLINK_INET_DIAG);
+ Log.d(TAG, String.format("Found open TCP connection by uid %d to %s"
+ + " cookie %d",
+ diagMsg.inetDiagMsg.idiag_uid,
+ diagMsg.inetDiagMsg.id.remSocketAddress,
+ diagMsg.inetDiagMsg.id.cookie));
+ }
return true;
}
}
@@ -602,6 +724,26 @@
}
}
+ private long getTcpPollingIntervalMs(@NonNull AutomaticOnOffKeepalive ki) {
+ final boolean useLowTimer = mTestLowTcpPollingTimerUntilMs > System.currentTimeMillis();
+ // Adjust the polling interval to be smaller than the keepalive delay to preserve
+ // some time for the system to restart the keepalive.
+ final int timer = ki.mKi.getKeepaliveIntervalSec() * 1000 - ADJUST_TCP_POLLING_DELAY_MS;
+ if (timer < MIN_INTERVAL_SEC) {
+ Log.wtf(TAG, "Unreasonably low keepalive delay: " + ki.mKi.getKeepaliveIntervalSec());
+ }
+ return useLowTimer ? LOW_TCP_POLLING_INTERVAL_MS : Math.max(timer, MIN_INTERVAL_SEC);
+ }
+
+ /**
+ * Temporarily use low TCP polling timer for testing.
+ * The value works when the time set is more than {@link System.currentTimeMillis()}.
+ */
+ public void handleSetTestLowTcpPollingTimer(long timeMs) {
+ Log.d(TAG, "handleSetTestLowTcpPollingTimer: " + timeMs);
+ mTestLowTcpPollingTimerUntilMs = timeMs;
+ }
+
/**
* Dependencies class for testing.
*/
@@ -651,6 +793,13 @@
}
/**
+ * Get an instance of AlarmManager
+ */
+ public AlarmManager getAlarmManager(@NonNull final Context ctx) {
+ return ctx.getSystemService(AlarmManager.class);
+ }
+
+ /**
* Receive the response message from kernel via given {@code FileDescriptor}.
* The usage should follow the {@code #sendRequest} call with the same
* FileDescriptor.
@@ -682,10 +831,22 @@
* Find out if a feature is enabled from DeviceConfig.
*
* @param name The name of the property to look up.
+ * @param defaultEnabled whether to consider the feature enabled in the absence of
+ * the flag. This MUST be a statically-known constant.
* @return whether the feature is enabled
*/
- public boolean isFeatureEnabled(@NonNull final String name) {
- return DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_CONNECTIVITY, name);
+ public boolean isFeatureEnabled(@NonNull final String name, final boolean defaultEnabled) {
+ return DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
+ defaultEnabled);
+ }
+
+ /**
+ * Returns milliseconds since boot, including time spent in sleep.
+ *
+ * @return elapsed milliseconds since boot.
+ */
+ public long getElapsedRealtime() {
+ return SystemClock.elapsedRealtime();
}
}
}
diff --git a/service/src/com/android/server/connectivity/InvalidTagException.java b/service/src/com/android/server/connectivity/InvalidTagException.java
new file mode 100644
index 0000000..b924d27
--- /dev/null
+++ b/service/src/com/android/server/connectivity/InvalidTagException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 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.server.connectivity;
+
+
+/**
+ * An exception thrown when a Tag is not valid in self_certified_network_capabilities.xml.
+ */
+public class InvalidTagException extends Exception {
+
+ public InvalidTagException(String message) {
+ super(message);
+ }
+}
diff --git a/service/src/com/android/server/connectivity/KeepaliveTracker.java b/service/src/com/android/server/connectivity/KeepaliveTracker.java
index 03f8f3e..60485b3 100644
--- a/service/src/com/android/server/connectivity/KeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/KeepaliveTracker.java
@@ -32,6 +32,7 @@
import static android.net.SocketKeepalive.MIN_INTERVAL_SEC;
import static android.net.SocketKeepalive.NO_KEEPALIVE;
import static android.net.SocketKeepalive.SUCCESS;
+import static android.net.SocketKeepalive.SUCCESS_PAUSED;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -49,7 +50,6 @@
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.system.ErrnoException;
@@ -58,6 +58,7 @@
import android.util.Pair;
import com.android.connectivity.resources.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.net.module.util.HexDump;
import com.android.net.module.util.IpUtils;
@@ -125,15 +126,20 @@
* All information about this keepalive is known at construction time except the slot number,
* which is only returned when the hardware has successfully started the keepalive.
*/
- class KeepaliveInfo implements IBinder.DeathRecipient {
- // Bookkeeping data.
+ @VisibleForTesting
+ public class KeepaliveInfo implements IBinder.DeathRecipient {
+ // TODO : remove this member. Only AutoOnOffKeepalive should have a reference to this.
public final ISocketKeepaliveCallback mCallback;
+ // Bookkeeping data.
private final int mUid;
private final int mPid;
private final boolean mPrivileged;
public final NetworkAgentInfo mNai;
private final int mType;
public final FileDescriptor mFd;
+ // True if this was resumed from a previously turned off keepalive, otherwise false.
+ // This is necessary to send the correct callbacks.
+ public final boolean mResumed;
public static final int TYPE_NATT = 1;
public static final int TYPE_TCP = 2;
@@ -160,6 +166,16 @@
int interval,
int type,
@Nullable FileDescriptor fd) throws InvalidSocketException {
+ this(callback, nai, packet, interval, type, fd, false /* resumed */);
+ }
+
+ KeepaliveInfo(@NonNull ISocketKeepaliveCallback callback,
+ @NonNull NetworkAgentInfo nai,
+ @NonNull KeepalivePacketData packet,
+ int interval,
+ int type,
+ @Nullable FileDescriptor fd,
+ boolean resumed) throws InvalidSocketException {
mCallback = callback;
mPid = Binder.getCallingPid();
mUid = Binder.getCallingUid();
@@ -169,6 +185,7 @@
mPacket = packet;
mInterval = interval;
mType = type;
+ mResumed = resumed;
// For SocketKeepalive, a dup of fd is kept in mFd so the source port from which the
// keepalives are sent cannot be reused by another app even if the fd gets closed by
@@ -232,6 +249,8 @@
/** Called when the application process is killed. */
public void binderDied() {
+ // TODO b/267106526 : this is not called on the handler thread but stop() happily
+ // assumes it is, which means this is a pretty dangerous race condition.
stop(BINDER_DIED);
}
@@ -245,6 +264,10 @@
return mSlot;
}
+ int getKeepaliveIntervalSec() {
+ return mInterval;
+ }
+
private int checkNetworkConnected() {
if (!mNai.networkInfo.isConnectedOrConnecting()) {
return ERROR_INVALID_NETWORK;
@@ -327,6 +350,10 @@
}
void start(int slot) {
+ // BINDER_DIED can happen if the binder died before the KeepaliveInfo was created and
+ // the constructor set the state to BINDER_DIED. If that's the case, the KI is already
+ // cleaned up.
+ if (BINDER_DIED == mStartedState) return;
mSlot = slot;
int error = isValid();
if (error == SUCCESS) {
@@ -371,7 +398,10 @@
// To prevent races from re-entrance of stop(), return if the state is already stopping.
// This might happen if multiple event sources stop keepalive in a short time. Such as
// network disconnect after user calls stop(), or tear down socket after binder died.
- if (mStartedState == STOPPING) return;
+ // Note that it's always possible this method is called by the auto keepalive timer
+ // or any other way after the binder died, hence the check for BINDER_DIED. If the
+ // binder has died, then the KI has already been cleaned up.
+ if (mStartedState == STOPPING || mStartedState == BINDER_DIED) return;
// Store the reason of stopping, and report it after the keepalive is fully stopped.
if (mStopReason != ERROR_STOP_REASON_UNINITIALIZED) {
@@ -382,9 +412,10 @@
+ ": " + reason);
switch (mStartedState) {
case NOT_STARTED:
- // Remove the reference of the keepalive that meet error before starting,
+ // Remove the reference to this keepalive that had an error before starting,
// e.g. invalid parameter.
cleanupStoppedKeepalive(mNai, mSlot);
+ if (BINDER_DIED == reason) mStartedState = BINDER_DIED;
break;
default:
mStartedState = STOPPING;
@@ -422,7 +453,8 @@
* Construct a new KeepaliveInfo from existing KeepaliveInfo with a new fd.
*/
public KeepaliveInfo withFd(@NonNull FileDescriptor fd) throws InvalidSocketException {
- return new KeepaliveInfo(mCallback, mNai, mPacket, mInterval, mType, fd);
+ return new KeepaliveInfo(mCallback, mNai, mPacket, mInterval, mType, fd,
+ true /* resumed */);
}
}
@@ -456,8 +488,7 @@
/**
* Handle start keepalives with the message.
*/
- public void handleStartKeepalive(Message message) {
- KeepaliveInfo ki = (KeepaliveInfo) message.obj;
+ public void handleStartKeepalive(KeepaliveInfo ki) {
NetworkAgentInfo nai = ki.getNai();
int slot = findFirstFreeSlot(nai);
mKeepalives.get(nai).put(slot, ki);
@@ -524,6 +555,12 @@
} catch (RemoteException e) {
Log.w(TAG, "Discarded onStop callback: " + reason);
}
+ } else if (reason == SUCCESS_PAUSED) {
+ try {
+ ki.mCallback.onPaused();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Discarded onPaused callback: " + reason);
+ }
} else if (reason == DATA_RECEIVED) {
try {
ki.mCallback.onDataReceived();
@@ -541,6 +578,25 @@
ki.unlinkDeathRecipient();
}
+ /**
+ * Finalize a paused keepalive.
+ *
+ * This will simply send the onStopped() callback after checking that this keepalive is
+ * indeed paused.
+ *
+ * @param ki the keepalive to finalize
+ */
+ public void finalizePausedKeepalive(@NonNull final KeepaliveInfo ki) {
+ if (SUCCESS_PAUSED != ki.mStopReason) {
+ throw new IllegalStateException("Keepalive is not paused");
+ }
+ try {
+ ki.mCallback.onStopped();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Discarded onStopped callback while finalizing paused keepalive");
+ }
+ }
+
public void handleCheckKeepalivesStillValid(NetworkAgentInfo nai) {
HashMap <Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
if (networkKeepalives != null) {
@@ -590,9 +646,14 @@
Log.d(TAG, "Started keepalive " + slot + " on " + nai.toShortString());
ki.mStartedState = KeepaliveInfo.STARTED;
try {
- ki.mCallback.onStarted(slot);
+ if (ki.mResumed) {
+ ki.mCallback.onResumed();
+ } else {
+ ki.mCallback.onStarted();
+ }
} catch (RemoteException e) {
- Log.w(TAG, "Discarded onStarted(" + slot + ") callback");
+ Log.w(TAG, "Discarded " + (ki.mResumed ? "onResumed" : "onStarted")
+ + " callback for slot " + slot);
}
} else {
Log.d(TAG, "Failed to start keepalive " + slot + " on " + nai.toShortString()
diff --git a/service/src/com/android/server/connectivity/NetworkNotificationManager.java b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
index 45da0ea..cdc0aa9 100644
--- a/service/src/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
@@ -22,6 +22,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import android.annotation.NonNull;
+import android.app.ActivityOptions;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -33,6 +34,8 @@
import android.net.NetworkSpecifier;
import android.net.TelephonyNetworkSpecifier;
import android.net.wifi.WifiInfo;
+import android.os.Build;
+import android.os.Bundle;
import android.os.UserHandle;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -45,6 +48,7 @@
import com.android.connectivity.resources.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.modules.utils.build.SdkLevel;
public class NetworkNotificationManager {
@@ -328,7 +332,26 @@
}
try {
- intent.send();
+ Bundle options = null;
+
+ if (SdkLevel.isAtLeastU() && intent.isActivity()) {
+ // Also check SDK_INT >= T separately, as the linter in some T-based branches does
+ // not recognize "isAtLeastU && something" as an SDK check for T+ APIs.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ // Android U requires pending intent background start mode to be specified:
+ // See #background-activity-restrictions in
+ // https://developer.android.com/about/versions/14/behavior-changes-14
+ // But setPendingIntentBackgroundActivityStartMode is U+, and replaces
+ // setPendingIntentBackgroundActivityLaunchAllowed which is T+ but deprecated.
+ // Use setPendingIntentBackgroundActivityLaunchAllowed as the U+ version is not
+ // yet available in all branches.
+ final ActivityOptions activityOptions = ActivityOptions.makeBasic();
+ activityOptions.setPendingIntentBackgroundActivityLaunchAllowed(true);
+ options = activityOptions.toBundle();
+ }
+ }
+
+ intent.send(null, 0, null, null, null, null, options);
} catch (PendingIntent.CanceledException e) {
Log.e(TAG, "Error sending dialog PendingIntent", e);
}
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index 5c9cc63..8e47235 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -65,7 +65,7 @@
defaults: ["jarjar-rules-combine-defaults"],
srcs: [
"tethering-jni-jarjar-rules.txt",
- ":connectivity-jarjar-rules",
+ ":frameworks-net-tests-jarjar-rules",
":TetheringTestsJarJarRules",
":NetworkStackJarJarRules",
],
diff --git a/tests/common/AndroidTest_Coverage.xml b/tests/common/AndroidTest_Coverage.xml
index 48d26b8..c94ec27 100644
--- a/tests/common/AndroidTest_Coverage.xml
+++ b/tests/common/AndroidTest_Coverage.xml
@@ -13,7 +13,7 @@
limitations under the License.
-->
<configuration description="Runs coverage tests for Connectivity">
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="test-file-name" value="ConnectivityCoverageTests.apk" />
<option name="install-arg" value="-t" />
</target_preparer>
diff --git a/tests/common/java/android/net/LinkPropertiesTest.java b/tests/common/java/android/net/LinkPropertiesTest.java
index 5ee375f..09f5d6e 100644
--- a/tests/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/common/java/android/net/LinkPropertiesTest.java
@@ -32,6 +32,7 @@
import android.compat.testing.PlatformCompatChangeRule;
import android.net.LinkProperties.ProvisioningChange;
+import android.net.connectivity.ConnectivityCompatChanges;
import android.os.Build;
import android.system.OsConstants;
import android.util.ArraySet;
@@ -1261,7 +1262,7 @@
@Test @IgnoreUpTo(Build.VERSION_CODES.R)
@CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
- @EnableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
+ @EnableCompatChanges({ConnectivityCompatChanges.EXCLUDED_ROUTES})
public void testHasExcludeRoute() {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -1274,7 +1275,7 @@
@Test @IgnoreUpTo(Build.VERSION_CODES.R)
@CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
- @EnableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
+ @EnableCompatChanges({ConnectivityCompatChanges.EXCLUDED_ROUTES})
public void testRouteAddWithSameKey() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("wlan0");
@@ -1348,14 +1349,14 @@
@Test @IgnoreUpTo(Build.VERSION_CODES.R)
@CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
- @EnableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
+ @EnableCompatChanges({ConnectivityCompatChanges.EXCLUDED_ROUTES})
public void testExcludedRoutesEnabledByCompatChange() {
assertExcludeRoutesVisible();
}
@Test @IgnoreUpTo(Build.VERSION_CODES.R)
@CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
- @DisableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
+ @DisableCompatChanges({ConnectivityCompatChanges.EXCLUDED_ROUTES})
public void testExcludedRoutesDisabledByCompatChange() {
checkExcludeRoutesNotVisibleAfterS();
}
diff --git a/tests/common/java/android/net/NetworkCapabilitiesTest.java b/tests/common/java/android/net/NetworkCapabilitiesTest.java
index 7b374d2..aae3425 100644
--- a/tests/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/common/java/android/net/NetworkCapabilitiesTest.java
@@ -21,6 +21,7 @@
import static android.net.NetworkCapabilities.MIN_TRANSPORT;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
@@ -36,6 +37,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
@@ -113,6 +115,9 @@
private static final int TEST_SUBID2 = 2;
private static final int TEST_SUBID3 = 3;
+ private static final Set<Integer> TEST_NETWORKS_EXTRA_ALLOWED_CAPS_ON_NON_CELL =
+ Set.of(NET_CAPABILITY_CBS, NET_CAPABILITY_DUN, NET_CAPABILITY_RCS);
+
@Rule
public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule();
@@ -1321,16 +1326,31 @@
}
@Test
- public void testRestrictCapabilitiesForTestNetworkByNotOwnerWithRestrictedNc() {
- testRestrictCapabilitiesForTestNetworkWithRestrictedNc(false /* isOwner */);
+ public void testRestrictCapabilitiesForTestNetworkRestrictedNc_NotOwner_NotCell() {
+ testRestrictCapabilitiesForTestNetworkWithRestrictedNc(
+ false /* isOwner */, false /* isCell */);
}
@Test
- public void testRestrictCapabilitiesForTestNetworkByOwnerWithRestrictedNc() {
- testRestrictCapabilitiesForTestNetworkWithRestrictedNc(true /* isOwner */);
+ public void testRestrictCapabilitiesForTestNetworkRestrictedNc_Owner_NotCell() {
+ testRestrictCapabilitiesForTestNetworkWithRestrictedNc(
+ true /* isOwner */, false /* isCell */);
}
- private void testRestrictCapabilitiesForTestNetworkWithRestrictedNc(boolean isOwner) {
+ @Test
+ public void testRestrictCapabilitiesForTestNetworkRestrictedNc_NotOwner_Cell() {
+ testRestrictCapabilitiesForTestNetworkWithRestrictedNc(
+ false /* isOwner */, true /* isCell */);
+ }
+
+ @Test
+ public void testRestrictCapabilitiesForTestNetworkRestrictedNc_Owner_Cell() {
+ testRestrictCapabilitiesForTestNetworkWithRestrictedNc(
+ true /* isOwner */, false /* isCell */);
+ }
+
+ private void testRestrictCapabilitiesForTestNetworkWithRestrictedNc(
+ boolean isOwner, boolean isCell) {
final int ownerUid = 1234;
final int signalStrength = -80;
final int[] administratorUids = {1001, ownerUid};
@@ -1339,29 +1359,50 @@
// the networkCapabilities will contain more than one transport type. However,
// networkCapabilities must have a single transport specified to use NetworkSpecifier. Thus,
// do not verify this part since it's verified in other tests.
- final NetworkCapabilities restrictedNc = new NetworkCapabilities.Builder()
+ final NetworkCapabilities.Builder restrictedNcBuilder = new NetworkCapabilities.Builder()
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
- .addTransportType(TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_MMS)
.addCapability(NET_CAPABILITY_NOT_METERED)
.setAdministratorUids(administratorUids)
.setOwnerUid(ownerUid)
.setSignalStrength(signalStrength)
.setTransportInfo(transportInfo)
- .setSubscriptionIds(Set.of(TEST_SUBID1)).build();
+ .setSubscriptionIds(Set.of(TEST_SUBID1));
+ for (int cap : TEST_NETWORKS_EXTRA_ALLOWED_CAPS_ON_NON_CELL) {
+ restrictedNcBuilder.addCapability(cap);
+ }
+
+ if (isCell) {
+ restrictedNcBuilder.addTransportType(TRANSPORT_CELLULAR);
+ }
+ final NetworkCapabilities restrictedNc = restrictedNcBuilder.build();
+
final int creatorUid = isOwner ? ownerUid : INVALID_UID;
restrictedNc.restrictCapabilitiesForTestNetwork(creatorUid);
final NetworkCapabilities.Builder expectedNcBuilder = new NetworkCapabilities.Builder()
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
- // If the test network is restricted, then the network may declare any transport, and
- // appended with TRANSPORT_TEST.
- expectedNcBuilder.addTransportType(TRANSPORT_CELLULAR);
+
+ if (isCell) {
+ // If the test network is restricted, then the network may declare any transport, and
+ // appended with TRANSPORT_TEST.
+ expectedNcBuilder.addTransportType(TRANSPORT_CELLULAR);
+ } else {
+ // If the test network only has TRANSPORT_TEST, then it can keep the subscription IDs.
+ expectedNcBuilder.setSubscriptionIds(Set.of(TEST_SUBID1));
+ }
expectedNcBuilder.addTransportType(TRANSPORT_TEST);
+
// Only TEST_NETWORKS_ALLOWED_CAPABILITIES will be kept.
expectedNcBuilder.addCapability(NET_CAPABILITY_NOT_METERED);
expectedNcBuilder.removeCapability(NET_CAPABILITY_TRUSTED);
+ if (!isCell) {
+ for (int cap : TEST_NETWORKS_EXTRA_ALLOWED_CAPS_ON_NON_CELL) {
+ expectedNcBuilder.addCapability(cap);
+ }
+ }
+
expectedNcBuilder.setSignalStrength(signalStrength).setTransportInfo(transportInfo);
if (creatorUid == ownerUid) {
// Only retain the owner and administrator UIDs if they match the app registering the
diff --git a/tests/common/java/android/net/NetworkProviderTest.kt b/tests/common/java/android/net/NetworkProviderTest.kt
index c0e7f61..fcbb0dd 100644
--- a/tests/common/java/android/net/NetworkProviderTest.kt
+++ b/tests/common/java/android/net/NetworkProviderTest.kt
@@ -79,6 +79,7 @@
@After
fun tearDown() {
mHandlerThread.quitSafely()
+ mHandlerThread.join()
instrumentation.getUiAutomation().dropShellPermissionIdentity()
}
diff --git a/tests/common/java/android/net/netstats/NetworkTemplateTest.kt b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
index 99f1e0b..fd7bd74 100644
--- a/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
+++ b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
@@ -30,16 +30,17 @@
import android.net.NetworkTemplate.MATCH_WIFI
import android.net.NetworkTemplate.NETWORK_TYPE_ALL
import android.net.NetworkTemplate.OEM_MANAGED_ALL
+import android.os.Build
import android.telephony.TelephonyManager
import com.android.testutils.ConnectivityModuleTest
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.SC_V2
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
private const val TEST_IMSI1 = "imsi"
private const val TEST_WIFI_KEY1 = "wifiKey1"
@@ -95,6 +96,31 @@
NetworkTemplate.Builder(MATCH_CARRIER).build()
}
+ // Verify carrier and mobile template cannot contain one of subscriber Id is null.
+ assertFailsWith<IllegalArgumentException> {
+ NetworkTemplate.Builder(MATCH_CARRIER).setSubscriberIds(setOf(null)).build()
+ }
+ val firstSdk = Build.VERSION.DEVICE_INITIAL_SDK_INT
+ if (firstSdk > Build.VERSION_CODES.TIRAMISU) {
+ assertFailsWith<IllegalArgumentException> {
+ NetworkTemplate.Builder(MATCH_MOBILE).setSubscriberIds(setOf(null)).build()
+ }
+ } else {
+ NetworkTemplate.Builder(MATCH_MOBILE).setSubscriberIds(setOf(null)).build().let {
+ val expectedTemplate = NetworkTemplate(
+ MATCH_MOBILE,
+ arrayOfNulls<String>(1) /*subscriberIds*/,
+ emptyArray<String>() /*wifiNetworkKey*/,
+ METERED_ALL,
+ ROAMING_ALL,
+ DEFAULT_NETWORK_ALL,
+ NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL
+ )
+ assertEquals(expectedTemplate, it)
+ }
+ }
+
// Verify template which matches metered cellular networks,
// regardless of IMSI. See buildTemplateMobileWildcard.
NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build().let {
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
index 47ea53e..891c2dd 100644
--- a/tests/cts/hostside/Android.bp
+++ b/tests/cts/hostside/Android.bp
@@ -12,6 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+next_app_data = [ ":CtsHostsideNetworkTestsAppNext" ]
+
+// The above line is put in place to prevent any future automerger merge conflict between aosp,
+// downstream branches. The CtsHostsideNetworkTestsAppNext target will not exist in
+// some downstream branches, but it should exist in aosp and some downstream branches.
+
+
+
+
+
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
@@ -37,7 +47,9 @@
data: [
":CtsHostsideNetworkTestsApp",
":CtsHostsideNetworkTestsApp2",
- ":CtsHostsideNetworkTestsAppNext",
- ],
+ ":CtsHostsideNetworkCapTestsAppWithoutProperty",
+ ":CtsHostsideNetworkCapTestsAppWithProperty",
+ ":CtsHostsideNetworkCapTestsAppSdk33",
+ ] + next_app_data,
per_testcase_directory: true,
}
diff --git a/tests/cts/hostside/AndroidTest.xml b/tests/cts/hostside/AndroidTest.xml
index 7a73313..e83e36a 100644
--- a/tests/cts/hostside/AndroidTest.xml
+++ b/tests/cts/hostside/AndroidTest.xml
@@ -16,6 +16,7 @@
<configuration description="Config for CTS net host test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="networking" />
+ <option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
diff --git a/tests/cts/hostside/TEST_MAPPING b/tests/cts/hostside/TEST_MAPPING
index ab6de82..2cfd7af 100644
--- a/tests/cts/hostside/TEST_MAPPING
+++ b/tests/cts/hostside/TEST_MAPPING
@@ -8,6 +8,9 @@
},
{
"exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
}
]
}
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
index 449454e..fe522a0 100644
--- 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
@@ -32,6 +32,7 @@
import com.android.networkstack.apishim.VpnServiceBuilderShimImpl;
import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
import com.android.networkstack.apishim.common.VpnServiceBuilderShim;
+import com.android.testutils.PacketReflector;
import java.io.IOException;
import java.net.InetAddress;
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 124c2c3..0000000
--- 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/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
index a62ef8a..c28ee64 100755
--- 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
@@ -18,6 +18,8 @@
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
+import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
import static android.content.pm.PackageManager.FEATURE_WIFI;
import static android.net.ConnectivityManager.TYPE_VPN;
@@ -36,11 +38,18 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.cts.net.hostside.VpnTest.TestSocketKeepaliveCallback.CallbackType.ON_DATA_RECEIVED;
+import static com.android.cts.net.hostside.VpnTest.TestSocketKeepaliveCallback.CallbackType.ON_ERROR;
+import static com.android.cts.net.hostside.VpnTest.TestSocketKeepaliveCallback.CallbackType.ON_PAUSED;
+import static com.android.cts.net.hostside.VpnTest.TestSocketKeepaliveCallback.CallbackType.ON_RESUMED;
+import static com.android.cts.net.hostside.VpnTest.TestSocketKeepaliveCallback.CallbackType.ON_STARTED;
+import static com.android.cts.net.hostside.VpnTest.TestSocketKeepaliveCallback.CallbackType.ON_STOPPED;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
import static com.android.networkstack.apishim.ConstantsShim.RECEIVER_EXPORTED;
import static com.android.testutils.Cleanup.testAndCleanup;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
+import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS_INT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -63,6 +72,7 @@
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.IpSecManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
@@ -70,6 +80,7 @@
import android.net.NetworkRequest;
import android.net.Proxy;
import android.net.ProxyInfo;
+import android.net.SocketKeepalive;
import android.net.TestNetworkInterface;
import android.net.TestNetworkManager;
import android.net.TransportInfo;
@@ -78,6 +89,7 @@
import android.net.VpnService;
import android.net.VpnTransportInfo;
import android.net.cts.util.CtsNetUtils;
+import android.net.util.KeepaliveUtils;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Handler;
@@ -86,6 +98,7 @@
import android.os.Process;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
@@ -94,7 +107,6 @@
import android.system.Os;
import android.system.OsConstants;
import android.system.StructPollfd;
-import android.telephony.TelephonyManager;
import android.test.MoreAsserts;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -105,6 +117,8 @@
import com.android.compatibility.common.util.BlockingBroadcastReceiver;
import com.android.modules.utils.build.SdkLevel;
+import com.android.net.module.util.ArrayTrackRecord;
+import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.PacketBuilder;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -141,6 +155,7 @@
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
/**
@@ -190,6 +205,12 @@
public static int SOCKET_TIMEOUT_MS = 100;
public static String TEST_HOST = "connectivitycheck.gstatic.com";
+ private static final String AUTOMATIC_ON_OFF_KEEPALIVE_VERSION =
+ "automatic_on_off_keepalive_version";
+ // Enabled since version 1 means it's always enabled because the version is always above 1
+ private static final String AUTOMATIC_ON_OFF_KEEPALIVE_ENABLED = "1";
+ private static final long TEST_TCP_POLLING_TIMER_EXPIRED_PERIOD_MS = 60_000L;
+
private UiDevice mDevice;
private MyActivity mActivity;
private String mPackageName;
@@ -198,16 +219,18 @@
private RemoteSocketFactoryClient mRemoteSocketFactoryClient;
private CtsNetUtils mCtsNetUtils;
private PackageManager mPackageManager;
- private TelephonyManager mTelephonyManager;
-
+ private Context mTestContext;
+ private Context mTargetContext;
Network mNetwork;
- NetworkCallback mCallback;
final Object mLock = new Object();
final Object mLockShutdown = new Object();
private String mOldPrivateDnsMode;
private String mOldPrivateDnsSpecifier;
+ // The registered callbacks.
+ private List<NetworkCallback> mRegisteredCallbacks = new ArrayList<>();
+
@Rule
public final DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule();
@@ -228,37 +251,59 @@
@Before
public void setUp() throws Exception {
mNetwork = null;
- mCallback = null;
+ mTestContext = getInstrumentation().getContext();
+ mTargetContext = getInstrumentation().getTargetContext();
storePrivateDnsSetting();
-
mDevice = UiDevice.getInstance(getInstrumentation());
- mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
- MyActivity.class);
+ mActivity = launchActivity(mTargetContext.getPackageName(), MyActivity.class);
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();
- mCtsNetUtils = new CtsNetUtils(getInstrumentation().getContext());
- mPackageManager = getInstrumentation().getContext().getPackageManager();
- mTelephonyManager =
- getInstrumentation().getContext().getSystemService(TelephonyManager.class);
+ mCtsNetUtils = new CtsNetUtils(mTestContext);
+ mPackageManager = mTestContext.getPackageManager();
}
@After
public void tearDown() throws Exception {
restorePrivateDnsSetting();
mRemoteSocketFactoryClient.unbind();
- if (mCallback != null) {
- mCM.unregisterNetworkCallback(mCallback);
- }
mCtsNetUtils.tearDown();
Log.i(TAG, "Stopping VPN");
stopVpn();
+ unregisterRegisteredCallbacks();
mActivity.finish();
}
+ private void registerNetworkCallback(NetworkRequest request, NetworkCallback callback) {
+ mCM.registerNetworkCallback(request, callback);
+ mRegisteredCallbacks.add(callback);
+ }
+
+ private void registerDefaultNetworkCallback(NetworkCallback callback) {
+ mCM.registerDefaultNetworkCallback(callback);
+ mRegisteredCallbacks.add(callback);
+ }
+
+ private void registerSystemDefaultNetworkCallback(NetworkCallback callback, Handler h) {
+ mCM.registerSystemDefaultNetworkCallback(callback, h);
+ mRegisteredCallbacks.add(callback);
+ }
+
+ private void registerDefaultNetworkCallbackForUid(int uid, NetworkCallback callback,
+ Handler h) {
+ mCM.registerDefaultNetworkCallbackForUid(uid, callback, h);
+ mRegisteredCallbacks.add(callback);
+ }
+
+ private void unregisterRegisteredCallbacks() {
+ for (NetworkCallback callback: mRegisteredCallbacks) {
+ mCM.unregisterNetworkCallback(callback);
+ }
+ }
+
private void prepareVpn() throws Exception {
final int REQUEST_ID = 42;
@@ -374,7 +419,7 @@
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- mCallback = new NetworkCallback() {
+ final NetworkCallback callback = new NetworkCallback() {
public void onAvailable(Network network) {
synchronized (mLock) {
Log.i(TAG, "Got available callback for network=" + network);
@@ -383,7 +428,7 @@
}
}
};
- mCM.registerNetworkCallback(request, mCallback); // Unregistered in tearDown.
+ registerNetworkCallback(request, callback);
// Start the service and wait up for TIMEOUT_MS ms for the VPN to come up.
establishVpn(addresses, routes, excludedRoutes, allowedApplications, disallowedApplications,
@@ -408,7 +453,7 @@
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- mCallback = new NetworkCallback() {
+ final NetworkCallback callback = new NetworkCallback() {
public void onLost(Network network) {
synchronized (mLockShutdown) {
Log.i(TAG, "Got lost callback for network=" + network
@@ -419,7 +464,7 @@
}
}
};
- mCM.registerNetworkCallback(request, mCallback); // Unregistered in tearDown.
+ registerNetworkCallback(request, callback);
// 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
@@ -742,7 +787,7 @@
}
private ContentResolver getContentResolver() {
- return getInstrumentation().getContext().getContentResolver();
+ return mTestContext.getContentResolver();
}
private boolean isPrivateDnsInStrictMode() {
@@ -780,18 +825,14 @@
}
};
- mCM.registerNetworkCallback(request, callback);
+ 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);
- }
+ assertTrue("Private DNS hostname was not " + hostname + " after " + TIMEOUT_MS + "ms",
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
private void setAndVerifyPrivateDns(boolean strictMode) throws Exception {
- final ContentResolver cr = getInstrumentation().getContext().getContentResolver();
+ final ContentResolver cr = mTestContext.getContentResolver();
String privateDnsHostname;
if (strictMode) {
@@ -874,7 +915,7 @@
false /* isAlwaysMetered */);
// Acquire the NETWORK_SETTINGS permission for getting the underlying networks.
runWithShellPermissionIdentity(() -> {
- mCM.registerNetworkCallback(makeVpnNetworkRequest(), callback);
+ registerNetworkCallback(makeVpnNetworkRequest(), callback);
// Check that this VPN doesn't have any underlying networks.
expectUnderlyingNetworks(callback, new ArrayList<Network>());
@@ -907,8 +948,6 @@
} else {
mCtsNetUtils.ensureWifiDisconnected(null);
}
- }, () -> {
- mCM.unregisterNetworkCallback(callback);
});
}
@@ -929,7 +968,7 @@
}
final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(
- getInstrumentation().getTargetContext(), MyVpnService.ACTION_ESTABLISHED);
+ mTargetContext, MyVpnService.ACTION_ESTABLISHED);
receiver.register();
// Test the behaviour of a variety of types of network callbacks.
@@ -942,9 +981,9 @@
UserHandle.of(5 /* userId */).getUid(Process.FIRST_APPLICATION_UID);
final Handler h = new Handler(Looper.getMainLooper());
runWithShellPermissionIdentity(() -> {
- mCM.registerSystemDefaultNetworkCallback(systemDefaultCallback, h);
- mCM.registerDefaultNetworkCallbackForUid(otherUid, otherUidCallback, h);
- mCM.registerDefaultNetworkCallbackForUid(Process.myUid(), myUidCallback, h);
+ registerSystemDefaultNetworkCallback(systemDefaultCallback, h);
+ registerDefaultNetworkCallbackForUid(otherUid, otherUidCallback, h);
+ registerDefaultNetworkCallbackForUid(Process.myUid(), myUidCallback, h);
}, NETWORK_SETTINGS);
for (TestableNetworkCallback callback :
List.of(systemDefaultCallback, otherUidCallback, myUidCallback)) {
@@ -995,9 +1034,6 @@
// fail and could cause the default network to switch (e.g., from wifi to cellular).
systemDefaultCallback.assertNoCallback();
otherUidCallback.assertNoCallback();
- mCM.unregisterNetworkCallback(systemDefaultCallback);
- mCM.unregisterNetworkCallback(otherUidCallback);
- mCM.unregisterNetworkCallback(myUidCallback);
}
checkStrictModePrivateDns();
@@ -1026,6 +1062,183 @@
checkStrictModePrivateDns();
}
+ private int getSupportedKeepalives(NetworkCapabilities nc) throws Exception {
+ // Get number of supported concurrent keepalives for testing network.
+ final int[] keepalivesPerTransport = KeepaliveUtils.getSupportedKeepalives(
+ mTargetContext);
+ return KeepaliveUtils.getSupportedKeepalivesForNetworkCapabilities(
+ keepalivesPerTransport, nc);
+ }
+
+ // This class can't be private, otherwise the constants can't be static imported.
+ static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
+ // This must be larger than the alarm delay in AutomaticOnOffKeepaliveTracker.
+ private static final int KEEPALIVE_TIMEOUT_MS = 10_000;
+ public enum CallbackType {
+ ON_STARTED,
+ ON_RESUMED,
+ ON_STOPPED,
+ ON_PAUSED,
+ ON_ERROR,
+ ON_DATA_RECEIVED
+ }
+ private ArrayTrackRecord<CallbackType> mHistory = new ArrayTrackRecord<>();
+ private ArrayTrackRecord<CallbackType>.ReadHead mEvents = mHistory.newReadHead();
+
+ @Override
+ public void onStarted() {
+ mHistory.add(ON_STARTED);
+ }
+
+ @Override
+ public void onResumed() {
+ mHistory.add(ON_RESUMED);
+ }
+
+ @Override
+ public void onStopped() {
+ mHistory.add(ON_STOPPED);
+ }
+
+ @Override
+ public void onPaused() {
+ mHistory.add(ON_PAUSED);
+ }
+
+ @Override
+ public void onError(final int error) {
+ mHistory.add(ON_ERROR);
+ }
+
+ @Override
+ public void onDataReceived() {
+ mHistory.add(ON_DATA_RECEIVED);
+ }
+
+ public CallbackType poll() {
+ return mEvents.poll(KEEPALIVE_TIMEOUT_MS, it -> true);
+ }
+ }
+
+ private InetAddress getV4AddrByName(final String hostname) throws Exception {
+ final InetAddress[] allAddrs = InetAddress.getAllByName(hostname);
+ for (InetAddress addr : allAddrs) {
+ if (addr instanceof Inet4Address) return addr;
+ }
+ return null;
+ }
+
+ @Test
+ public void testAutomaticOnOffKeepaliveModeNoClose() throws Exception {
+ doTestAutomaticOnOffKeepaliveMode(false);
+ }
+
+ @Test
+ public void testAutomaticOnOffKeepaliveModeClose() throws Exception {
+ doTestAutomaticOnOffKeepaliveMode(true);
+ }
+
+ private void startKeepalive(SocketKeepalive kp, TestSocketKeepaliveCallback callback) {
+ runWithShellPermissionIdentity(() -> {
+ // Only SocketKeepalive.start() requires READ_DEVICE_CONFIG because feature is protected
+ // by a feature flag. But also verify ON_STARTED callback received here to ensure
+ // keepalive is indeed started because start() runs in the executor thread and shell
+ // permission may be dropped before reading DeviceConfig.
+ kp.start(10 /* intervalSec */, SocketKeepalive.FLAG_AUTOMATIC_ON_OFF, mNetwork);
+
+ // Verify callback status.
+ assertEquals(ON_STARTED, callback.poll());
+ }, READ_DEVICE_CONFIG);
+ }
+
+ private void doTestAutomaticOnOffKeepaliveMode(final boolean closeSocket) throws Exception {
+ assumeTrue(supportedHardware());
+
+ // Get default network first before starting VPN
+ final Network defaultNetwork = mCM.getActiveNetwork();
+ final TestableNetworkCallback cb = new TestableNetworkCallback();
+ registerDefaultNetworkCallback(cb);
+ cb.expect(CallbackEntry.AVAILABLE, defaultNetwork);
+ final NetworkCapabilities cap =
+ cb.expect(CallbackEntry.NETWORK_CAPS_UPDATED, defaultNetwork).getCaps();
+ final LinkProperties lp =
+ cb.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, defaultNetwork).getLp();
+ cb.expect(CallbackEntry.BLOCKED_STATUS, defaultNetwork);
+
+ // Setup VPN
+ final FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
+ final 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, "" /* disallowedApplications */, null /* proxyInfo */,
+ null /* underlyingNetworks */, false /* isAlwaysMetered */);
+ assertSocketClosed(fd, TEST_HOST);
+
+ // Decrease the TCP polling timer for testing.
+ runWithShellPermissionIdentity(() -> mCM.setTestLowTcpPollingTimerForKeepalive(
+ System.currentTimeMillis() + TEST_TCP_POLLING_TIMER_EXPIRED_PERIOD_MS),
+ NETWORK_SETTINGS);
+
+ // Setup keepalive
+ final int supported = getSupportedKeepalives(cap);
+ assumeTrue("Network " + defaultNetwork + " does not support keepalive", supported != 0);
+ final InetAddress srcAddr = CollectionUtils.findFirst(lp.getAddresses(),
+ it -> it instanceof Inet4Address);
+ assumeTrue("This test requires native IPv4", srcAddr != null);
+
+ final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
+
+ final String origMode = runWithShellPermissionIdentity(() -> {
+ final String mode = DeviceConfig.getProperty(
+ DeviceConfig.NAMESPACE_CONNECTIVITY, AUTOMATIC_ON_OFF_KEEPALIVE_VERSION);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CONNECTIVITY,
+ AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
+ AUTOMATIC_ON_OFF_KEEPALIVE_ENABLED, false /* makeDefault */);
+ return mode;
+ }, READ_DEVICE_CONFIG, WRITE_DEVICE_CONFIG);
+
+ final IpSecManager ipSec = mTargetContext.getSystemService(IpSecManager.class);
+ SocketKeepalive kp = null;
+ try (IpSecManager.UdpEncapsulationSocket nattSocket = ipSec.openUdpEncapsulationSocket()) {
+ final InetAddress dstAddr = getV4AddrByName(TEST_HOST);
+ assertNotNull(dstAddr);
+
+ // Start keepalive with dynamic keepalive mode enabled.
+ final Executor executor = mTargetContext.getMainExecutor();
+ kp = mCM.createSocketKeepalive(defaultNetwork, nattSocket,
+ srcAddr, dstAddr, executor, callback);
+ startKeepalive(kp, callback);
+
+ // There should be no open sockets on the VPN network, because any
+ // open sockets were closed when startVpn above was called. So the
+ // first TCP poll should trigger ON_PAUSED.
+ assertEquals(ON_PAUSED, callback.poll());
+
+ final Socket s = new Socket();
+ mNetwork.bindSocket(s);
+ s.connect(new InetSocketAddress(dstAddr, 80));
+ assertEquals(ON_RESUMED, callback.poll());
+
+ if (closeSocket) {
+ s.close();
+ assertEquals(ON_PAUSED, callback.poll());
+ }
+
+ kp.stop();
+ assertEquals(ON_STOPPED, callback.poll());
+ } finally {
+ if (kp != null) kp.stop();
+
+ runWithShellPermissionIdentity(() -> {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_CONNECTIVITY,
+ AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
+ origMode, false);
+ mCM.setTestLowTcpPollingTimerForKeepalive(0);
+ }, WRITE_DEVICE_CONFIG, NETWORK_SETTINGS);
+ }
+ }
+
@Test
public void testAppDisallowed() throws Exception {
assumeTrue(supportedHardware());
@@ -1061,6 +1274,31 @@
}
@Test
+ public void testSocketClosed() throws Exception {
+ assumeTrue(supportedHardware());
+
+ final FileDescriptor localFd = openSocketFd(TEST_HOST, 80, TIMEOUT_MS);
+ final List<FileDescriptor> remoteFds = new ArrayList<>();
+
+ for (int i = 0; i < 30; i++) {
+ remoteFds.add(openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS));
+ }
+
+ final 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 */);
+
+ // Socket owned by VPN uid is not closed
+ assertSocketStillOpen(localFd, TEST_HOST);
+
+ // Sockets not owned by VPN uid are closed
+ for (final FileDescriptor remoteFd: remoteFds) {
+ assertSocketClosed(remoteFd, TEST_HOST);
+ }
+ }
+
+ @Test
public void testExcludedRoutes() throws Exception {
assumeTrue(supportedHardware());
assumeTrue(SdkLevel.isAtLeastT());
@@ -1525,7 +1763,7 @@
private boolean received;
public ProxyChangeBroadcastReceiver() {
- super(getInstrumentation().getContext(), Proxy.PROXY_CHANGE_ACTION);
+ super(mTestContext, Proxy.PROXY_CHANGE_ACTION);
received = false;
}
@@ -1555,12 +1793,11 @@
"" /* allowedApps */, "com.android.providers.downloads", null /* proxyInfo */,
null /* underlyingNetworks */, false /* isAlwaysMetered */);
- final Context context = getInstrumentation().getContext();
- final DownloadManager dm = context.getSystemService(DownloadManager.class);
+ final DownloadManager dm = mTestContext.getSystemService(DownloadManager.class);
final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
try {
final int flags = SdkLevel.isAtLeastT() ? RECEIVER_EXPORTED : 0;
- context.registerReceiver(receiver,
+ mTestContext.registerReceiver(receiver,
new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), flags);
// Enqueue a request and check only one download.
@@ -1578,7 +1815,7 @@
assertEquals(1, dm.remove(id));
assertEquals(0, getTotalNumberDownloads(dm, new Query()));
} finally {
- context.unregisterReceiver(receiver);
+ mTestContext.unregisterReceiver(receiver);
}
}
@@ -1615,8 +1852,7 @@
// Create a TUN interface
final FileDescriptor tunFd = runWithShellPermissionIdentity(() -> {
- final TestNetworkManager tnm = getInstrumentation().getContext().getSystemService(
- TestNetworkManager.class);
+ final TestNetworkManager tnm = mTestContext.getSystemService(TestNetworkManager.class);
final TestNetworkInterface iface = tnm.createTunInterface(List.of(
TEST_IP4_DST_ADDR, TEST_IP6_DST_ADDR));
return iface.getFileDescriptor().getFileDescriptor();
@@ -1627,7 +1863,7 @@
testAndCleanup(() -> {
runWithShellPermissionIdentity(() -> {
- mCM.registerDefaultNetworkCallbackForUid(remoteUid, remoteUidCallback,
+ registerDefaultNetworkCallbackForUid(remoteUid, remoteUidCallback,
new Handler(Looper.getMainLooper()));
}, NETWORK_SETTINGS);
remoteUidCallback.expectAvailableCallbacksWithBlockedReasonNone(network);
@@ -1643,7 +1879,8 @@
// setRequireVpnForUids setup a lockdown rule asynchronously. So it needs to wait for
// BlockedStatusCallback to be fired before checking the blocking status of incoming
// packets.
- remoteUidCallback.expectBlockedStatusCallback(network, BLOCKED_REASON_LOCKDOWN_VPN);
+ remoteUidCallback.expect(BLOCKED_STATUS_INT, network,
+ cb -> cb.getReason() == BLOCKED_REASON_LOCKDOWN_VPN);
if (SdkLevel.isAtLeastT()) {
// On T and above, lockdown rule drop packets not coming from lo regardless of the
@@ -1662,8 +1899,6 @@
checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_BLOCK);
}, /* cleanup */ () -> {
- mCM.unregisterNetworkCallback(remoteUidCallback);
- }, /* cleanup */ () -> {
Os.close(tunFd);
}, /* cleanup */ () -> {
Os.close(remoteUdpFd);
@@ -1687,7 +1922,7 @@
final int myUid = Process.myUid();
testAndCleanup(() -> {
- mCM.registerDefaultNetworkCallback(defaultNetworkCallback);
+ registerDefaultNetworkCallback(defaultNetworkCallback);
defaultNetworkCallback.expectAvailableCallbacks(defaultNetwork);
final Range<Integer> myUidRange = new Range<>(myUid, myUid);
@@ -1719,8 +1954,6 @@
defaultNetworkCallback.eventuallyExpect(CallbackEntry.AVAILABLE,
NETWORK_CALLBACK_TIMEOUT_MS,
entry -> defaultNetwork.equals(entry.getNetwork()));
- }, /* cleanup */ () -> {
- mCM.unregisterNetworkCallback(defaultNetworkCallback);
});
}
@@ -1818,9 +2051,6 @@
super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */,
BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS);
}
- public void expectBlockedStatusCallback(Network network, int blockedStatus) {
- super.expectBlockedStatusCallback(blockedStatus, network, NETWORK_CALLBACK_TIMEOUT_MS);
- }
public void onBlockedStatusChanged(Network network, int blockedReasons) {
getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
}
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
index 2e79182..37dc7a0 100644
--- 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
@@ -99,7 +99,8 @@
}
case TYPE_COMPONENT_EXPEDITED_JOB: {
final int capabilities = activityManager.getUidProcessCapabilities(Process.myUid());
- if ((capabilities & ActivityManager.PROCESS_CAPABILITY_NETWORK) == 0) {
+ if ((capabilities
+ & ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) == 0) {
observer.onNetworkStateChecked(
INetworkStateObserver.RESULT_ERROR_UNEXPECTED_CAPABILITIES,
"Unexpected capabilities: " + capabilities);
diff --git a/tests/cts/hostside/networkslicingtestapp/Android.bp b/tests/cts/hostside/networkslicingtestapp/Android.bp
new file mode 100644
index 0000000..2aa3f69
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/Android.bp
@@ -0,0 +1,65 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_defaults {
+ name: "CtsHostsideNetworkCapTestsAppDefaults",
+ platform_apis: true,
+ static_libs: [
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "modules-utils-build",
+ "cts-net-utils",
+ ],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ ],
+}
+
+android_test_helper_app {
+ name: "CtsHostsideNetworkCapTestsAppWithoutProperty",
+ defaults: [
+ "cts_support_defaults",
+ "CtsHostsideNetworkCapTestsAppDefaults"
+ ],
+ manifest: "AndroidManifestWithoutProperty.xml",
+}
+
+android_test_helper_app {
+ name: "CtsHostsideNetworkCapTestsAppWithProperty",
+ defaults: [
+ "cts_support_defaults",
+ "CtsHostsideNetworkCapTestsAppDefaults"
+ ],
+ manifest: "AndroidManifestWithProperty.xml",
+}
+
+android_test_helper_app {
+ name: "CtsHostsideNetworkCapTestsAppSdk33",
+ defaults: [
+ "cts_support_defaults",
+ "CtsHostsideNetworkCapTestsAppDefaults"
+ ],
+ target_sdk_version: "33",
+ manifest: "AndroidManifestWithoutProperty.xml",
+}
diff --git a/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithProperty.xml b/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithProperty.xml
new file mode 100644
index 0000000..3ef0376
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithProperty.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.net.hostside.networkslicingtestapp">
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ <property android:name="android.net.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES"
+ android:resource="@xml/self_certified_network_capabilities_both" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.net.hostside.networkslicingtestapp"/>
+
+</manifest>
diff --git a/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithoutProperty.xml b/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithoutProperty.xml
new file mode 100644
index 0000000..fe66684
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithoutProperty.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.net.hostside.networkslicingtestapp">
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.net.hostside.networkslicingtestapp"/>
+
+</manifest>
diff --git a/tests/cts/hostside/networkslicingtestapp/res/xml/self_certified_network_capabilities_both.xml b/tests/cts/hostside/networkslicingtestapp/res/xml/self_certified_network_capabilities_both.xml
new file mode 100644
index 0000000..4066be2
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/res/xml/self_certified_network_capabilities_both.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+</network-capabilities-declaration>
diff --git a/tests/cts/hostside/networkslicingtestapp/src/com.android.cts.net.hostside.networkslicingtestapp/NetworkSelfDeclaredCapabilitiesTest.java b/tests/cts/hostside/networkslicingtestapp/src/com.android.cts.net.hostside.networkslicingtestapp/NetworkSelfDeclaredCapabilitiesTest.java
new file mode 100644
index 0000000..39792fc
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/src/com.android.cts.net.hostside.networkslicingtestapp/NetworkSelfDeclaredCapabilitiesTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 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.networkslicingtestapp;
+
+import static org.junit.Assert.assertThrows;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.Build;
+
+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.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class NetworkSelfDeclaredCapabilitiesTest {
+
+ @Rule
+ public final DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule();
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ public void requestNetwork_withoutRequestCapabilities() {
+ final ConnectivityManager cm =
+ (ConnectivityManager)
+ InstrumentationRegistry.getInstrumentation()
+ .getContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ final NetworkRequest request =
+ new NetworkRequest.Builder().build();
+ final ConnectivityManager.NetworkCallback callback =
+ new ConnectivityManager.NetworkCallback();
+ cm.requestNetwork(request, callback);
+ cm.unregisterNetworkCallback(callback);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ public void requestNetwork_withSelfDeclaredCapabilities() {
+ final ConnectivityManager cm =
+ (ConnectivityManager)
+ InstrumentationRegistry.getInstrumentation()
+ .getContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ final NetworkRequest request =
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .build();
+ final ConnectivityManager.NetworkCallback callback =
+ new ConnectivityManager.NetworkCallback();
+ cm.requestNetwork(request, callback);
+ cm.unregisterNetworkCallback(callback);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ public void requestNetwork_lackingRequiredSelfDeclaredCapabilities() {
+ final ConnectivityManager cm =
+ (ConnectivityManager)
+ InstrumentationRegistry.getInstrumentation()
+ .getContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ final NetworkRequest request =
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .build();
+ final ConnectivityManager.NetworkCallback callback =
+ new ConnectivityManager.NetworkCallback();
+ assertThrows(
+ SecurityException.class,
+ () -> cm.requestNetwork(request, callback));
+ }
+
+}
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java b/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
index d0567ae..2aa1032 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideNetworkTestCase.java
@@ -31,6 +31,7 @@
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.util.RunUtil;
import java.io.FileNotFoundException;
import java.util.Map;
@@ -120,7 +121,7 @@
i++;
Log.v(TAG, "Package " + packageName + " not uninstalled yet (" + result
+ "); sleeping 1s before polling again");
- Thread.sleep(1000);
+ RunUtil.getDefault().sleep(1000);
}
fail("Package '" + packageName + "' not uinstalled after " + max_tries + " seconds");
}
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index 7a613b3..21c78b7 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -20,6 +20,7 @@
import com.android.ddmlib.Log;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.util.RunUtil;
public class HostsideRestrictBackgroundNetworkTests extends HostsideNetworkTestCase {
@@ -359,7 +360,7 @@
}
Log.v(TAG, "whitelist check for uid " + uid + " doesn't match yet (expected "
+ expected + ", got " + actual + "); sleeping 1s before polling again");
- Thread.sleep(1000);
+ RunUtil.getDefault().sleep(1000);
}
fail("whitelist check for uid " + uid + " failed: expected "
+ expected + ", got " + actual);
@@ -384,7 +385,7 @@
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);
+ RunUtil.getDefault().sleep(1000);
}
fail("Command '" + command + "' did not return '" + expectedResult + "' after " + maxTries
+ " attempts");
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideSelfDeclaredNetworkCapabilitiesCheckTest.java b/tests/cts/hostside/src/com/android/cts/net/HostsideSelfDeclaredNetworkCapabilitiesCheckTest.java
new file mode 100644
index 0000000..4c2985d
--- /dev/null
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideSelfDeclaredNetworkCapabilitiesCheckTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 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 HostsideSelfDeclaredNetworkCapabilitiesCheckTest extends HostsideNetworkTestCase {
+
+ private static final String TEST_WITH_PROPERTY_IN_CURRENT_SDK_APK =
+ "CtsHostsideNetworkCapTestsAppWithProperty.apk";
+ private static final String TEST_WITHOUT_PROPERTY_IN_CURRENT_SDK_APK =
+ "CtsHostsideNetworkCapTestsAppWithoutProperty.apk";
+ private static final String TEST_IN_SDK_33_APK =
+ "CtsHostsideNetworkCapTestsAppSdk33.apk";
+ private static final String TEST_APP_PKG =
+ "com.android.cts.net.hostside.networkslicingtestapp";
+ private static final String TEST_CLASS_NAME = ".NetworkSelfDeclaredCapabilitiesTest";
+ private static final String WITH_SELF_DECLARED_CAPABILITIES_METHOD =
+ "requestNetwork_withSelfDeclaredCapabilities";
+ private static final String LACKING_SELF_DECLARED_CAPABILITIES_METHOD =
+ "requestNetwork_lackingRequiredSelfDeclaredCapabilities";
+ private static final String WITHOUT_REQUEST_CAPABILITIES_METHOD =
+ "requestNetwork_withoutRequestCapabilities";
+
+
+ public void testRequestNetworkInCurrentSdkWithProperty() throws Exception {
+ uninstallPackage(TEST_APP_PKG, false);
+ installPackage(TEST_WITH_PROPERTY_IN_CURRENT_SDK_APK);
+ // If the self-declared capabilities are defined,
+ // the ConnectivityManager.requestNetwork() call should always pass.
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITH_SELF_DECLARED_CAPABILITIES_METHOD);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITHOUT_REQUEST_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+ }
+
+ public void testRequestNetworkInCurrentSdkWithoutProperty() throws Exception {
+ uninstallPackage(TEST_APP_PKG, false);
+ installPackage(TEST_WITHOUT_PROPERTY_IN_CURRENT_SDK_APK);
+ // If the self-declared capabilities are not defined,
+ // the ConnectivityManager.requestNetwork() call will fail if the properly is not declared.
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ LACKING_SELF_DECLARED_CAPABILITIES_METHOD);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITHOUT_REQUEST_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+ }
+
+ public void testRequestNetworkInSdk33() throws Exception {
+ uninstallPackage(TEST_APP_PKG, false);
+ installPackage(TEST_IN_SDK_33_APK);
+ // In Sdk33, the ConnectivityManager.requestNetwork() call should always pass.
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITH_SELF_DECLARED_CAPABILITIES_METHOD);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITHOUT_REQUEST_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+ }
+
+ public void testReinstallPackageWillUpdateProperty() throws Exception {
+ uninstallPackage(TEST_APP_PKG, false);
+ installPackage(TEST_WITHOUT_PROPERTY_IN_CURRENT_SDK_APK);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ LACKING_SELF_DECLARED_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+
+
+ // Updates package.
+ installPackage(TEST_WITH_PROPERTY_IN_CURRENT_SDK_APK);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITH_SELF_DECLARED_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+
+ }
+}
+
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
index 10a2821..3ca4775 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
@@ -16,6 +16,8 @@
package com.android.cts.net;
+import android.platform.test.annotations.RequiresDevice;
+
public class HostsideVpnTests extends HostsideNetworkTestCase {
@Override
@@ -49,6 +51,10 @@
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testAppDisallowed");
}
+ public void testSocketClosed() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testSocketClosed");
+ }
+
public void testGetConnectionOwnerUidSecurity() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testGetConnectionOwnerUidSecurity");
}
@@ -89,6 +95,18 @@
TEST_PKG, TEST_PKG + ".VpnTest", "testAlwaysMeteredVpnWithNullUnderlyingNetwork");
}
+ @RequiresDevice // Keepalive is not supported on virtual hardware
+ public void testAutomaticOnOffKeepaliveModeClose() throws Exception {
+ runDeviceTests(
+ TEST_PKG, TEST_PKG + ".VpnTest", "testAutomaticOnOffKeepaliveModeClose");
+ }
+
+ @RequiresDevice // Keepalive is not supported on virtual hardware
+ public void testAutomaticOnOffKeepaliveModeNoClose() throws Exception {
+ runDeviceTests(
+ TEST_PKG, TEST_PKG + ".VpnTest", "testAutomaticOnOffKeepaliveModeNoClose");
+ }
+
public void testAlwaysMeteredVpnWithNonNullUnderlyingNetwork() throws Exception {
runDeviceTests(
TEST_PKG,
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index 23cb15c..f9fe5b0 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -114,34 +114,39 @@
],
}
-android_test {
- name: "CtsNetTestCasesMaxTargetSdk31", // Must match CtsNetTestCasesMaxTargetSdk31 annotation.
+java_defaults {
+ name: "CtsNetTestCasesMaxTargetSdkDefaults",
defaults: [
"CtsNetTestCasesDefaults",
"CtsNetTestCasesApiStableDefaults",
],
- target_sdk_version: "31",
- package_name: "android.net.cts.maxtargetsdk31", // CTS package names must be unique.
- instrumentation_target_package: "android.net.cts.maxtargetsdk31",
test_suites: [
"cts",
"general-tests",
- "mts-networking",
+ "mts-tethering",
],
}
android_test {
+ name: "CtsNetTestCasesMaxTargetSdk33", // Must match CtsNetTestCasesMaxTargetSdk33 annotation.
+ defaults: ["CtsNetTestCasesMaxTargetSdkDefaults"],
+ target_sdk_version: "33",
+ package_name: "android.net.cts.maxtargetsdk33",
+ instrumentation_target_package: "android.net.cts.maxtargetsdk33",
+}
+
+android_test {
+ name: "CtsNetTestCasesMaxTargetSdk31", // Must match CtsNetTestCasesMaxTargetSdk31 annotation.
+ defaults: ["CtsNetTestCasesMaxTargetSdkDefaults"],
+ target_sdk_version: "31",
+ package_name: "android.net.cts.maxtargetsdk31", // CTS package names must be unique.
+ instrumentation_target_package: "android.net.cts.maxtargetsdk31",
+}
+
+android_test {
name: "CtsNetTestCasesMaxTargetSdk30", // Must match CtsNetTestCasesMaxTargetSdk30 annotation.
- defaults: [
- "CtsNetTestCasesDefaults",
- "CtsNetTestCasesApiStableDefaults",
- ],
+ defaults: ["CtsNetTestCasesMaxTargetSdkDefaults"],
target_sdk_version: "30",
package_name: "android.net.cts.maxtargetsdk30", // CTS package names must be unique.
instrumentation_target_package: "android.net.cts.maxtargetsdk30",
- test_suites: [
- "cts",
- "general-tests",
- "mts-networking",
- ],
}
diff --git a/tests/cts/net/AndroidManifest.xml b/tests/cts/net/AndroidManifest.xml
index 25490da..999614c 100644
--- a/tests/cts/net/AndroidManifest.xml
+++ b/tests/cts/net/AndroidManifest.xml
@@ -54,8 +54,6 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.net.cts"
android:label="CTS tests of android.net">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/tests/cts/net/api23Test/AndroidManifest.xml b/tests/cts/net/api23Test/AndroidManifest.xml
index 69ee0dd..44c63f6 100644
--- a/tests/cts/net/api23Test/AndroidManifest.xml
+++ b/tests/cts/net/api23Test/AndroidManifest.xml
@@ -39,7 +39,5 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.net.cts.api23test"
android:label="CTS tests of android.net">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener"/>
</instrumentation>
</manifest>
diff --git a/tests/cts/net/native/dns/Android.bp b/tests/cts/net/native/dns/Android.bp
index 434e529..49b9337 100644
--- a/tests/cts/net/native/dns/Android.bp
+++ b/tests/cts/net/native/dns/Android.bp
@@ -24,6 +24,10 @@
"liblog",
"libutils",
],
+ static_libs: [
+ "libbase",
+ "libnetdutils",
+ ],
// To be compatible with Q devices, the min_sdk_version must be 29.
min_sdk_version: "29",
}
diff --git a/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp b/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp
index e501475..68bd227 100644
--- a/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp
+++ b/tests/cts/net/native/dns/NativeDnsAsyncTest.cpp
@@ -28,6 +28,7 @@
#include <android/multinetwork.h>
#include <gtest/gtest.h>
+#include <netdutils/NetNativeTestBase.h>
namespace {
constexpr int MAXPACKET = 8 * 1024;
@@ -101,7 +102,9 @@
} // namespace
-TEST (NativeDnsAsyncTest, Async_Query) {
+class NativeDnsAsyncTest : public NetNativeTestBase {};
+
+TEST_F(NativeDnsAsyncTest, Async_Query) {
// V4
int fd1 = android_res_nquery(
NETWORK_UNSPECIFIED, "www.google.com", ns_c_in, ns_t_a, 0);
@@ -123,7 +126,7 @@
expectAnswersValid(fd1, AF_INET6, ns_r_noerror);
}
-TEST (NativeDnsAsyncTest, Async_Send) {
+TEST_F(NativeDnsAsyncTest, Async_Send) {
// V4
uint8_t buf1[MAXPACKET] = {};
int len1 = res_mkquery(ns_o_query, "www.googleapis.com",
@@ -162,7 +165,7 @@
expectAnswersValid(fd1, AF_INET6, ns_r_noerror);
}
-TEST (NativeDnsAsyncTest, Async_NXDOMAIN) {
+TEST_F(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));
@@ -191,7 +194,7 @@
expectAnswersValid(fd1, AF_INET6, ns_r_nxdomain);
}
-TEST (NativeDnsAsyncTest, Async_Cancel) {
+TEST_F(NativeDnsAsyncTest, Async_Cancel) {
int fd = android_res_nquery(
NETWORK_UNSPECIFIED, "www.google.com", ns_c_in, ns_t_a, 0);
errno = 0;
@@ -202,7 +205,7 @@
// otherwise it will hit fdsan double-close fd.
}
-TEST (NativeDnsAsyncTest, Async_Query_MALFORMED) {
+TEST_F(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(
@@ -221,7 +224,7 @@
EXPECT_EQ(-EMSGSIZE, fd);
}
-TEST (NativeDnsAsyncTest, Async_Send_MALFORMED) {
+TEST_F(NativeDnsAsyncTest, Async_Send_MALFORMED) {
uint8_t buf[10] = {};
// empty BLOB
int fd = android_res_nsend(NETWORK_UNSPECIFIED, buf, 10, 0);
diff --git a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
index 7c24c95..dc22369 100644
--- a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
+++ b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
@@ -37,8 +37,6 @@
import android.net.cts.NetworkValidationTestUtil.setHttpsUrlDeviceConfig
import android.net.cts.NetworkValidationTestUtil.setUrlExpirationDeviceConfig
import android.net.cts.util.CtsNetUtils
-import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL
-import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL
import android.platform.test.annotations.AppModeFull
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY
@@ -47,28 +45,30 @@
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.runner.AndroidJUnit4
import com.android.modules.utils.build.SdkLevel.isAtLeastR
+import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL
+import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL
import com.android.testutils.DeviceConfigRule
-import com.android.testutils.RecorderCallback
+import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
import com.android.testutils.TestHttpServer
import com.android.testutils.TestHttpServer.Request
import com.android.testutils.TestableNetworkCallback
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.Assume.assumeFalse
-import org.junit.Before
-import org.junit.BeforeClass
-import org.junit.Rule
-import org.junit.runner.RunWith
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
+import junit.framework.AssertionFailedError
import kotlin.test.Test
import kotlin.test.assertNotEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
+import org.junit.After
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.BeforeClass
+import org.junit.Rule
+import org.junit.runner.RunWith
private const val TEST_HTTPS_URL_PATH = "/https_path"
private const val TEST_HTTP_URL_PATH = "/http_path"
@@ -151,8 +151,8 @@
.build()
val cellCb = TestableNetworkCallback(timeoutMs = TEST_TIMEOUT_MS)
cm.registerNetworkCallback(cellReq, cellCb)
- val cb = cellCb.eventuallyExpectOrNull<RecorderCallback.CallbackEntry.CapabilitiesChanged> {
- it.network == cellNetwork && it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
+ val cb = cellCb.poll { it.network == cellNetwork &&
+ it is CapabilitiesChanged && it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
}
assertNotNull(cb, "Mobile network $cellNetwork has no access to the internet. " +
"Check the mobile data connection.")
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index d4b23a3..9d234d3 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -1140,11 +1140,8 @@
.setPackage(mContext.getPackageName());
// While ConnectivityService would put extra info such as network or request id before
// broadcasting the inner intent. The MUTABLE flag needs to be added accordingly.
- // TODO: replace with PendingIntent.FLAG_MUTABLE when this code compiles against S+ or
- // shims.
- final int pendingIntentFlagMutable = 1 << 25;
final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0 /*requestCode*/,
- intent, PendingIntent.FLAG_CANCEL_CURRENT | pendingIntentFlagMutable);
+ intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
// We will register for a WIFI network being available or lost.
mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent);
@@ -1184,15 +1181,13 @@
// Avoid receiving broadcasts from other runs by appending a timestamp
final String broadcastAction = NETWORK_CALLBACK_ACTION + System.currentTimeMillis();
try {
- // TODO: replace with PendingIntent.FLAG_MUTABLE when this code compiles against S+
// Intent is mutable to receive EXTRA_NETWORK_REQUEST from ConnectivityService
- final int pendingIntentFlagMutable = 1 << 25;
final String extraBoolKey = "extra_bool";
firstIntent = PendingIntent.getBroadcast(mContext,
0 /* requestCode */,
new Intent(broadcastAction).putExtra(extraBoolKey, false)
.setPackage(mContext.getPackageName()),
- PendingIntent.FLAG_UPDATE_CURRENT | pendingIntentFlagMutable);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
if (useListen) {
mCm.registerNetworkCallback(firstRequest, firstIntent);
@@ -1206,7 +1201,7 @@
0 /* requestCode */,
new Intent(broadcastAction).putExtra(extraBoolKey, true)
.setPackage(mContext.getPackageName()),
- PendingIntent.FLAG_UPDATE_CURRENT | pendingIntentFlagMutable);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
// Because secondIntent.intentFilterEquals the first, the request should be replaced
if (useListen) {
@@ -2181,15 +2176,12 @@
c -> c instanceof CallbackEntry.Available);
}
- private void waitForAvailable(
+ private void waitForTransport(
@NonNull final TestableNetworkCallback cb, final int expectedTransport) {
- cb.eventuallyExpect(
- CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
- entry -> {
- final NetworkCapabilities nc = mCm.getNetworkCapabilities(entry.getNetwork());
- return nc.hasTransport(expectedTransport);
- }
- );
+ cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
+ NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> ((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+ .hasTransport(expectedTransport));
}
private void waitForAvailable(
@@ -2390,9 +2382,10 @@
}
public void eventuallyExpectBlockedStatusCallback(Network network, int blockedStatus) {
super.eventuallyExpect(CallbackEntry.BLOCKED_STATUS_INT, NETWORK_CALLBACK_TIMEOUT_MS,
- (it) -> it.getNetwork().equals(network) && it.getBlocked() == blockedStatus);
+ (it) -> it.getNetwork().equals(network) && it.getReason() == blockedStatus);
}
public void onBlockedStatusChanged(Network network, int blockedReasons) {
+ Log.v(TAG, "onBlockedStatusChanged " + network + " " + blockedReasons);
getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
}
private void assertNoBlockedStatusCallback() {
@@ -2413,7 +2406,12 @@
}
}
- private void doTestBlockedStatusCallback() throws Exception {
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
+ @Test
+ public void testBlockedStatusCallback() throws Exception {
+ // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
+ // shims, and @IgnoreUpTo does not check that.
+ assumeTrue(TestUtils.shouldTestSApis());
// The test will need a stable active network that is persistent during the test.
// Try to connect to a wifi network and wait for it becomes the default network before
// starting the test to prevent from sudden active network change caused by previous
@@ -2431,35 +2429,40 @@
final Handler handler = new Handler(Looper.getMainLooper());
registerDefaultNetworkCallback(myUidCallback, handler);
- registerDefaultNetworkCallbackForUid(otherUid, otherUidCallback, handler);
+ runWithShellPermissionIdentity(() -> registerDefaultNetworkCallbackForUid(
+ otherUid, otherUidCallback, handler), NETWORK_SETTINGS);
- final Network defaultNetwork = mCm.getActiveNetwork();
+ final Network defaultNetwork = myUidCallback.expect(CallbackEntry.AVAILABLE).getNetwork();
final List<DetailedBlockedStatusCallback> allCallbacks =
List.of(myUidCallback, otherUidCallback);
for (DetailedBlockedStatusCallback callback : allCallbacks) {
- callback.expectAvailableCallbacksWithBlockedReasonNone(defaultNetwork);
+ callback.eventuallyExpectBlockedStatusCallback(defaultNetwork, BLOCKED_REASON_NONE);
}
final Range<Integer> myUidRange = new Range<>(myUid, myUid);
final Range<Integer> otherUidRange = new Range<>(otherUid, otherUid);
- setRequireVpnForUids(true, List.of(myUidRange));
+ runWithShellPermissionIdentity(() -> setRequireVpnForUids(
+ true, List.of(myUidRange)), NETWORK_SETTINGS);
myUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork,
BLOCKED_REASON_LOCKDOWN_VPN);
otherUidCallback.assertNoBlockedStatusCallback();
- setRequireVpnForUids(true, List.of(myUidRange, otherUidRange));
+ runWithShellPermissionIdentity(() -> setRequireVpnForUids(
+ true, List.of(myUidRange, otherUidRange)), NETWORK_SETTINGS);
myUidCallback.assertNoBlockedStatusCallback();
otherUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork,
BLOCKED_REASON_LOCKDOWN_VPN);
// setRequireVpnForUids does no deduplication or refcounting. Removing myUidRange does not
// unblock myUid because it was added to the blocked ranges twice.
- setRequireVpnForUids(false, List.of(myUidRange));
+ runWithShellPermissionIdentity(() ->
+ setRequireVpnForUids(false, List.of(myUidRange)), NETWORK_SETTINGS);
myUidCallback.assertNoBlockedStatusCallback();
otherUidCallback.assertNoBlockedStatusCallback();
- setRequireVpnForUids(false, List.of(myUidRange, otherUidRange));
+ runWithShellPermissionIdentity(() -> setRequireVpnForUids(
+ false, List.of(myUidRange, otherUidRange)), NETWORK_SETTINGS);
myUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork, BLOCKED_REASON_NONE);
otherUidCallback.eventuallyExpectBlockedStatusCallback(defaultNetwork, BLOCKED_REASON_NONE);
@@ -2468,14 +2471,6 @@
}
@Test
- public void testBlockedStatusCallback() {
- // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
- // shims, and @IgnoreUpTo does not check that.
- assumeTrue(TestUtils.shouldTestSApis());
- runWithShellPermissionIdentity(() -> doTestBlockedStatusCallback(), NETWORK_SETTINGS);
- }
-
- @Test
public void testSetVpnDefaultForUids() {
assumeTrue(TestUtils.shouldTestUApis());
final String session = UUID.randomUUID().toString();
@@ -2558,15 +2553,14 @@
try {
tetherEventCallback.assumeWifiTetheringSupported(mContext);
- final TestableNetworkCallback wifiCb = new TestableNetworkCallback();
- mCtsNetUtils.ensureWifiConnected();
- registerCallbackAndWaitForAvailable(makeWifiNetworkRequest(), wifiCb);
+ tetherUtils.startWifiTethering(tetherEventCallback);
// Update setting to verify the behavior.
setAirplaneMode(true);
- // Verify wifi lost to make sure airplane mode takes effect. This could
+ // Verify softap lost to make sure airplane mode takes effect. This could
// prevent the race condition between airplane mode enabled and the followed
// up wifi tethering enabled.
- waitForLost(wifiCb);
+ tetherEventCallback.expectNoTetheringActive();
+
// start wifi tethering
tetherUtils.startWifiTethering(tetherEventCallback);
@@ -2675,7 +2669,8 @@
// Validate that an unmetered network is used over other networks.
waitForAvailable(defaultCallback, wifiNetwork);
- waitForAvailable(systemDefaultCallback, wifiNetwork);
+ systemDefaultCallback.eventuallyExpect(CallbackEntry.AVAILABLE,
+ NETWORK_CALLBACK_TIMEOUT_MS, cb -> wifiNetwork.equals(cb.getNetwork()));
// Validate that when setting unmetered to metered, unmetered is lost and replaced by
// the network with the TEST transport. Also wait for validation here, in case there
@@ -2687,11 +2682,14 @@
// callbacks may be received. Eventually, metered Wi-Fi should be the final available
// callback in any case therefore confirm its receipt before continuing to assure the
// system is in the expected state.
- waitForAvailable(systemDefaultCallback, TRANSPORT_WIFI);
+ waitForTransport(systemDefaultCallback, TRANSPORT_WIFI);
}, /* cleanup */ () -> {
- // Validate that removing the test network will fallback to the default network.
+ // Validate that removing the test network will fallback to the default network.
runWithShellPermissionIdentity(tnt::teardown);
- defaultCallback.expect(CallbackEntry.LOST, tnt, NETWORK_CALLBACK_TIMEOUT_MS);
+ // The other callbacks (LP or NC changes) would receive before LOST callback. Use
+ // eventuallyExpect to check callback for avoiding test flake.
+ defaultCallback.eventuallyExpect(CallbackEntry.LOST, NETWORK_CALLBACK_TIMEOUT_MS,
+ lost -> tnt.getNetwork().equals(lost.getNetwork()));
waitForAvailable(defaultCallback);
}, /* cleanup */ () -> {
setWifiMeteredStatusAndWait(ssid, oldMeteredValue, false /* waitForValidation */);
@@ -2711,6 +2709,7 @@
// Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
// shims, and @IgnoreUpTo does not check that.
assumeTrue(TestUtils.shouldTestSApis());
+ assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
final TestNetworkTracker tnt = callWithShellPermissionIdentity(
() -> initTestNetwork(mContext, TEST_LINKADDR, NETWORK_CALLBACK_TIMEOUT_MS));
@@ -2724,7 +2723,8 @@
OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY);
registerTestOemNetworkPreferenceCallbacks(defaultCallback, systemDefaultCallback);
waitForAvailable(defaultCallback, tnt.getNetwork());
- waitForAvailable(systemDefaultCallback, wifiNetwork);
+ systemDefaultCallback.eventuallyExpect(CallbackEntry.AVAILABLE,
+ NETWORK_CALLBACK_TIMEOUT_MS, cb -> wifiNetwork.equals(cb.getNetwork()));
}, /* cleanup */ () -> {
runWithShellPermissionIdentity(tnt::teardown);
defaultCallback.expect(CallbackEntry.LOST, tnt, NETWORK_CALLBACK_TIMEOUT_MS);
@@ -3377,7 +3377,7 @@
}
private void checkFirewallBlocking(final DatagramSocket srcSock, final DatagramSocket dstSock,
- final boolean expectBlock) throws Exception {
+ final boolean expectBlock, final int chain) throws Exception {
final Random random = new Random();
final byte[] sendData = new byte[100];
random.nextBytes(sendData);
@@ -3390,19 +3390,28 @@
if (expectBlock) {
return;
}
- fail("Expect not to be blocked by firewall but sending packet was blocked");
- }
-
- if (expectBlock) {
- fail("Expect to be blocked by firewall but sending packet was not blocked");
+ fail("Expect not to be blocked by firewall but sending packet was blocked:"
+ + " chain=" + chain
+ + " chainEnabled=" + mCm.getFirewallChainEnabled(chain)
+ + " uidFirewallRule=" + mCm.getUidFirewallRule(chain, Process.myUid()));
}
dstSock.receive(pkt);
assertArrayEquals(sendData, pkt.getData());
+
+ if (expectBlock) {
+ fail("Expect to be blocked by firewall but sending packet was not blocked:"
+ + " chain=" + chain
+ + " chainEnabled=" + mCm.getFirewallChainEnabled(chain)
+ + " uidFirewallRule=" + mCm.getUidFirewallRule(chain, Process.myUid()));
+ }
}
private static final boolean EXPECT_PASS = false;
private static final boolean EXPECT_BLOCK = true;
+
+ // ALLOWLIST means the firewall denies all by default, uids must be explicitly allowed
+ // DENYLIST means the firewall allows all by default, uids must be explicitly denyed
private static final boolean ALLOWLIST = true;
private static final boolean DENYLIST = false;
@@ -3414,34 +3423,40 @@
runWithShellPermissionIdentity(() -> {
// Firewall chain status will be restored after the test.
final boolean wasChainEnabled = mCm.getFirewallChainEnabled(chain);
+ final int previousUidFirewallRule = mCm.getUidFirewallRule(chain, myUid);
final DatagramSocket srcSock = new DatagramSocket();
final DatagramSocket dstSock = new DatagramSocket();
testAndCleanup(() -> {
if (wasChainEnabled) {
mCm.setFirewallChainEnabled(chain, false /* enable */);
}
+ if (previousUidFirewallRule == ruleToAddMatch) {
+ mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
+ }
dstSock.setSoTimeout(SOCKET_TIMEOUT_MS);
// Chain disabled, UID not on chain.
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS, chain);
// Chain enabled, UID not on chain.
mCm.setFirewallChainEnabled(chain, true /* enable */);
assertTrue(mCm.getFirewallChainEnabled(chain));
- checkFirewallBlocking(srcSock, dstSock, isAllowList ? EXPECT_BLOCK : EXPECT_PASS);
+ checkFirewallBlocking(
+ srcSock, dstSock, isAllowList ? EXPECT_BLOCK : EXPECT_PASS, chain);
// Chain enabled, UID on chain.
mCm.setUidFirewallRule(chain, myUid, ruleToAddMatch);
- checkFirewallBlocking(srcSock, dstSock, isAllowList ? EXPECT_PASS : EXPECT_BLOCK);
+ checkFirewallBlocking(
+ srcSock, dstSock, isAllowList ? EXPECT_PASS : EXPECT_BLOCK, chain);
// Chain disabled, UID on chain.
mCm.setFirewallChainEnabled(chain, false /* enable */);
assertFalse(mCm.getFirewallChainEnabled(chain));
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS, chain);
// Chain disabled, UID not on chain.
mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS, chain);
}, /* cleanup */ () -> {
srcSock.close();
dstSock.close();
@@ -3449,8 +3464,9 @@
// Restore the global chain status
mCm.setFirewallChainEnabled(chain, wasChainEnabled);
}, /* cleanup */ () -> {
+ // Restore the uid firewall rule status
try {
- mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
+ mCm.setUidFirewallRule(chain, myUid, previousUidFirewallRule);
} catch (IllegalStateException ignored) {
// Removing match causes an exception when the rule entry for the uid does
// not exist. But this is fine and can be ignored.
@@ -3461,17 +3477,49 @@
@Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest
@AppModeFull(reason = "Socket cannot bind in instant app mode")
- public void testFirewallBlocking() {
- // ALLOWLIST means the firewall denies all by default, uids must be explicitly allowed
+ public void testFirewallBlockingDozable() {
doTestFirewallBlocking(FIREWALL_CHAIN_DOZABLE, ALLOWLIST);
- doTestFirewallBlocking(FIREWALL_CHAIN_POWERSAVE, ALLOWLIST);
- doTestFirewallBlocking(FIREWALL_CHAIN_RESTRICTED, ALLOWLIST);
- doTestFirewallBlocking(FIREWALL_CHAIN_LOW_POWER_STANDBY, ALLOWLIST);
+ }
- // DENYLIST means the firewall allows all by default, uids must be explicitly denyed
+ @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void testFirewallBlockingPowersave() {
+ doTestFirewallBlocking(FIREWALL_CHAIN_POWERSAVE, ALLOWLIST);
+ }
+
+ @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void testFirewallBlockingRestricted() {
+ doTestFirewallBlocking(FIREWALL_CHAIN_RESTRICTED, ALLOWLIST);
+ }
+
+ @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void testFirewallBlockingLowPowerStandby() {
+ doTestFirewallBlocking(FIREWALL_CHAIN_LOW_POWER_STANDBY, ALLOWLIST);
+ }
+
+ @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void testFirewallBlockingStandby() {
doTestFirewallBlocking(FIREWALL_CHAIN_STANDBY, DENYLIST);
+ }
+
+ @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void testFirewallBlockingOemDeny1() {
doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_1, DENYLIST);
+ }
+
+ @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void testFirewallBlockingOemDeny2() {
doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_2, DENYLIST);
+ }
+
+ @Test @IgnoreUpTo(SC_V2) @ConnectivityModuleTest
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void testFirewallBlockingOemDeny3() {
doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_3, DENYLIST);
}
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index 2a1e7e7..732a42b 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -652,10 +652,9 @@
val listener = EthernetStateListener()
addInterfaceStateListener(listener)
- // TODO(b/236895792): THIS IS A BUG! Existing server mode interfaces are not reported when
- // an InterfaceStateListener is registered.
// Note: using eventuallyExpect as there may be other interfaces present.
- // listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_SERVER)
+ listener.eventuallyExpect(InterfaceStateChanged(iface.name,
+ STATE_LINK_UP, ROLE_SERVER, /* IpConfiguration */ null))
releaseTetheredInterface()
listener.eventuallyExpect(iface, STATE_LINK_UP, ROLE_CLIENT)
diff --git a/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java b/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java
index ac50740..805dd65 100644
--- a/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java
+++ b/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java
@@ -60,7 +60,11 @@
import com.android.internal.util.HexDump;
import com.android.networkstack.apishim.ConstantsShim;
+import com.android.networkstack.apishim.Ikev2VpnProfileBuilderShimImpl;
+import com.android.networkstack.apishim.Ikev2VpnProfileShimImpl;
import com.android.networkstack.apishim.VpnManagerShimImpl;
+import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim;
+import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
import com.android.networkstack.apishim.common.VpnManagerShim;
import com.android.networkstack.apishim.common.VpnProfileStateShim;
import com.android.testutils.DevSdkIgnoreRule;
@@ -223,17 +227,28 @@
}
private Ikev2VpnProfile buildIkev2VpnProfileCommon(
- @NonNull Ikev2VpnProfile.Builder builder, boolean isRestrictedToTestNetworks,
- boolean requiresValidation) throws Exception {
+ @NonNull Ikev2VpnProfileBuilderShim builderShim, boolean isRestrictedToTestNetworks,
+ boolean requiresValidation, boolean automaticIpVersionSelectionEnabled,
+ boolean automaticNattKeepaliveTimerEnabled) throws Exception {
- builder.setBypassable(true)
+ builderShim.setBypassable(true)
.setAllowedAlgorithms(TEST_ALLOWED_ALGORITHMS)
.setProxy(TEST_PROXY_INFO)
.setMaxMtu(TEST_MTU)
.setMetered(false);
if (TestUtils.shouldTestTApis()) {
- builder.setRequiresInternetValidation(requiresValidation);
+ builderShim.setRequiresInternetValidation(requiresValidation);
}
+
+ if (TestUtils.shouldTestUApis()) {
+ builderShim.setAutomaticIpVersionSelectionEnabled(automaticIpVersionSelectionEnabled);
+ builderShim.setAutomaticNattKeepaliveTimerEnabled(automaticNattKeepaliveTimerEnabled);
+ }
+
+ // Convert shim back to Ikev2VpnProfile.Builder since restrictToTestNetworks is a hidden
+ // method and is not defined in shims.
+ // TODO: replace it in alternative way to remove the hidden method usage
+ final Ikev2VpnProfile.Builder builder = (Ikev2VpnProfile.Builder) builderShim.getBuilder();
if (isRestrictedToTestNetworks) {
builder.restrictToTestNetworks();
}
@@ -249,13 +264,16 @@
? IkeSessionTestUtils.IKE_PARAMS_V6 : IkeSessionTestUtils.IKE_PARAMS_V4,
IkeSessionTestUtils.CHILD_PARAMS);
- final Ikev2VpnProfile.Builder builder =
- new Ikev2VpnProfile.Builder(params)
+ final Ikev2VpnProfileBuilderShim builderShim =
+ Ikev2VpnProfileBuilderShimImpl.newInstance(params)
.setRequiresInternetValidation(requiresValidation)
.setProxy(TEST_PROXY_INFO)
.setMaxMtu(TEST_MTU)
.setMetered(false);
-
+ // Convert shim back to Ikev2VpnProfile.Builder since restrictToTestNetworks is a hidden
+ // method and is not defined in shims.
+ // TODO: replace it in alternative way to remove the hidden method usage
+ final Ikev2VpnProfile.Builder builder = (Ikev2VpnProfile.Builder) builderShim.getBuilder();
if (isRestrictedToTestNetworks) {
builder.restrictToTestNetworks();
}
@@ -263,31 +281,35 @@
}
private Ikev2VpnProfile buildIkev2VpnProfilePsk(@NonNull String remote,
- boolean isRestrictedToTestNetworks, boolean requiresValidation) throws Exception {
- final Ikev2VpnProfile.Builder builder =
- new Ikev2VpnProfile.Builder(remote, TEST_IDENTITY).setAuthPsk(TEST_PSK);
+ boolean isRestrictedToTestNetworks, boolean requiresValidation)
+ throws Exception {
+ final Ikev2VpnProfileBuilderShim builder =
+ Ikev2VpnProfileBuilderShimImpl.newInstance(remote, TEST_IDENTITY)
+ .setAuthPsk(TEST_PSK);
return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks,
- requiresValidation);
+ requiresValidation, false /* automaticIpVersionSelectionEnabled */,
+ false /* automaticNattKeepaliveTimerEnabled */);
}
private Ikev2VpnProfile buildIkev2VpnProfileUsernamePassword(boolean isRestrictedToTestNetworks)
throws Exception {
-
- final Ikev2VpnProfile.Builder builder =
- new Ikev2VpnProfile.Builder(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
+ final Ikev2VpnProfileBuilderShim builder =
+ Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
.setAuthUsernamePassword(TEST_USER, TEST_PASSWORD, mServerRootCa);
return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks,
- false /* requiresValidation */);
+ false /* requiresValidation */, false /* automaticIpVersionSelectionEnabled */,
+ false /* automaticNattKeepaliveTimerEnabled */);
}
private Ikev2VpnProfile buildIkev2VpnProfileDigitalSignature(boolean isRestrictedToTestNetworks)
throws Exception {
- final Ikev2VpnProfile.Builder builder =
- new Ikev2VpnProfile.Builder(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
+ final Ikev2VpnProfileBuilderShim builder =
+ Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
.setAuthDigitalSignature(
mUserCertKey.cert, mUserCertKey.key, mServerRootCa);
return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks,
- false /* requiresValidation */);
+ false /* requiresValidation */, false /* automaticIpVersionSelectionEnabled */,
+ false /* automaticNattKeepaliveTimerEnabled */);
}
private void checkBasicIkev2VpnProfile(@NonNull Ikev2VpnProfile profile) throws Exception {
@@ -529,11 +551,10 @@
assertFalse(profileState.isLockdownEnabled());
}
- cb.expectCapabilitiesThat(vpnNetwork, TIMEOUT_MS,
- caps -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasCapability(NET_CAPABILITY_INTERNET)
- && !caps.hasCapability(NET_CAPABILITY_VALIDATED)
- && Process.myUid() == caps.getOwnerUid());
+ cb.expectCaps(vpnNetwork, TIMEOUT_MS, c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasCapability(NET_CAPABILITY_INTERNET)
+ && !c.hasCapability(NET_CAPABILITY_VALIDATED)
+ && Process.myUid() == c.getOwnerUid());
cb.expect(CallbackEntry.LINK_PROPERTIES_CHANGED, vpnNetwork);
cb.expect(CallbackEntry.BLOCKED_STATUS, vpnNetwork);
@@ -688,6 +709,56 @@
true /* testSessionKey */, false /* testIkeTunConnParams */);
}
+ @Test
+ public void testBuildIkev2VpnProfileWithAutomaticNattKeepaliveTimerEnabled() throws Exception {
+ // Cannot use @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) because this test also requires API
+ // 34 shims, and @IgnoreUpTo does not check that.
+ assumeTrue(TestUtils.shouldTestUApis());
+
+ final Ikev2VpnProfile profileWithDefaultValue = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6,
+ false /* isRestrictedToTestNetworks */, false /* requiresValidation */);
+ final Ikev2VpnProfileShim<Ikev2VpnProfile> shimWithDefaultValue =
+ Ikev2VpnProfileShimImpl.newInstance(profileWithDefaultValue);
+ assertFalse(shimWithDefaultValue.isAutomaticNattKeepaliveTimerEnabled());
+
+ final Ikev2VpnProfileBuilderShim builder =
+ Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
+ .setAuthPsk(TEST_PSK);
+ final Ikev2VpnProfile profile = buildIkev2VpnProfileCommon(builder,
+ false /* isRestrictedToTestNetworks */,
+ false /* requiresValidation */,
+ false /* automaticIpVersionSelectionEnabled */,
+ true /* automaticNattKeepaliveTimerEnabled */);
+ final Ikev2VpnProfileShim<Ikev2VpnProfile> shim =
+ Ikev2VpnProfileShimImpl.newInstance(profile);
+ assertTrue(shim.isAutomaticNattKeepaliveTimerEnabled());
+ }
+
+ @Test
+ public void testBuildIkev2VpnProfileWithAutomaticIpVersionSelectionEnabled() throws Exception {
+ // Cannot use @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) because this test also requires API
+ // 34 shims, and @IgnoreUpTo does not check that.
+ assumeTrue(TestUtils.shouldTestUApis());
+
+ final Ikev2VpnProfile profileWithDefaultValue = buildIkev2VpnProfilePsk(TEST_SERVER_ADDR_V6,
+ false /* isRestrictedToTestNetworks */, false /* requiresValidation */);
+ final Ikev2VpnProfileShim<Ikev2VpnProfile> shimWithDefaultValue =
+ Ikev2VpnProfileShimImpl.newInstance(profileWithDefaultValue);
+ assertFalse(shimWithDefaultValue.isAutomaticIpVersionSelectionEnabled());
+
+ final Ikev2VpnProfileBuilderShim builder =
+ Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
+ .setAuthPsk(TEST_PSK);
+ final Ikev2VpnProfile profile = buildIkev2VpnProfileCommon(builder,
+ false /* isRestrictedToTestNetworks */,
+ false /* requiresValidation */,
+ true /* automaticIpVersionSelectionEnabled */,
+ false /* automaticNattKeepaliveTimerEnabled */);
+ final Ikev2VpnProfileShim<Ikev2VpnProfile> shim =
+ Ikev2VpnProfileShimImpl.newInstance(profile);
+ assertTrue(shim.isAutomaticIpVersionSelectionEnabled());
+ }
+
private static class CertificateAndKey {
public final X509Certificate cert;
public final PrivateKey key;
diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
index 8234ec1..f935cef 100644
--- a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
@@ -16,6 +16,7 @@
package android.net.cts;
+import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.net.IpSecAlgorithm.AUTH_AES_CMAC;
import static android.net.IpSecAlgorithm.AUTH_AES_XCBC;
import static android.net.IpSecAlgorithm.AUTH_CRYPT_AES_GCM;
@@ -52,7 +53,9 @@
import static com.android.compatibility.common.util.PropertyUtil.getFirstApiLevel;
import static com.android.compatibility.common.util.PropertyUtil.getVendorApiLevel;
+import static com.android.testutils.DeviceInfoUtils.isKernelVersionAtLeast;
import static com.android.testutils.MiscAsserts.assertThrows;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -62,6 +65,8 @@
import android.net.IpSecAlgorithm;
import android.net.IpSecManager;
+import android.net.IpSecManager.SecurityParameterIndex;
+import android.net.IpSecManager.UdpEncapsulationSocket;
import android.net.IpSecTransform;
import android.net.TrafficStats;
import android.os.Build;
@@ -73,6 +78,7 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.modules.utils.build.SdkLevel;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -120,7 +126,7 @@
@Test
public void testAllocSpi() throws Exception {
for (InetAddress addr : GOOGLE_DNS_LIST) {
- IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
+ SecurityParameterIndex randomSpi, droidSpi;
randomSpi = mISM.allocateSecurityParameterIndex(addr);
assertTrue(
"Failed to receive a valid SPI",
@@ -258,6 +264,24 @@
accepted.close();
}
+ private IpSecTransform buildTransportModeTransform(
+ SecurityParameterIndex spi, InetAddress localAddr,
+ UdpEncapsulationSocket encapSocket)
+ throws Exception {
+ final IpSecTransform.Builder builder =
+ 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));
+ if (encapSocket != null) {
+ builder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
+ }
+ return builder.buildTransportModeTransform(localAddr, spi);
+ }
+
/*
* Alloc outbound SPI
* Alloc inbound SPI
@@ -268,21 +292,8 @@
* 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);
+ private void doTestCreateTransform(String loopbackAddrString, boolean encap) throws Exception {
+ InetAddress localAddr = InetAddress.getByName(loopbackAddrString);
final boolean [][] applyInApplyOut = {
{false, false}, {false, true}, {true, false}, {true,true}};
@@ -291,57 +302,110 @@
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 {
+ try (
+ SecurityParameterIndex spi = mISM.allocateSecurityParameterIndex(localAddr);
+ UdpEncapsulationSocket encapSocket = encap
+ ? getPrivilegedUdpEncapSocket(/*ipv6=*/ localAddr instanceof Inet6Address)
+ : null;
+ IpSecTransform transform = buildTransportModeTransform(spi, localAddr,
+ encapSocket);
+ // Bind localSocket to a random available port.
+ DatagramSocket 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);
- } catch (IOException e) {
- continue;
- } finally {
+ assertTrue("Encrypted 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);
+ }
+ // 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);
}
- // 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();
+ }
+
+ private UdpEncapsulationSocket getPrivilegedUdpEncapSocket(boolean ipv6) throws Exception {
+ return runAsShell(NETWORK_SETTINGS, () -> {
+ if (ipv6) {
+ return mISM.openUdpEncapsulationSocket(65536);
+ } else {
+ // Can't pass 0 to IpSecManager#openUdpEncapsulationSocket(int).
+ return mISM.openUdpEncapsulationSocket();
+ }
+ });
+ }
+
+ private static boolean isIpv6UdpEncapSupportedByKernel() {
+ return isKernelVersionAtLeast("5.15.31")
+ || (isKernelVersionAtLeast("5.10.108") && !isKernelVersionAtLeast("5.15.0"));
+ }
+
+ // Packet private for use in IpSecManagerTunnelTest
+ static boolean isIpv6UdpEncapSupported() {
+ return SdkLevel.isAtLeastU() && isIpv6UdpEncapSupportedByKernel();
+ }
+
+ // Packet private for use in IpSecManagerTunnelTest
+ static void assumeExperimentalIpv6UdpEncapSupported() throws Exception {
+ assumeTrue("Not supported before U", SdkLevel.isAtLeastU());
+ assumeTrue("Not supported by kernel", isIpv6UdpEncapSupportedByKernel());
+ }
+
+ @Test
+ public void testCreateTransformIpv4() throws Exception {
+ doTestCreateTransform(IPV4_LOOPBACK, false);
+ }
+
+ @Test
+ public void testCreateTransformIpv6() throws Exception {
+ doTestCreateTransform(IPV6_LOOPBACK, false);
+ }
+
+ @Test
+ public void testCreateTransformIpv4Encap() throws Exception {
+ doTestCreateTransform(IPV4_LOOPBACK, true);
+ }
+
+ @Test
+ public void testCreateTransformIpv6Encap() throws Exception {
+ assumeExperimentalIpv6UdpEncapSupported();
+ doTestCreateTransform(IPV6_LOOPBACK, true);
}
/** 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 final int MAX_WAIT_TIME_MILLIS = 3000;
private static long uidTxBytes;
private static long uidRxBytes;
@@ -503,8 +567,8 @@
StatsChecker.initStatsChecker();
InetAddress local = InetAddress.getByName(localAddress);
- try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
- IpSecManager.SecurityParameterIndex spi =
+ try (UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket();
+ SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(local)) {
IpSecTransform.Builder transformBuilder =
@@ -656,7 +720,7 @@
public void testIkeOverUdpEncapSocket() throws Exception {
// IPv6 not supported for UDP-encap-ESP
InetAddress local = InetAddress.getByName(IPV4_LOOPBACK);
- try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+ try (UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
NativeUdpSocket wrappedEncapSocket =
new NativeUdpSocket(encapSocket.getFileDescriptor());
checkIkePacket(wrappedEncapSocket, local);
@@ -665,7 +729,7 @@
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 =
+ try (SecurityParameterIndex spi =
mISM.allocateSecurityParameterIndex(local);
IpSecTransform transform =
new IpSecTransform.Builder(InstrumentationRegistry.getContext())
@@ -1498,7 +1562,7 @@
@Test
public void testOpenUdpEncapSocketSpecificPort() throws Exception {
- IpSecManager.UdpEncapsulationSocket encapSocket = null;
+ UdpEncapsulationSocket encapSocket = null;
int port = -1;
for (int i = 0; i < MAX_PORT_BIND_ATTEMPTS; i++) {
try {
@@ -1527,7 +1591,7 @@
@Test
public void testOpenUdpEncapSocketRandomPort() throws Exception {
- try (IpSecManager.UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+ try (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
index 5fc3068..1ede5c1 100644
--- a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
@@ -18,6 +18,8 @@
import static android.app.AppOpsManager.OP_MANAGE_IPSEC_TUNNELS;
import static android.net.IpSecManager.UdpEncapsulationSocket;
+import static android.net.cts.IpSecManagerTest.assumeExperimentalIpv6UdpEncapSupported;
+import static android.net.cts.IpSecManagerTest.isIpv6UdpEncapSupported;
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;
@@ -76,6 +78,7 @@
import java.net.InetAddress;
import java.net.NetworkInterface;
+// TODO: b/268552823 Improve the readability of IpSecManagerTunnelTest
@RunWith(AndroidJUnit4.class)
@AppModeFull(reason = "MANAGE_TEST_NETWORKS permission can't be granted to instant apps")
public class IpSecManagerTunnelTest extends IpSecBaseTest {
@@ -83,11 +86,6 @@
private static final String TAG = IpSecManagerTunnelTest.class.getSimpleName();
- // Redefine this flag here so that IPsec code shipped in a mainline module can build on old
- // platforms before FEATURE_IPSEC_TUNNEL_MIGRATION API is released.
- private static final String FEATURE_IPSEC_TUNNEL_MIGRATION =
- "android.software.ipsec_tunnel_migration";
-
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 =
@@ -115,6 +113,7 @@
private static final int IP4_PREFIX_LEN = 32;
private static final int IP6_PREFIX_LEN = 128;
+ private static final int IP6_UDP_ENCAP_SOCKET_PORT_ANY = 65536;
private static final int TIMEOUT_MS = 500;
@@ -263,14 +262,23 @@
*
* @param ipsecNetwork The IPsec Interface based Network for binding sockets on
* @param tunnelIface The IPsec tunnel interface that will be tested
- * @param underlyingTunUtils The utility of the IPsec tunnel interface's underlying TUN
- * network
- * @return the integer port of the inner socket if outbound, or 0 if inbound
- * IpSecTunnelTestRunnable
+ * @param tunUtils The utility of the IPsec tunnel interface's underlying TUN network
+ * @param inTunnelTransform The inbound tunnel mode transform
+ * @param outTunnelTransform The outbound tunnel mode transform
+ * @param localOuter The local address of the outer IP packet
+ * @param remoteOuter The remote address of the outer IP packet
+ * @param seqNum The expected sequence number of the inbound packet
* @throws Exception if any part of the test failed.
*/
public abstract int run(
- Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils underlyingTunUtils)
+ Network ipsecNetwork,
+ IpSecTunnelInterface tunnelIface,
+ TunUtils tunUtils,
+ IpSecTransform inTunnelTransform,
+ IpSecTransform outTunnelTransform,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ int seqNum)
throws Exception;
}
@@ -305,19 +313,41 @@
return expectedPacketSize;
}
+ private UdpEncapsulationSocket openUdpEncapsulationSocket(int ipVersion) throws Exception {
+ if (ipVersion == AF_INET) {
+ return mISM.openUdpEncapsulationSocket();
+ }
+
+ if (!isIpv6UdpEncapSupported()) {
+ throw new UnsupportedOperationException("IPv6 UDP encapsulation unsupported");
+ }
+
+ return mISM.openUdpEncapsulationSocket(IP6_UDP_ENCAP_SOCKET_PORT_ANY);
+ }
+
private interface IpSecTunnelTestRunnableFactory {
+ /**
+ * Build a IpSecTunnelTestRunnable.
+ *
+ * @param transportInTunnelMode indicate if there needs to be a transport mode transform
+ * inside the tunnel mode transform
+ * @param spi The IPsec SPI
+ * @param localInner The local address of the inner IP packet
+ * @param remoteInner The remote address of the inner IP packet
+ * @param inTransportTransform The inbound transport mode transform
+ * @param outTransportTransform The outbound transport mode transform
+ * @param encapSocket The UDP encapsulation socket or null
+ * @param innerSocketPort The inner socket port
+ */
IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
boolean transportInTunnelMode,
int spi,
InetAddress localInner,
InetAddress remoteInner,
- InetAddress localOuter,
- InetAddress remoteOuter,
IpSecTransform inTransportTransform,
IpSecTransform outTransportTransform,
- int encapPort,
- int innerSocketPort,
- int expectedPacketSize)
+ UdpEncapsulationSocket encapSocket,
+ int innerSocketPort)
throws Exception;
}
@@ -327,17 +357,21 @@
int spi,
InetAddress localInner,
InetAddress remoteInner,
- InetAddress localOuter,
- InetAddress remoteOuter,
IpSecTransform inTransportTransform,
IpSecTransform outTransportTransform,
- int encapPort,
- int unusedInnerSocketPort,
- int expectedPacketSize) {
+ UdpEncapsulationSocket encapSocket,
+ int unusedInnerSocketPort) {
return new IpSecTunnelTestRunnable() {
@Override
public int run(
- Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils tunUtils)
+ Network ipsecNetwork,
+ IpSecTunnelInterface tunnelIface,
+ TunUtils tunUtils,
+ IpSecTransform inTunnelTransform,
+ IpSecTransform outTunnelTransform,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ int seqNum)
throws Exception {
// Build a socket and send traffic
JavaUdpSocket socket = new JavaUdpSocket(localInner);
@@ -357,9 +391,14 @@
// 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)
+ int innerFamily = localInner instanceof Inet4Address ? AF_INET : AF_INET6;
+ int outerFamily = localOuter instanceof Inet4Address ? AF_INET : AF_INET6;
+ boolean useEncap = encapSocket != null;
+ int expectedPacketSize =
+ getPacketSize(
+ innerFamily, outerFamily, useEncap, transportInTunnelMode);
tunUtils.awaitEspPacketNoPlaintext(
- spi, TEST_DATA, encapPort != 0, expectedPacketSize);
-
+ spi, TEST_DATA, useEncap, expectedPacketSize);
socket.close();
return innerSocketPort;
@@ -375,18 +414,22 @@
int spi,
InetAddress localInner,
InetAddress remoteInner,
- InetAddress localOuter,
- InetAddress remoteOuter,
IpSecTransform inTransportTransform,
IpSecTransform outTransportTransform,
- int encapPort,
- int innerSocketPort,
- int expectedPacketSize)
+ UdpEncapsulationSocket encapSocket,
+ int innerSocketPort)
throws Exception {
return new IpSecTunnelTestRunnable() {
@Override
public int run(
- Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils tunUtils)
+ Network ipsecNetwork,
+ IpSecTunnelInterface tunnelIface,
+ TunUtils tunUtils,
+ IpSecTransform inTunnelTransform,
+ IpSecTransform outTunnelTransform,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ int seqNum)
throws Exception {
// Build a socket and receive traffic
JavaUdpSocket socket = new JavaUdpSocket(localInner, innerSocketPort);
@@ -420,18 +463,22 @@
int spi,
InetAddress localInner,
InetAddress remoteInner,
- InetAddress localOuter,
- InetAddress remoteOuter,
IpSecTransform inTransportTransform,
IpSecTransform outTransportTransform,
- int encapPort,
- int innerSocketPort,
- int expectedPacketSize)
+ UdpEncapsulationSocket encapSocket,
+ int innerSocketPort)
throws Exception {
return new IpSecTunnelTestRunnable() {
@Override
public int run(
- Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils tunUtils)
+ Network ipsecNetwork,
+ IpSecTunnelInterface tunnelIface,
+ TunUtils tunUtils,
+ IpSecTransform inTunnelTransform,
+ IpSecTransform outTunnelTransform,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ int seqNum)
throws Exception {
// Build a socket and receive traffic
JavaUdpSocket socket = new JavaUdpSocket(localInner);
@@ -456,7 +503,8 @@
remoteOuter,
localOuter,
socket.getPort(),
- encapPort);
+ encapSocket != null ? encapSocket.getPort() : 0,
+ seqNum);
} else {
pkt =
getTunnelModePacket(
@@ -466,7 +514,8 @@
remoteOuter,
localOuter,
socket.getPort(),
- encapPort);
+ encapSocket != null ? encapSocket.getPort() : 0,
+ seqNum);
}
tunUtils.injectPacket(pkt);
@@ -483,13 +532,16 @@
private class MigrateIpSecTunnelTestRunnableFactory implements IpSecTunnelTestRunnableFactory {
private final IpSecTunnelTestRunnableFactory mTestRunnableFactory;
+ private final boolean mTestEncapTypeChange;
- MigrateIpSecTunnelTestRunnableFactory(boolean isOutputTest) {
+ MigrateIpSecTunnelTestRunnableFactory(boolean isOutputTest, boolean testEncapTypeChange) {
if (isOutputTest) {
mTestRunnableFactory = new OutputIpSecTunnelTestRunnableFactory();
} else {
mTestRunnableFactory = new InputPacketGeneratorIpSecTunnelTestRunnableFactory();
}
+
+ mTestEncapTypeChange = testEncapTypeChange;
}
@Override
@@ -498,17 +550,21 @@
int spi,
InetAddress localInner,
InetAddress remoteInner,
- InetAddress localOuter,
- InetAddress remoteOuter,
IpSecTransform inTransportTransform,
IpSecTransform outTransportTransform,
- int encapPort,
- int unusedInnerSocketPort,
- int expectedPacketSize) {
+ UdpEncapsulationSocket encapSocket,
+ int unusedInnerSocketPort) {
return new IpSecTunnelTestRunnable() {
@Override
public int run(
- Network ipsecNetwork, IpSecTunnelInterface tunnelIface, TunUtils tunUtils)
+ Network ipsecNetwork,
+ IpSecTunnelInterface tunnelIface,
+ TunUtils tunUtils,
+ IpSecTransform inTunnelTransform,
+ IpSecTransform outTunnelTransform,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ int seqNum)
throws Exception {
mTestRunnableFactory
.getIpSecTunnelTestRunnable(
@@ -516,17 +572,25 @@
spi,
localInner,
remoteInner,
- localOuter,
- remoteOuter,
inTransportTransform,
outTransportTransform,
- encapPort,
- unusedInnerSocketPort,
- expectedPacketSize)
- .run(ipsecNetwork, tunnelIface, sTunWrapper.utils);
-
+ encapSocket,
+ unusedInnerSocketPort)
+ .run(
+ ipsecNetwork,
+ tunnelIface,
+ tunUtils,
+ inTunnelTransform,
+ outTunnelTransform,
+ localOuter,
+ remoteOuter,
+ seqNum);
tunnelIface.setUnderlyingNetwork(sTunWrapperNew.network);
+ final boolean useEncapBeforeMigrate = encapSocket != null;
+ final boolean useEncapAfterMigrate =
+ mTestEncapTypeChange ? !useEncapBeforeMigrate : useEncapBeforeMigrate;
+
// Verify migrating to IPv4 and IPv6 addresses. It ensures that not only
// can IPsec tunnel migrate across interfaces, IPsec tunnel can also migrate to
// a different address on the same interface.
@@ -535,21 +599,24 @@
remoteInner,
LOCAL_OUTER_4_NEW,
REMOTE_OUTER_4_NEW,
- encapPort != 0,
+ useEncapAfterMigrate,
transportInTunnelMode,
sTunWrapperNew.utils,
tunnelIface,
ipsecNetwork);
- checkMigratedTunnel(
- localInner,
- remoteInner,
- LOCAL_OUTER_6_NEW,
- REMOTE_OUTER_6_NEW,
- false, // IPv6 does not support UDP encapsulation
- transportInTunnelMode,
- sTunWrapperNew.utils,
- tunnelIface,
- ipsecNetwork);
+
+ if (!useEncapAfterMigrate || isIpv6UdpEncapSupported()) {
+ checkMigratedTunnel(
+ localInner,
+ remoteInner,
+ LOCAL_OUTER_6_NEW,
+ REMOTE_OUTER_6_NEW,
+ useEncapAfterMigrate,
+ transportInTunnelMode,
+ sTunWrapperNew.utils,
+ tunnelIface,
+ ipsecNetwork);
+ }
return 0;
}
@@ -589,7 +656,8 @@
buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
IpSecTransform outTransportTransform =
buildIpSecTransform(sContext, outTransportSpi, null, localInner);
- UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+ UdpEncapsulationSocket encapSocket =
+ useEncap ? openUdpEncapsulationSocket(outerFamily) : null) {
// Configure tunnel mode Transform parameters
IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(sContext);
@@ -599,7 +667,7 @@
new IpSecAlgorithm(
IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4));
- if (useEncap) {
+ if (encapSocket != null) {
transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
}
@@ -623,19 +691,152 @@
spi,
localInner,
remoteInner,
- localOuter,
- remoteOuter,
inTransportTransform,
outTransportTransform,
- useEncap ? encapSocket.getPort() : 0,
- 0,
- expectedPacketSize)
- .run(ipsecNetwork, tunnelIface, tunUtils);
+ encapSocket,
+ 0)
+ .run(
+ ipsecNetwork,
+ tunnelIface,
+ tunUtils,
+ inTransform,
+ outTransform,
+ localOuter,
+ remoteOuter,
+ 1 /* seqNum */);
}
}
}
}
+ private class MigrateTunnelModeIpSecTransformTestRunnableFactory
+ implements IpSecTunnelTestRunnableFactory {
+ private final IpSecTunnelTestRunnableFactory mTestRunnableFactory;
+
+ MigrateTunnelModeIpSecTransformTestRunnableFactory(boolean isOutputTest) {
+ if (isOutputTest) {
+ mTestRunnableFactory = new OutputIpSecTunnelTestRunnableFactory();
+ } else {
+ mTestRunnableFactory = new InputPacketGeneratorIpSecTunnelTestRunnableFactory();
+ }
+ }
+
+ @Override
+ public IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
+ boolean transportInTunnelMode,
+ int spi,
+ InetAddress localInner,
+ InetAddress remoteInner,
+ IpSecTransform inTransportTransform,
+ IpSecTransform outTransportTransform,
+ UdpEncapsulationSocket encapSocket,
+ int unusedInnerSocketPort) {
+ return new IpSecTunnelTestRunnable() {
+ @Override
+ public int run(
+ Network ipsecNetwork,
+ IpSecTunnelInterface tunnelIface,
+ TunUtils tunUtils,
+ IpSecTransform inTunnelTransform,
+ IpSecTransform outTunnelTransform,
+ InetAddress localOuter,
+ InetAddress remoteOuter,
+ int seqNum)
+ throws Exception {
+ final IpSecTunnelTestRunnable testRunnable =
+ mTestRunnableFactory.getIpSecTunnelTestRunnable(
+ transportInTunnelMode,
+ spi,
+ localInner,
+ remoteInner,
+ inTransportTransform,
+ outTransportTransform,
+ encapSocket,
+ unusedInnerSocketPort);
+ testRunnable.run(
+ ipsecNetwork,
+ tunnelIface,
+ tunUtils,
+ inTunnelTransform,
+ outTunnelTransform,
+ localOuter,
+ remoteOuter,
+ seqNum++);
+
+ tunnelIface.setUnderlyingNetwork(sTunWrapperNew.network);
+
+ final boolean useEncap = encapSocket != null;
+ if (useEncap) {
+ sTunWrapperNew.network.bindSocket(encapSocket.getFileDescriptor());
+ }
+
+ // Updating UDP encapsulation socket is not supported. Thus this runnable will
+ // only cover 1) migration from non-encap to non-encap and 2) migration from
+ // encap to encap with the same family
+ if (!useEncap || localOuter instanceof Inet4Address) {
+ checkMigrateTunnelModeTransform(
+ testRunnable,
+ inTunnelTransform,
+ outTunnelTransform,
+ tunnelIface,
+ ipsecNetwork,
+ sTunWrapperNew.utils,
+ LOCAL_OUTER_4_NEW,
+ REMOTE_OUTER_4_NEW,
+ seqNum++);
+ }
+ if (!useEncap || localOuter instanceof Inet6Address) {
+ checkMigrateTunnelModeTransform(
+ testRunnable,
+ inTunnelTransform,
+ outTunnelTransform,
+ tunnelIface,
+ ipsecNetwork,
+ sTunWrapperNew.utils,
+ LOCAL_OUTER_6_NEW,
+ REMOTE_OUTER_6_NEW,
+ seqNum++);
+ }
+
+ // Unused return value for MigrateTunnelModeIpSecTransformTest
+ return 0;
+ }
+ };
+ }
+
+ private void checkMigrateTunnelModeTransform(
+ IpSecTunnelTestRunnable testRunnable,
+ IpSecTransform inTunnelTransform,
+ IpSecTransform outTunnelTransform,
+ IpSecTunnelInterface tunnelIface,
+ Network ipsecNetwork,
+ TunUtils tunUtils,
+ InetAddress newLocalOuter,
+ InetAddress newRemoteOuter,
+ int seqNum)
+ throws Exception {
+ mISM.startTunnelModeTransformMigration(
+ inTunnelTransform, newRemoteOuter, newLocalOuter);
+ mISM.startTunnelModeTransformMigration(
+ outTunnelTransform, newLocalOuter, newRemoteOuter);
+
+ mISM.applyTunnelModeTransform(
+ tunnelIface, IpSecManager.DIRECTION_IN, inTunnelTransform);
+ mISM.applyTunnelModeTransform(
+ tunnelIface, IpSecManager.DIRECTION_OUT, outTunnelTransform);
+
+ testRunnable.run(
+ ipsecNetwork,
+ tunnelIface,
+ tunUtils,
+ inTunnelTransform,
+ outTunnelTransform,
+ newLocalOuter,
+ newRemoteOuter,
+ seqNum);
+ }
+ }
+
private void checkTunnelOutput(
int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
throws Exception {
@@ -659,17 +860,36 @@
}
private void checkMigrateTunnelOutput(
- int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ int innerFamily,
+ int outerFamily,
+ boolean useEncap,
+ boolean transportInTunnelMode,
+ boolean isEncapTypeChanged)
throws Exception {
checkTunnel(
innerFamily,
outerFamily,
useEncap,
transportInTunnelMode,
- new MigrateIpSecTunnelTestRunnableFactory(true));
+ new MigrateIpSecTunnelTestRunnableFactory(true, isEncapTypeChanged));
}
private void checkMigrateTunnelInput(
+ int innerFamily,
+ int outerFamily,
+ boolean useEncap,
+ boolean transportInTunnelMode,
+ boolean isEncapTypeChanged)
+ throws Exception {
+ checkTunnel(
+ innerFamily,
+ outerFamily,
+ useEncap,
+ transportInTunnelMode,
+ new MigrateIpSecTunnelTestRunnableFactory(false, isEncapTypeChanged));
+ }
+
+ private void checkMigrateTunnelModeTransformOutput(
int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
throws Exception {
checkTunnel(
@@ -677,7 +897,18 @@
outerFamily,
useEncap,
transportInTunnelMode,
- new MigrateIpSecTunnelTestRunnableFactory(false));
+ new MigrateTunnelModeIpSecTransformTestRunnableFactory(true /* isOutputTest */));
+ }
+
+ private void checkMigrateTunnelModeTransformInput(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ throws Exception {
+ checkTunnel(
+ innerFamily,
+ outerFamily,
+ useEncap,
+ transportInTunnelMode,
+ new MigrateTunnelModeIpSecTransformTestRunnableFactory(false /* isOutputTest */));
}
/**
@@ -709,7 +940,8 @@
buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
IpSecTransform outTransportTransform =
buildIpSecTransform(sContext, outTransportSpi, null, localInner);
- UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+ UdpEncapsulationSocket encapSocket =
+ useEncap ? openUdpEncapsulationSocket(outerFamily) : null) {
// Run output direction tests
IpSecTunnelTestRunnable outputIpSecTunnelTestRunnable =
@@ -719,22 +951,19 @@
spi,
localInner,
remoteInner,
- localOuter,
- remoteOuter,
inTransportTransform,
outTransportTransform,
- useEncap ? encapSocket.getPort() : 0,
- 0,
- expectedPacketSize);
+ encapSocket,
+ 0);
int innerSocketPort =
buildTunnelNetworkAndRunTests(
- localInner,
- remoteInner,
- localOuter,
- remoteOuter,
- spi,
- useEncap ? encapSocket : null,
- outputIpSecTunnelTestRunnable);
+ localInner,
+ remoteInner,
+ localOuter,
+ remoteOuter,
+ spi,
+ encapSocket,
+ outputIpSecTunnelTestRunnable);
// Input direction tests, with matching inner socket ports.
IpSecTunnelTestRunnable inputIpSecTunnelTestRunnable =
@@ -744,20 +973,17 @@
spi,
remoteInner,
localInner,
- localOuter,
- remoteOuter,
inTransportTransform,
outTransportTransform,
- useEncap ? encapSocket.getPort() : 0,
- innerSocketPort,
- expectedPacketSize);
+ encapSocket,
+ innerSocketPort);
buildTunnelNetworkAndRunTests(
remoteInner,
localInner,
localOuter,
remoteOuter,
spi,
- useEncap ? encapSocket : null,
+ encapSocket,
inputIpSecTunnelTestRunnable);
}
}
@@ -791,7 +1017,8 @@
buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
IpSecTransform outTransportTransform =
buildIpSecTransform(sContext, outTransportSpi, null, localInner);
- UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+ UdpEncapsulationSocket encapSocket =
+ useEncap ? openUdpEncapsulationSocket(outerFamily) : null) {
buildTunnelNetworkAndRunTests(
localInner,
@@ -799,19 +1026,16 @@
localOuter,
remoteOuter,
spi,
- useEncap ? encapSocket : null,
+ encapSocket,
factory.getIpSecTunnelTestRunnable(
transportInTunnelMode,
spi,
localInner,
remoteInner,
- localOuter,
- remoteOuter,
inTransportTransform,
outTransportTransform,
- useEncap ? encapSocket.getPort() : 0,
- 0,
- expectedPacketSize));
+ encapSocket,
+ 0));
}
}
@@ -859,6 +1083,7 @@
if (encapSocket != null) {
transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
+ sTunWrapper.network.bindSocket(encapSocket.getFileDescriptor());
}
// Apply transform and check that traffic is properly encrypted
@@ -870,7 +1095,16 @@
mISM.applyTunnelModeTransform(
tunnelIface, IpSecManager.DIRECTION_OUT, outTransform);
- innerSocketPort = test.run(testNetwork, tunnelIface, sTunWrapper.utils);
+ innerSocketPort =
+ test.run(
+ testNetwork,
+ tunnelIface,
+ sTunWrapper.utils,
+ inTransform,
+ outTransform,
+ localOuter,
+ remoteOuter,
+ 1 /* seqNum */);
}
// Teardown the test network
@@ -909,13 +1143,14 @@
}
private EspHeader buildTransportModeEspPacket(
- int spi, InetAddress src, InetAddress dst, int port, Payload payload) throws Exception {
+ int spi, int seqNum, InetAddress src, InetAddress dst, Payload payload)
+ throws Exception {
IpHeader preEspIpHeader = getIpHeader(payload.getProtocolId(), src, dst, payload);
return new EspHeader(
payload.getProtocolId(),
spi,
- 1, // sequence number
+ seqNum,
CRYPT_KEY, // Same key for auth and crypt
payload.getPacketBytes(preEspIpHeader));
}
@@ -928,13 +1163,14 @@
InetAddress dstOuter,
int port,
int encapPort,
+ int seqNum,
Payload payload)
throws Exception {
IpHeader innerIp = getIpHeader(payload.getProtocolId(), srcInner, dstInner, payload);
return new EspHeader(
innerIp.getProtocolId(),
spi,
- 1, // sequence number
+ seqNum, // sequence number
CRYPT_KEY, // Same key for auth and crypt
innerIp.getPacketBytes());
}
@@ -958,13 +1194,14 @@
InetAddress srcOuter,
InetAddress dstOuter,
int port,
- int encapPort)
+ int encapPort,
+ int seqNum)
throws Exception {
UdpHeader udp = new UdpHeader(port, port, new BytePayload(TEST_DATA));
EspHeader espPayload =
buildTunnelModeEspPacket(
- spi, srcInner, dstInner, srcOuter, dstOuter, port, encapPort, udp);
+ spi, srcInner, dstInner, srcOuter, dstOuter, port, encapPort, seqNum, udp);
return maybeEncapPacket(srcOuter, dstOuter, encapPort, espPayload).getPacketBytes();
}
@@ -976,11 +1213,13 @@
InetAddress srcOuter,
InetAddress dstOuter,
int port,
- int encapPort)
+ int encapPort,
+ int seqNum)
throws Exception {
UdpHeader udp = new UdpHeader(port, port, new BytePayload(TEST_DATA));
- EspHeader espPayload = buildTransportModeEspPacket(spiInner, srcInner, dstInner, port, udp);
+ EspHeader espPayload =
+ buildTransportModeEspPacket(spiInner, seqNum, srcInner, dstInner, udp);
espPayload =
buildTunnelModeEspPacket(
spiOuter,
@@ -990,21 +1229,56 @@
dstOuter,
port,
encapPort,
+ seqNum,
espPayload);
return maybeEncapPacket(srcOuter, dstOuter, encapPort, espPayload).getPacketBytes();
}
private void doTestMigrateTunnel(
+ int innerFamily,
+ int outerFamily,
+ boolean useEncap,
+ boolean transportInTunnelMode,
+ boolean testEncapTypeChange)
+ throws Exception {
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
+ checkMigrateTunnelOutput(
+ innerFamily, outerFamily, useEncap, transportInTunnelMode, testEncapTypeChange);
+ checkMigrateTunnelInput(
+ innerFamily, outerFamily, useEncap, transportInTunnelMode, testEncapTypeChange);
+ }
+
+ private void doTestMigrateTunnel(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ throws Exception {
+ doTestMigrateTunnel(
+ innerFamily,
+ outerFamily,
+ useEncap,
+ transportInTunnelMode,
+ false /* testEncapTypeChange */);
+ }
+
+ private void doTestMigrateTunnelWithEncapTypeChange(
+ int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+ throws Exception {
+ doTestMigrateTunnel(
+ innerFamily,
+ outerFamily,
+ useEncap,
+ transportInTunnelMode,
+ true /* testEncapTypeChange */);
+ }
+
+ private void doTestMigrateTunnelModeTransform(
int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
- checkTunnelOutput(innerFamily, outerFamily, useEncap, transportInTunnelMode);
- checkTunnelInput(innerFamily, outerFamily, useEncap, transportInTunnelMode);
- }
-
- /** Checks if FEATURE_IPSEC_TUNNEL_MIGRATION is enabled on the device */
- private static boolean hasIpsecTunnelMigrateFeature() {
- return sContext.getPackageManager().hasSystemFeature(FEATURE_IPSEC_TUNNEL_MIGRATION);
+ assumeTrue(mCtsNetUtils.hasIpsecTunnelMigrateFeature());
+ checkMigrateTunnelModeTransformOutput(
+ innerFamily, outerFamily, useEncap, transportInTunnelMode);
+ checkMigrateTunnelModeTransformInput(
+ innerFamily, outerFamily, useEncap, transportInTunnelMode);
}
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
@@ -1012,28 +1286,7 @@
public void testHasIpSecTunnelMigrateFeature() throws Exception {
// FEATURE_IPSEC_TUNNEL_MIGRATION is required when VSR API is U/U+
if (getVsrApiLevel() > Build.VERSION_CODES.TIRAMISU) {
- assertTrue(hasIpsecTunnelMigrateFeature());
- }
- }
-
- @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
- @Test
- public void testMigrateTunnelModeTransform() throws Exception {
- assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
- assumeTrue(hasIpsecTunnelMigrateFeature());
-
- 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));
- int spi = getRandomSpi(LOCAL_OUTER_4, REMOTE_OUTER_4);
-
- try (IpSecManager.SecurityParameterIndex outSpi =
- mISM.allocateSecurityParameterIndex(REMOTE_OUTER_4, spi);
- IpSecTransform outTunnelTransform =
- transformBuilder.buildTunnelModeTransform(LOCAL_INNER_4, outSpi)) {
- mISM.startTunnelModeTransformMigration(
- outTunnelTransform, LOCAL_OUTER_4_NEW, REMOTE_OUTER_4_NEW);
+ assertTrue(mCtsNetUtils.hasIpsecTunnelMigrateFeature());
}
}
@@ -1051,6 +1304,12 @@
doTestMigrateTunnel(AF_INET, AF_INET, false, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV4InV4_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET, false, true);
+ }
+
@Test
public void testTransportInTunnelModeV4InV4Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1070,6 +1329,12 @@
doTestMigrateTunnel(AF_INET, AF_INET, true, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV4InV4UdpEncap_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET, true, true);
+ }
+
@Test
public void testTransportInTunnelModeV4InV4UdpEncapReflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1089,6 +1354,12 @@
doTestMigrateTunnel(AF_INET, AF_INET6, false, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV4InV6_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET6, false, true);
+ }
+
@Test
public void testTransportInTunnelModeV4InV6Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1108,6 +1379,12 @@
doTestMigrateTunnel(AF_INET6, AF_INET, false, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV6InV4_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET, false, true);
+ }
+
@Test
public void testTransportInTunnelModeV6InV4Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1127,6 +1404,12 @@
doTestMigrateTunnel(AF_INET6, AF_INET, true, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV6InV4UdpEncap_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET, true, true);
+ }
+
@Test
public void testTransportInTunnelModeV6InV4UdpEncapReflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1146,6 +1429,12 @@
doTestMigrateTunnel(AF_INET, AF_INET6, false, true);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTransportInTunnelModeV6InV6_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET6, false, true);
+ }
+
@Test
public void testTransportInTunnelModeV6InV6Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1166,6 +1455,12 @@
doTestMigrateTunnel(AF_INET, AF_INET, false, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV4InV4_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET, false, false);
+ }
+
@Test
public void testTunnelV4InV4Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1185,6 +1480,12 @@
doTestMigrateTunnel(AF_INET, AF_INET, true, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV4InV4UdpEncap_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET, true, false);
+ }
+
@Test
public void testTunnelV4InV4UdpEncapReflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1204,6 +1505,12 @@
doTestMigrateTunnel(AF_INET, AF_INET6, false, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV4InV6_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET6, false, false);
+ }
+
@Test
public void testTunnelV4InV6Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1223,6 +1530,12 @@
doTestMigrateTunnel(AF_INET6, AF_INET, false, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV6InV4_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET, false, false);
+ }
+
@Test
public void testTunnelV6InV4Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1242,6 +1555,12 @@
doTestMigrateTunnel(AF_INET6, AF_INET, true, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV6InV4UdpEncap_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET, true, false);
+ }
+
@Test
public void testTunnelV6InV4UdpEncapReflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1261,9 +1580,115 @@
doTestMigrateTunnel(AF_INET6, AF_INET6, false, false);
}
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testMigrateTunnelV6InV6_EncapTypeChange() throws Exception {
+ doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET6, false, false);
+ }
+
@Test
public void testTunnelV6InV6Reflected() throws Exception {
assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
checkTunnelReflected(AF_INET6, AF_INET6, false, false);
}
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTransportInTunnelModeV4InV4() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET, AF_INET, false, true);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTransportInTunnelModeV6InV4() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET6, AF_INET, false, true);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTransportInTunnelModeV4InV6() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET, AF_INET6, false, true);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTransportInTunnelModeV6InV6() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET, AF_INET6, false, true);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTransportInTunnelModeV4InV4UdpEncap() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET, AF_INET, true, true);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTransportInTunnelModeV6InV4UdpEncap() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET6, AF_INET, true, true);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTransportInTunnelModeV4InV6UdpEncap() throws Exception {
+ assumeExperimentalIpv6UdpEncapSupported();
+ doTestMigrateTunnelModeTransform(AF_INET, AF_INET6, true, true);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTransportInTunnelModeV6InV6UdpEncap() throws Exception {
+ assumeExperimentalIpv6UdpEncapSupported();
+ doTestMigrateTunnelModeTransform(AF_INET6, AF_INET6, true, true);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTunnelV4InV4() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET, AF_INET, false, false);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTunnelV6InV4() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET6, AF_INET, false, false);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTunnelV4InV6() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET, AF_INET6, false, false);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTunnelV6InV6() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET6, AF_INET6, false, false);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTunnelV4InV4UdpEncap() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET, AF_INET, true, false);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTunnelV6InV4UdpEncap() throws Exception {
+ doTestMigrateTunnelModeTransform(AF_INET6, AF_INET, true, false);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTunnelV4InV6UdpEncap() throws Exception {
+ assumeExperimentalIpv6UdpEncapSupported();
+ doTestMigrateTunnelModeTransform(AF_INET, AF_INET6, true, false);
+ }
+
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ public void testMigrateTransformTunnelV6InV6UdpEncap() throws Exception {
+ assumeExperimentalIpv6UdpEncapSupported();
+ doTestMigrateTunnelModeTransform(AF_INET6, AF_INET6, true, false);
+ }
}
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 6df71c8..b535a8f 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -191,6 +191,7 @@
callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) }
qosTestSocket?.close()
mHandlerThread.quitSafely()
+ mHandlerThread.join()
instrumentation.getUiAutomation().dropShellPermissionIdentity()
}
@@ -391,9 +392,7 @@
val nc = NetworkCapabilities(agent.nc)
nc.addCapability(NET_CAPABILITY_NOT_METERED)
agent.sendNetworkCapabilities(nc)
- callback.expectCapabilitiesThat(agent.network) {
- it.hasCapability(NET_CAPABILITY_NOT_METERED)
- }
+ callback.expectCaps(agent.network) { it.hasCapability(NET_CAPABILITY_NOT_METERED) }
val networkInfo = mCM.getNetworkInfo(agent.network)
assertEquals(subtypeUMTS, networkInfo.getSubtype())
assertEquals(subtypeNameUMTS, networkInfo.getSubtypeName())
@@ -434,27 +433,28 @@
(agent, callback) ->
// Send signal strength and check that the callbacks are called appropriately.
val nc = NetworkCapabilities(agent.nc)
+ val net = agent.network!!
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[0].expectAvailableCallbacks(net)
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!!)
+ callbacks[0].expectCaps(net) { it.signalStrength == 80 }
+ callbacks[1].expectAvailableCallbacks(net)
+ callbacks[2].expectAvailableCallbacks(net)
nc.setSignalStrength(55)
agent.sendNetworkCapabilities(nc)
- callbacks[0].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 }
- callbacks[1].expectCapabilitiesThat(agent.network!!) { it.signalStrength == 55 }
- callbacks[2].expect<Lost>(agent.network!!)
+ callbacks[0].expectCaps(net) { it.signalStrength == 55 }
+ callbacks[1].expectCaps(net) { it.signalStrength == 55 }
+ callbacks[2].expect<Lost>(net)
}
callbacks.forEach {
mCM.unregisterNetworkCallback(it)
@@ -507,15 +507,11 @@
val lp = LinkProperties(agent.lp)
lp.setInterfaceName(ifaceName)
agent.sendLinkProperties(lp)
- callback.expectLinkPropertiesThat(agent.network!!) {
- it.getInterfaceName() == ifaceName
- }
+ callback.expect<LinkPropertiesChanged>(agent.network!!) { it.lp.interfaceName == ifaceName }
val nc = NetworkCapabilities(agent.nc)
nc.addCapability(NET_CAPABILITY_NOT_METERED)
agent.sendNetworkCapabilities(nc)
- callback.expectCapabilitiesThat(agent.network!!) {
- it.hasCapability(NET_CAPABILITY_NOT_METERED)
- }
+ callback.expectCaps(agent.network!!) { it.hasCapability(NET_CAPABILITY_NOT_METERED) }
}
private fun ncWithAllowedUids(vararg uids: Int) = NetworkCapabilities.Builder()
@@ -533,12 +529,12 @@
// Make sure the UIDs have been ignored.
callback.expect<Available>(agent.network!!)
- callback.expectCapabilitiesThat(agent.network!!) {
+ callback.expectCaps(agent.network!!) {
it.allowedUids.isEmpty() && !it.hasCapability(NET_CAPABILITY_VALIDATED)
}
callback.expect<LinkPropertiesChanged>(agent.network!!)
callback.expect<BlockedStatus>(agent.network!!)
- callback.expectCapabilitiesThat(agent.network!!) {
+ callback.expectCaps(agent.network!!) {
it.allowedUids.isEmpty() && it.hasCapability(NET_CAPABILITY_VALIDATED)
}
callback.assertNoCallback(NO_CALLBACK_TIMEOUT)
@@ -582,8 +578,8 @@
// tearDown() will unregister the requests and agents
}
- private fun hasAllTransports(nc: NetworkCapabilities?, transports: IntArray) =
- nc != null && transports.all { nc.hasTransport(it) }
+ private fun NetworkCapabilities?.hasAllTransports(transports: IntArray) =
+ this != null && transports.all { hasTransport(it) }
@Test
@IgnoreUpTo(Build.VERSION_CODES.R)
@@ -625,25 +621,25 @@
assertEquals(mySessionId, (vpnNc.transportInfo as VpnTransportInfo).sessionId)
val testAndVpn = intArrayOf(TRANSPORT_TEST, TRANSPORT_VPN)
- assertTrue(hasAllTransports(vpnNc, testAndVpn))
+ assertTrue(vpnNc.hasAllTransports(testAndVpn))
assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_VPN))
- assertTrue(hasAllTransports(vpnNc, defaultNetworkTransports),
+ assertTrue(vpnNc.hasAllTransports(defaultNetworkTransports),
"VPN transports ${Arrays.toString(vpnNc.transportTypes)}" +
" lacking transports from ${Arrays.toString(defaultNetworkTransports)}")
// Check that when no underlying networks are announced the underlying transport disappears.
agent.setUnderlyingNetworks(listOf<Network>())
- callback.expectCapabilitiesThat(agent.network!!) {
- it.transportTypes.size == 2 && hasAllTransports(it, testAndVpn)
+ callback.expectCaps(agent.network!!) {
+ it.transportTypes.size == 2 && it.hasAllTransports(testAndVpn)
}
// Put the underlying network back and check that the underlying transport reappears.
val expectedTransports = (defaultNetworkTransports.toSet() + TRANSPORT_TEST + TRANSPORT_VPN)
.toIntArray()
agent.setUnderlyingNetworks(null)
- callback.expectCapabilitiesThat(agent.network!!) {
+ callback.expectCaps(agent.network!!) {
it.transportTypes.size == expectedTransports.size &&
- hasAllTransports(it, expectedTransports)
+ it.hasAllTransports(expectedTransports)
}
// Check that some underlying capabilities are propagated.
@@ -757,7 +753,7 @@
val nc1 = NetworkCapabilities(agent.nc)
.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
agent.sendNetworkCapabilities(nc1)
- callback.expectCapabilitiesThat(agent.network!!) {
+ callback.expectCaps(agent.network!!) {
it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
}
@@ -765,7 +761,7 @@
val nc2 = NetworkCapabilities(agent.nc)
.removeCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
agent.sendNetworkCapabilities(nc2)
- callback.expectCapabilitiesThat(agent.network!!) {
+ callback.expectCaps(agent.network!!) {
!it.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
}
@@ -917,12 +913,10 @@
val history = ArrayTrackRecord<CallbackEntry>().newReadHead()
sealed class CallbackEntry {
- data class OnQosSessionAvailable(val sess: QosSession, val attr: QosSessionAttributes)
- : CallbackEntry()
- data class OnQosSessionLost(val sess: QosSession)
- : CallbackEntry()
- data class OnError(val ex: QosCallbackException)
- : CallbackEntry()
+ data class OnQosSessionAvailable(val sess: QosSession, val attr: QosSessionAttributes) :
+ CallbackEntry()
+ data class OnQosSessionLost(val sess: QosSession) : CallbackEntry()
+ data class OnError(val ex: QosCallbackException) : CallbackEntry()
}
override fun onQosSessionAvailable(sess: QosSession, attr: QosSessionAttributes) {
@@ -1330,14 +1324,10 @@
val (wifiAgent, wifiNetwork) = connectNetwork(TRANSPORT_WIFI)
testCallback.expectAvailableCallbacks(wifiNetwork, validated = true)
- testCallback.expectCapabilitiesThat(wifiNetwork) {
- it.hasCapability(NET_CAPABILITY_VALIDATED)
- }
+ testCallback.expectCaps(wifiNetwork) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
matchAllCallback.expectAvailableCallbacks(wifiNetwork, validated = false)
matchAllCallback.expect<Losing>(cellNetwork)
- matchAllCallback.expectCapabilitiesThat(wifiNetwork) {
- it.hasCapability(NET_CAPABILITY_VALIDATED)
- }
+ matchAllCallback.expectCaps(wifiNetwork) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
wifiAgent.unregisterAfterReplacement(5_000 /* timeoutMillis */)
wifiAgent.expectCallback<OnNetworkDestroyed>()
diff --git a/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt b/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt
index eb41d71..fcfecad 100644
--- a/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt
@@ -90,6 +90,7 @@
mCm.unregisterNetworkCallback(agentCleanUpCb)
mHandlerThread.quitSafely()
+ mHandlerThread.join()
callbacksToCleanUp.forEach { mCm.unregisterNetworkCallback(it) }
}
diff --git a/tests/cts/net/src/android/net/cts/NetworkValidationTest.kt b/tests/cts/net/src/android/net/cts/NetworkValidationTest.kt
index 8e98dba..621af23 100644
--- a/tests/cts/net/src/android/net/cts/NetworkValidationTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkValidationTest.kt
@@ -146,6 +146,7 @@
httpServer.stop()
handlerThread.threadHandler.post { reader.stop() }
handlerThread.quitSafely()
+ handlerThread.join()
iface.fileDescriptor.close()
}
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index b7eb009..db7f38c 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -19,17 +19,23 @@
import android.app.compat.CompatChanges
import android.net.ConnectivityManager
import android.net.ConnectivityManager.NetworkCallback
+import android.net.InetAddresses.parseNumericAddress
+import android.net.LinkAddress
import android.net.LinkProperties
+import android.net.LocalSocket
+import android.net.LocalSocketAddress
import android.net.Network
import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED
import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
+import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_TEST
import android.net.NetworkRequest
import android.net.TestNetworkInterface
import android.net.TestNetworkManager
import android.net.TestNetworkSpecifier
+import android.net.connectivity.ConnectivityCompatChanges
import android.net.cts.NsdManagerTest.NsdDiscoveryRecord.DiscoveryEvent.DiscoveryStarted
import android.net.cts.NsdManagerTest.NsdDiscoveryRecord.DiscoveryEvent.DiscoveryStopped
import android.net.cts.NsdManagerTest.NsdDiscoveryRecord.DiscoveryEvent.ServiceFound
@@ -40,10 +46,15 @@
import android.net.cts.NsdManagerTest.NsdRegistrationRecord.RegistrationEvent.ServiceRegistered
import android.net.cts.NsdManagerTest.NsdRegistrationRecord.RegistrationEvent.ServiceUnregistered
import android.net.cts.NsdManagerTest.NsdRegistrationRecord.RegistrationEvent.UnregistrationFailed
+import android.net.cts.NsdManagerTest.NsdResolveRecord.ResolveEvent.ResolutionStopped
import android.net.cts.NsdManagerTest.NsdResolveRecord.ResolveEvent.ResolveFailed
-import android.net.cts.NsdManagerTest.NsdResolveRecord.ResolveEvent.ResolveStopped
import android.net.cts.NsdManagerTest.NsdResolveRecord.ResolveEvent.ServiceResolved
import android.net.cts.NsdManagerTest.NsdResolveRecord.ResolveEvent.StopResolutionFailed
+import android.net.cts.NsdManagerTest.NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent.RegisterCallbackFailed
+import android.net.cts.NsdManagerTest.NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent.ServiceUpdated
+import android.net.cts.NsdManagerTest.NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent.ServiceUpdatedLost
+import android.net.cts.NsdManagerTest.NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent.UnregisterCallbackSucceeded
+import android.net.cts.util.CtsNetUtils
import android.net.nsd.NsdManager
import android.net.nsd.NsdManager.DiscoveryListener
import android.net.nsd.NsdManager.RegistrationListener
@@ -54,25 +65,45 @@
import android.os.HandlerThread
import android.os.Process.myTid
import android.platform.test.annotations.AppModeFull
+import android.system.ErrnoException
+import android.system.Os
+import android.system.OsConstants.AF_INET6
+import android.system.OsConstants.EADDRNOTAVAIL
+import android.system.OsConstants.ENETUNREACH
+import android.system.OsConstants.IPPROTO_UDP
+import android.system.OsConstants.SOCK_DGRAM
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
+import com.android.compatibility.common.util.PollingCheck
+import com.android.compatibility.common.util.PropertyUtil
+import com.android.modules.utils.build.SdkLevel.isAtLeastU
import com.android.net.module.util.ArrayTrackRecord
import com.android.net.module.util.TrackRecord
import com.android.networkstack.apishim.NsdShimImpl
+import com.android.networkstack.apishim.common.NsdShim
import com.android.testutils.ConnectivityModuleTest
import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
+import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
import com.android.testutils.TestableNetworkAgent
+import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk30
+import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk33
import com.android.testutils.runAsShell
import com.android.testutils.tryTest
import com.android.testutils.waitForIdle
import java.io.File
+import java.io.IOException
+import java.net.Inet6Address
+import java.net.InetAddress
+import java.net.NetworkInterface
import java.net.ServerSocket
import java.nio.charset.StandardCharsets
import java.util.Random
import java.util.concurrent.Executor
+import kotlin.math.min
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertNotNull
@@ -103,6 +134,7 @@
@AppModeFull(reason = "Socket cannot bind in instant app mode")
@RunWith(AndroidJUnit4::class)
+@ConnectivityModuleTest
class NsdManagerTest {
// Rule used to filter CtsNetTestCasesMaxTargetSdkXX
@get:Rule
@@ -115,6 +147,7 @@
private val serviceName = "NsdTest%09d".format(Random().nextInt(1_000_000_000))
private val serviceType = "_nmt%09d._tcp".format(Random().nextInt(1_000_000_000))
private val handlerThread = HandlerThread(NsdManagerTest::class.java.simpleName)
+ private val ctsNetUtils by lazy{ CtsNetUtils(context) }
private lateinit var testNetwork1: TestTapNetwork
private lateinit var testNetwork2: TestTapNetwork
@@ -157,7 +190,8 @@
inline fun <reified V : NsdEvent> expectCallback(timeoutMs: Long = TIMEOUT_MS): V {
val nextEvent = nextEvents.poll(timeoutMs)
- assertNotNull(nextEvent, "No callback received after $timeoutMs ms")
+ assertNotNull(nextEvent, "No callback received after $timeoutMs ms, expected " +
+ "${V::class.java.simpleName}")
assertTrue(nextEvent is V, "Expected ${V::class.java.simpleName} but got " +
nextEvent.javaClass.simpleName)
return nextEvent
@@ -265,7 +299,7 @@
ResolveEvent()
data class ServiceResolved(val serviceInfo: NsdServiceInfo) : ResolveEvent()
- data class ResolveStopped(val serviceInfo: NsdServiceInfo) : ResolveEvent()
+ data class ResolutionStopped(val serviceInfo: NsdServiceInfo) : ResolveEvent()
data class StopResolutionFailed(val serviceInfo: NsdServiceInfo, val errorCode: Int) :
ResolveEvent()
}
@@ -278,15 +312,42 @@
add(ServiceResolved(si))
}
- override fun onResolveStopped(si: NsdServiceInfo) {
- add(ResolveStopped(si))
+ override fun onResolutionStopped(si: NsdServiceInfo) {
+ add(ResolutionStopped(si))
}
override fun onStopResolutionFailed(si: NsdServiceInfo, err: Int) {
+ super.onStopResolutionFailed(si, err)
add(StopResolutionFailed(si, err))
}
}
+ private class NsdServiceInfoCallbackRecord : NsdShim.ServiceInfoCallbackShim,
+ NsdRecord<NsdServiceInfoCallbackRecord.ServiceInfoCallbackEvent>() {
+ sealed class ServiceInfoCallbackEvent : NsdEvent {
+ data class RegisterCallbackFailed(val errorCode: Int) : ServiceInfoCallbackEvent()
+ data class ServiceUpdated(val serviceInfo: NsdServiceInfo) : ServiceInfoCallbackEvent()
+ object ServiceUpdatedLost : ServiceInfoCallbackEvent()
+ object UnregisterCallbackSucceeded : ServiceInfoCallbackEvent()
+ }
+
+ override fun onServiceInfoCallbackRegistrationFailed(err: Int) {
+ add(RegisterCallbackFailed(err))
+ }
+
+ override fun onServiceUpdated(si: NsdServiceInfo) {
+ add(ServiceUpdated(si))
+ }
+
+ override fun onServiceLost() {
+ add(ServiceUpdatedLost)
+ }
+
+ override fun onServiceInfoCallbackUnregistered() {
+ add(UnregisterCallbackSucceeded)
+ }
+ }
+
@Before
fun setUp() {
handlerThread.start()
@@ -311,24 +372,63 @@
.build(), cb)
val agent = registerTestNetworkAgent(iface.interfaceName)
val network = agent.network ?: fail("Registered agent should have a network")
+
+ cb.eventuallyExpect<LinkPropertiesChanged>(TIMEOUT_MS) {
+ it.lp.linkAddresses.isNotEmpty()
+ }
+
// The network has no INTERNET capability, so will be marked validated immediately
- cb.expectAvailableThenValidatedCallbacks(network, TIMEOUT_MS)
+ // It does not matter if validated capabilities come before/after the link addresses change
+ cb.eventuallyExpect<CapabilitiesChanged>(TIMEOUT_MS, from = 0) {
+ it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
+ }
return TestTapNetwork(iface, cb, agent, network)
}
private fun registerTestNetworkAgent(ifaceName: String): TestableNetworkAgent {
+ val lp = LinkProperties().apply {
+ interfaceName = ifaceName
+ }
+
val agent = TestableNetworkAgent(context, handlerThread.looper,
NetworkCapabilities().apply {
removeCapability(NET_CAPABILITY_TRUSTED)
addTransportType(TRANSPORT_TEST)
setNetworkSpecifier(TestNetworkSpecifier(ifaceName))
- },
- LinkProperties().apply {
- interfaceName = ifaceName
- },
- NetworkAgentConfig.Builder().build())
- agent.register()
+ }, lp, NetworkAgentConfig.Builder().build())
+ val network = agent.register()
agent.markConnected()
+ agent.expectCallback<OnNetworkCreated>()
+
+ // Wait until the link-local address can be used. Address flags are not available without
+ // elevated permissions, so check that bindSocket works.
+ PollingCheck.check("No usable v6 address on interface after $TIMEOUT_MS ms", TIMEOUT_MS) {
+ // To avoid race condition between socket connection succeeding and interface returning
+ // a non-empty address list. Verify that interface returns a non-empty list, before
+ // trying the socket connection.
+ if (NetworkInterface.getByName(ifaceName).interfaceAddresses.isEmpty()) {
+ return@check false
+ }
+
+ val sock = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
+ tryTest {
+ network.bindSocket(sock)
+ Os.connect(sock, parseNumericAddress("ff02::fb%$ifaceName"), 12345)
+ true
+ }.catch<ErrnoException> {
+ if (it.errno != ENETUNREACH && it.errno != EADDRNOTAVAIL) {
+ throw it
+ }
+ false
+ } cleanup {
+ Os.close(sock)
+ }
+ }
+
+ lp.setLinkAddresses(NetworkInterface.getByName(ifaceName).interfaceAddresses.map {
+ LinkAddress(it.address, it.networkPrefixLength.toInt())
+ })
+ agent.sendLinkProperties(lp)
return agent
}
@@ -336,12 +436,14 @@
fun tearDown() {
if (TestUtils.shouldTestTApis()) {
runAsShell(MANAGE_TEST_NETWORKS) {
- testNetwork1.close(cm)
- testNetwork2.close(cm)
+ // Avoid throwing here if initializing failed in setUp
+ if (this::testNetwork1.isInitialized) testNetwork1.close(cm)
+ if (this::testNetwork2.isInitialized) testNetwork2.close(cm)
}
}
handlerThread.waitForIdle(TIMEOUT_MS)
handlerThread.quitSafely()
+ handlerThread.join()
}
@Test
@@ -423,7 +525,12 @@
assertTrue(resolvedService.attributes.containsKey("nullBinaryDataAttr"))
assertNull(resolvedService.attributes["nullBinaryDataAttr"])
assertTrue(resolvedService.attributes.containsKey("emptyBinaryDataAttr"))
- assertNull(resolvedService.attributes["emptyBinaryDataAttr"])
+ // TODO: change the check to target SDK U when this is what the code implements
+ if (isAtLeastU()) {
+ assertArrayEquals(byteArrayOf(), resolvedService.attributes["emptyBinaryDataAttr"])
+ } else {
+ assertNull(resolvedService.attributes["emptyBinaryDataAttr"])
+ }
assertEquals(localPort, resolvedService.port)
// Unregister the service
@@ -600,6 +707,20 @@
}
}
+ private fun checkAddressScopeId(iface: TestNetworkInterface, address: List<InetAddress>) {
+ val targetSdkVersion = context.packageManager
+ .getTargetSdkVersion(context.applicationInfo.packageName)
+ if (targetSdkVersion <= Build.VERSION_CODES.TIRAMISU) {
+ return
+ }
+ val ifaceIdx = NetworkInterface.getByName(iface.interfaceName).index
+ address.forEach {
+ if (it is Inet6Address && it.isLinkLocalAddress) {
+ assertEquals(ifaceIdx, it.scopeId)
+ }
+ }
+ }
+
@Test
fun testNsdManager_ResolveOnNetwork() {
// This test requires shims supporting T+ APIs (NsdServiceInfo.network)
@@ -635,6 +756,7 @@
assertEquals(registeredInfo.serviceName, it.serviceName)
assertEquals(si.port, it.port)
assertEquals(testNetwork1.network, nsdShim.getNetwork(it))
+ checkAddressScopeId(testNetwork1.iface, it.hostAddresses)
}
// TODO: check that MDNS packets are sent only on testNetwork1.
} cleanupStep {
@@ -728,6 +850,69 @@
}
}
+ private fun checkConnectSocketToMdnsd(shouldFail: Boolean) {
+ val discoveryRecord = NsdDiscoveryRecord()
+ val localSocket = LocalSocket()
+ tryTest {
+ // Discover any service from NsdManager to enforce NsdService to start the mdnsd.
+ nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, discoveryRecord)
+ discoveryRecord.expectCallback<DiscoveryStarted>()
+
+ // Checks the /dev/socket/mdnsd is created.
+ val socket = File("/dev/socket/mdnsd")
+ val doesSocketExist = PollingCheck.waitFor(
+ TIMEOUT_MS,
+ {
+ socket.exists()
+ },
+ { doesSocketExist ->
+ doesSocketExist
+ },
+ )
+
+ // If the socket is not created, then no need to check the access.
+ if (doesSocketExist) {
+ // Create a LocalSocket and try to connect to mdnsd.
+ assertFalse("LocalSocket is connected.", localSocket.isConnected)
+ val address = LocalSocketAddress("mdnsd", LocalSocketAddress.Namespace.RESERVED)
+ if (shouldFail) {
+ assertFailsWith<IOException>("Expect fail but socket connected") {
+ localSocket.connect(address)
+ }
+ } else {
+ localSocket.connect(address)
+ assertTrue("LocalSocket is not connected.", localSocket.isConnected)
+ }
+ }
+ } cleanup {
+ localSocket.close()
+ nsdManager.stopServiceDiscovery(discoveryRecord)
+ discoveryRecord.expectCallback<DiscoveryStopped>()
+ }
+ }
+
+ /**
+ * Starting from Android U, the access to the /dev/socket/mdnsd is blocked by the
+ * sepolicy(b/265364111).
+ */
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ fun testCannotConnectSocketToMdnsd() {
+ val targetSdkVersion = context.packageManager
+ .getTargetSdkVersion(context.applicationInfo.packageName)
+ assumeTrue(targetSdkVersion > Build.VERSION_CODES.TIRAMISU)
+ val firstApiLevel = min(PropertyUtil.getFirstApiLevel(), PropertyUtil.getVendorApiLevel())
+ // The sepolicy is implemented in the vendor image, so the access may not be blocked if
+ // the vendor image is not update to date.
+ assumeTrue(firstApiLevel > Build.VERSION_CODES.TIRAMISU)
+ checkConnectSocketToMdnsd(shouldFail = true)
+ }
+
+ @Test @CtsNetTestCasesMaxTargetSdk33("mdnsd socket is accessible up to target SDK 33")
+ fun testCanConnectSocketToMdnsd() {
+ checkConnectSocketToMdnsd(shouldFail = false)
+ }
+
@Test @CtsNetTestCasesMaxTargetSdk30("Socket is started with the service up to target SDK 30")
fun testManagerCreatesLegacySocket() {
nsdManager // Ensure the lazy-init member is initialized, so NsdManager is created
@@ -749,7 +934,7 @@
// when the compat change is disabled.
// Note that before T the compat constant had a different int value.
assertFalse(CompatChanges.isChangeEnabled(
- NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER))
+ ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER))
}
@Test
@@ -764,14 +949,87 @@
val resolveRecord = NsdResolveRecord()
// Try to resolve an unknown service then stop it immediately.
- // Expected ResolveStopped callback.
+ // Expected ResolutionStopped callback.
nsdShim.resolveService(nsdManager, si, { it.run() }, resolveRecord)
nsdShim.stopServiceResolution(nsdManager, resolveRecord)
- val stoppedCb = resolveRecord.expectCallback<ResolveStopped>()
+ val stoppedCb = resolveRecord.expectCallback<ResolutionStopped>()
assertEquals(si.serviceName, stoppedCb.serviceInfo.serviceName)
assertEquals(si.serviceType, stoppedCb.serviceInfo.serviceType)
}
+ @Test
+ fun testRegisterServiceInfoCallback() {
+ // This test requires shims supporting U+ APIs (NsdManager.registerServiceInfoCallback)
+ assumeTrue(TestUtils.shouldTestUApis())
+
+ val lp = cm.getLinkProperties(testNetwork1.network)
+ assertNotNull(lp)
+ val addresses = lp.addresses
+ assertFalse(addresses.isEmpty())
+
+ val si = NsdServiceInfo().apply {
+ serviceType = this@NsdManagerTest.serviceType
+ serviceName = this@NsdManagerTest.serviceName
+ network = testNetwork1.network
+ port = 12345 // Test won't try to connect so port does not matter
+ }
+
+ // Register service on the network
+ val registrationRecord = NsdRegistrationRecord()
+ registerService(registrationRecord, si)
+
+ val discoveryRecord = NsdDiscoveryRecord()
+ val cbRecord = NsdServiceInfoCallbackRecord()
+ tryTest {
+ // Discover service on the network.
+ nsdShim.discoverServices(nsdManager, serviceType, NsdManager.PROTOCOL_DNS_SD,
+ testNetwork1.network, Executor { it.run() }, discoveryRecord)
+ val foundInfo = discoveryRecord.waitForServiceDiscovered(
+ serviceName, testNetwork1.network)
+
+ // Register service callback and check the addresses are the same as network addresses
+ nsdShim.registerServiceInfoCallback(nsdManager, foundInfo, { it.run() }, cbRecord)
+ val serviceInfoCb = cbRecord.expectCallback<ServiceUpdated>()
+ assertEquals(foundInfo.serviceName, serviceInfoCb.serviceInfo.serviceName)
+ val hostAddresses = serviceInfoCb.serviceInfo.hostAddresses
+ assertEquals(addresses.size, hostAddresses.size)
+ for (hostAddress in hostAddresses) {
+ assertTrue(addresses.contains(hostAddress))
+ }
+ checkAddressScopeId(testNetwork1.iface, serviceInfoCb.serviceInfo.hostAddresses)
+ } cleanupStep {
+ nsdManager.unregisterService(registrationRecord)
+ registrationRecord.expectCallback<ServiceUnregistered>()
+ discoveryRecord.expectCallback<ServiceLost>()
+ cbRecord.expectCallback<ServiceUpdatedLost>()
+ } cleanupStep {
+ // Cancel subscription and check stop callback received.
+ nsdShim.unregisterServiceInfoCallback(nsdManager, cbRecord)
+ cbRecord.expectCallback<UnregisterCallbackSucceeded>()
+ } cleanup {
+ nsdManager.stopServiceDiscovery(discoveryRecord)
+ discoveryRecord.expectCallback<DiscoveryStopped>()
+ }
+ }
+
+ @Test
+ fun testStopServiceResolutionFailedCallback() {
+ // This test requires shims supporting U+ APIs (NsdManager.stopServiceResolution)
+ assumeTrue(TestUtils.shouldTestUApis())
+
+ // It's not possible to make ResolutionListener#onStopResolutionFailed callback sending
+ // because it is only sent in very edge-case scenarios when the legacy implementation is
+ // used, and the legacy implementation is never used in the current AOSP builds. Considering
+ // that this callback isn't expected to be sent at all at the moment, and this is just an
+ // interface with no implementation. To verify this callback, just call
+ // onStopResolutionFailed on the record directly then verify it is received.
+ val resolveRecord = NsdResolveRecord()
+ resolveRecord.onStopResolutionFailed(
+ NsdServiceInfo(), NsdManager.FAILURE_OPERATION_NOT_RUNNING)
+ val failedCb = resolveRecord.expectCallback<StopResolutionFailed>()
+ assertEquals(NsdManager.FAILURE_OPERATION_NOT_RUNNING, failedCb.errorCode)
+ }
+
/**
* Register a service and return its registration record.
*/
diff --git a/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java b/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
index cbe54f8..1a780a7 100644
--- a/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
+++ b/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
@@ -66,7 +66,6 @@
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);
@@ -76,10 +75,11 @@
.map(addr -> new InetSocketAddress(addr, HTTPS_PORT))
.collect(Collectors.toList());
- // Find the local IP address which will be used to connect to TEST_HOST.
+ // Find the local and remote IP addresses which will be used to connect to TEST_HOST.
try {
Socket testSocket = new Socket(TEST_HOST, HTTPS_PORT);
mLocalAddress = testSocket.getLocalAddress();
+ mTestHostAddress = testSocket.getInetAddress();
testSocket.close();
} catch (IOException ioe) {
throw new AssertionError(""
diff --git a/tests/cts/net/src/android/net/cts/TunUtils.java b/tests/cts/net/src/android/net/cts/TunUtils.java
index 0377160..268d8d2 100644
--- a/tests/cts/net/src/android/net/cts/TunUtils.java
+++ b/tests/cts/net/src/android/net/cts/TunUtils.java
@@ -22,7 +22,6 @@
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;
@@ -32,6 +31,7 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -140,10 +140,8 @@
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);
+ (pkt) -> expectedPacketSize == pkt.length
+ && isEspFailIfSpecifiedPlaintextFound(pkt, spi, useEncap, plaintext));
return espPkt; // We've found the packet we're looking for.
}
@@ -153,11 +151,11 @@
}
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);
+ ByteBuffer buffer = ByteBuffer.wrap(pkt);
+ buffer.get(new byte[espOffset]); // Skip IP, UDP header
+ int actualSpi = buffer.getInt();
+
+ return actualSpi == spi;
}
/**
@@ -180,8 +178,13 @@
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);
+ if (encap) {
+ return pkt[IP6_PROTO_OFFSET] == IPPROTO_UDP
+ && isSpiEqual(pkt, IP6_HDRLEN + UDP_HDRLEN, spi);
+ } else {
+ return pkt[IP6_PROTO_OFFSET] == IPPROTO_ESP && isSpiEqual(pkt, IP6_HDRLEN, spi);
+ }
+
} else {
// Use default IPv4 header length (assuming no options)
if (encap) {
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
index df3a4aa..d817630 100644
--- a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
+++ b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
@@ -75,6 +75,13 @@
public final class CtsNetUtils {
private static final String TAG = CtsNetUtils.class.getSimpleName();
+
+ // Redefine this flag here so that IPsec code shipped in a mainline module can build on old
+ // platforms before FEATURE_IPSEC_TUNNEL_MIGRATION API is released.
+ // TODO: b/275378783 Remove this flag and use the platform API when it is available.
+ private static final String FEATURE_IPSEC_TUNNEL_MIGRATION =
+ "android.software.ipsec_tunnel_migration";
+
private static final int SOCKET_TIMEOUT_MS = 2000;
private static final int PRIVATE_DNS_PROBE_MS = 1_000;
@@ -115,6 +122,11 @@
|| getFirstApiLevel() >= Build.VERSION_CODES.Q;
}
+ /** Checks if FEATURE_IPSEC_TUNNEL_MIGRATION is enabled on the device */
+ public boolean hasIpsecTunnelMigrateFeature() {
+ return mContext.getPackageManager().hasSystemFeature(FEATURE_IPSEC_TUNNEL_MIGRATION);
+ }
+
/**
* Sets the given appop using shell commands
*
diff --git a/tests/cts/net/util/java/android/net/cts/util/IkeSessionTestUtils.java b/tests/cts/net/util/java/android/net/cts/util/IkeSessionTestUtils.java
index 11eb466..25534b8 100644
--- a/tests/cts/net/util/java/android/net/cts/util/IkeSessionTestUtils.java
+++ b/tests/cts/net/util/java/android/net/cts/util/IkeSessionTestUtils.java
@@ -42,8 +42,9 @@
public class IkeSessionTestUtils {
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";
+ public static final String TEST_IDENTITY = "client.cts.android.com";
private static final byte[] TEST_PSK = "ikeAndroidPsk".getBytes();
+ public static final int TEST_KEEPALIVE_TIMEOUT_UNSET = -1;
public static final IkeSessionParams IKE_PARAMS_V4 = getTestIkeSessionParams(false);
public static final IkeSessionParams IKE_PARAMS_V6 = getTestIkeSessionParams(true);
@@ -63,17 +64,26 @@
public static IkeSessionParams getTestIkeSessionParams(boolean testIpv6,
IkeIdentification identification) {
+ return getTestIkeSessionParams(testIpv6, identification, TEST_KEEPALIVE_TIMEOUT_UNSET);
+ }
+
+ public static IkeSessionParams getTestIkeSessionParams(boolean testIpv6,
+ IkeIdentification identification, int keepaliveTimer) {
final String testServer = testIpv6 ? TEST_SERVER_ADDR_V6 : TEST_SERVER_ADDR_V4;
final InetAddress addr = InetAddresses.parseNumericAddress(testServer);
final IkeSessionParams.Builder ikeOptionsBuilder =
new IkeSessionParams.Builder()
.setServerHostname(testServer)
- .setLocalIdentification(new IkeFqdnIdentification(TEST_IDENTITY))
+ .setLocalIdentification(identification)
.setRemoteIdentification(testIpv6
? new IkeIpv6AddrIdentification((Inet6Address) addr)
: new IkeIpv4AddrIdentification((Inet4Address) addr))
.setAuthPsk(TEST_PSK)
+
.addSaProposal(getIkeSaProposals());
+ if (keepaliveTimer != TEST_KEEPALIVE_TIMEOUT_UNSET) {
+ ikeOptionsBuilder.setNattKeepAliveDelaySeconds(keepaliveTimer);
+ }
return ikeOptionsBuilder.build();
}
diff --git a/tests/cts/netpermission/internetpermission/AndroidManifest.xml b/tests/cts/netpermission/internetpermission/AndroidManifest.xml
index 45ef5bd..ae7de3f 100644
--- a/tests/cts/netpermission/internetpermission/AndroidManifest.xml
+++ b/tests/cts/netpermission/internetpermission/AndroidManifest.xml
@@ -43,8 +43,6 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.networkpermission.internetpermission.cts"
android:label="CTS tests for INTERNET permissions">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener"/>
</instrumentation>
</manifest>
diff --git a/tests/cts/netpermission/updatestatspermission/AndroidManifest.xml b/tests/cts/netpermission/updatestatspermission/AndroidManifest.xml
index 6babe8f..8a7e3f7 100644
--- a/tests/cts/netpermission/updatestatspermission/AndroidManifest.xml
+++ b/tests/cts/netpermission/updatestatspermission/AndroidManifest.xml
@@ -51,8 +51,6 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.networkpermission.updatestatspermission.cts"
android:label="CTS tests for UPDATE_DEVICE_STATS permissions">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener"/>
</instrumentation>
</manifest>
diff --git a/tests/cts/tethering/Android.bp b/tests/cts/tethering/Android.bp
index 42949a4..4284f56 100644
--- a/tests/cts/tethering/Android.bp
+++ b/tests/cts/tethering/Android.bp
@@ -46,6 +46,7 @@
// Change to system current when TetheringManager move to bootclass path.
platform_apis: true,
+ host_required: ["net-tests-utils-host-common"],
}
// Tethering CTS tests that target the latest released SDK. These tests can be installed on release
diff --git a/tests/cts/tethering/AndroidManifest.xml b/tests/cts/tethering/AndroidManifest.xml
index 911dbf2..bad722b 100644
--- a/tests/cts/tethering/AndroidManifest.xml
+++ b/tests/cts/tethering/AndroidManifest.xml
@@ -27,8 +27,6 @@
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.tethering.cts"
android:label="CTS tests of android.tethering">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>
diff --git a/tests/cts/tethering/AndroidTestTemplate.xml b/tests/cts/tethering/AndroidTestTemplate.xml
index 491b004..c842c09 100644
--- a/tests/cts/tethering/AndroidTestTemplate.xml
+++ b/tests/cts/tethering/AndroidTestTemplate.xml
@@ -25,6 +25,8 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="{MODULE}.apk" />
</target_preparer>
+ <target_preparer class="com.android.testutils.ConnectivityCheckTargetPreparer">
+ </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.tethering.cts" />
</test>
diff --git a/tests/integration/Android.bp b/tests/integration/Android.bp
index e3d80a0..12919ae 100644
--- a/tests/integration/Android.bp
+++ b/tests/integration/Android.bp
@@ -21,7 +21,10 @@
android_test {
name: "FrameworksNetIntegrationTests",
- defaults: ["framework-connectivity-internal-test-defaults"],
+ defaults: [
+ "framework-connectivity-internal-test-defaults",
+ "NetworkStackApiShimSettingsForCurrentBranch",
+ ],
platform_apis: true,
certificate: "platform",
srcs: [
@@ -33,6 +36,13 @@
"ServiceConnectivityResources",
],
static_libs: [
+ // It does not matter if NetworkStackApiStableLib or NetworkStackApiCurrentLib is used here,
+ // since the shims for the branch are already included via
+ // NetworkStackApiShimSettingsForCurrentBranch, and will be used in priority as they are
+ // first in the classpath.
+ // If the wrong shims are used for some reason, tests that use newer APIs fail.
+ // TODO: have NetworkStackApiStableLib link dynamically against the shims to remove this
+ // order-dependent setup.
"NetworkStackApiStableLib",
"androidx.test.ext.junit",
"frameworks-net-integration-testutils",
diff --git a/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 26b058d..3c1340d 100644
--- a/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -37,7 +37,6 @@
import android.net.TestNetworkStackClient
import android.net.Uri
import android.net.metrics.IpConnectivityLog
-import com.android.server.connectivity.MultinetworkPolicyTracker
import android.os.ConditionVariable
import android.os.IBinder
import android.os.SystemConfigManager
@@ -52,7 +51,9 @@
import com.android.server.NetworkAgentWrapper
import com.android.server.TestNetIdManager
import com.android.server.connectivity.MockableSystemProperties
+import com.android.server.connectivity.MultinetworkPolicyTracker
import com.android.server.connectivity.ProxyTracker
+import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
import com.android.testutils.TestableNetworkCallback
import org.junit.After
import org.junit.Before
@@ -73,8 +74,6 @@
import org.mockito.MockitoAnnotations
import org.mockito.Spy
import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlin.test.fail
@@ -289,15 +288,16 @@
testCb.expectAvailableCallbacks(na.network, validated = false, tmt = TEST_TIMEOUT_MS)
- val capportData = testCb.expectLinkPropertiesThat(na, TEST_TIMEOUT_MS) {
- it.captivePortalData != null
+ val capportData = testCb.expect<LinkPropertiesChanged>(na, TEST_TIMEOUT_MS) {
+ it.lp.captivePortalData != null
}.lp.captivePortalData
- assertNotNull(capportData)
assertTrue(capportData.isCaptive)
assertEquals(Uri.parse("https://login.capport.android.com"), capportData.userPortalUrl)
assertEquals(Uri.parse("https://venueinfo.capport.android.com"), capportData.venueInfoUrl)
- val nc = testCb.expectCapabilitiesWith(NET_CAPABILITY_CAPTIVE_PORTAL, na, TEST_TIMEOUT_MS)
- assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED))
+ testCb.expectCaps(na, TEST_TIMEOUT_MS) {
+ it.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) &&
+ !it.hasCapability(NET_CAPABILITY_VALIDATED)
+ }
}
-}
\ No newline at end of file
+}
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index e0de246..36b3356 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -69,6 +69,7 @@
"java/com/android/server/VpnManagerServiceTest.java",
"java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java",
"java/com/android/server/connectivity/IpConnectivityMetricsTest.java",
+ "java/com/android/server/connectivity/MetricsTestUtil.java",
"java/com/android/server/connectivity/MultipathPolicyTrackerTest.java",
"java/com/android/server/connectivity/NetdEventListenerServiceTest.java",
"java/com/android/server/connectivity/VpnTest.java",
@@ -114,6 +115,7 @@
"service-connectivity-pre-jarjar",
"service-connectivity-tiramisu-pre-jarjar",
"services.core-vpn",
+ "testables",
"cts-net-utils"
],
libs: [
@@ -135,6 +137,37 @@
visibility: ["//packages/modules/Connectivity/tests:__subpackages__"],
}
+genrule {
+ name: "frameworks-net-tests-jarjar-rules",
+ defaults: ["jarjar-rules-combine-defaults"],
+ srcs: [
+ ":frameworks-net-tests-lib-jarjar-gen",
+ // This is necessary because the tests use framework-connectivity-internal-test-defaults,
+ // which require the user to use connectivity jarjar rules.
+ ":connectivity-jarjar-rules",
+ ],
+ out: ["frameworks-net-tests-jarjar-rules.txt"],
+ visibility: ["//packages/modules/Connectivity/tests:__subpackages__"],
+}
+
+java_genrule {
+ name: "frameworks-net-tests-lib-jarjar-gen",
+ tool_files: [
+ ":FrameworksNetTestsLib{.jar}",
+ "jarjar-excludes.txt",
+ ],
+ tools: [
+ "jarjar-rules-generator",
+ ],
+ out: ["frameworks-net-tests-lib-jarjar-rules.txt"],
+ cmd: "$(location jarjar-rules-generator) " +
+ "$(location :FrameworksNetTestsLib{.jar}) " +
+ "--prefix android.net.connectivity " +
+ "--excludes $(location jarjar-excludes.txt) " +
+ "--output $(out)",
+ visibility: ["//visibility:private"],
+}
+
android_test {
name: "FrameworksNetTests",
enabled: enable_frameworks_net_tests,
@@ -142,7 +175,7 @@
"FrameworksNetTestsDefaults",
"FrameworksNetTests-jni-defaults",
],
- jarjar_rules: ":connectivity-jarjar-rules",
+ jarjar_rules: ":frameworks-net-tests-jarjar-rules",
test_suites: ["device-tests"],
static_libs: [
"services.core",
diff --git a/tests/unit/AndroidManifest.xml b/tests/unit/AndroidManifest.xml
index 5bac2dd..5d4bdf7 100644
--- a/tests/unit/AndroidManifest.xml
+++ b/tests/unit/AndroidManifest.xml
@@ -63,7 +63,7 @@
<uses-library android:name="android.test.runner" />
<uses-library android:name="android.net.ipsec.ike" />
<activity
- android:name="com.android.server.connectivity.NetworkNotificationManagerTest$TestDialogActivity"/>
+ android:name="android.net.connectivity.com.android.server.connectivity.NetworkNotificationManagerTest$TestDialogActivity"/>
</application>
<instrumentation
diff --git a/tests/unit/jarjar-excludes.txt b/tests/unit/jarjar-excludes.txt
new file mode 100644
index 0000000..d2022bf
--- /dev/null
+++ b/tests/unit/jarjar-excludes.txt
@@ -0,0 +1,27 @@
+# Exclude some test prefixes, otherwise the classes reference below can't find
+# them after jarjared.
+android\.compat\..+
+androidx\.test\..+
+com\.android\.frameworks\.tests\..+
+com\.android\.testutils\..+
+com\.android\.dx\.mockito\..+
+com\.android\.internal\.compat\..+
+com\.android\.internal\.org\.bouncycastle\..+
+kotlin\.test\..+
+kotlin\.reflect\..+
+org\.junit\..+
+org\.mockito\..+
+
+# Auto-jarjar-gen can't handle kotlin object expression, exclude the tests which use
+# object expressions.
+#
+# For example: Illegal class access:
+# 'android.net.connectivity.com.android.net.module.util.TrackRecordTest' attempting to access
+# 'com.android.networkstack.tethering.util.TRTInterpreter' (declaration of
+# 'android.net.connectivity.com.android.net.module.util.TrackRecordTest' ...
+#
+# In coverage test, TRTInterpreter don't be jarjar'ed to
+# android.net.connectivity* by frameworks-net-tests-jarjar-rules instead it is
+# jarjar'ed by follow up TetheringTestsJarJarRules.
+# TODO(b/269259216): remove this after fixing Auto-jarjar-gen.
+com\.android\.net\.module\.util\.TrackRecord.*
diff --git a/tests/unit/java/android/net/Ikev2VpnProfileTest.java b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
index 3b68120..e12e961 100644
--- a/tests/unit/java/android/net/Ikev2VpnProfileTest.java
+++ b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
@@ -492,6 +492,29 @@
}
@Test
+ public void testAutomaticNattAndIpVersionConversionIsLossless() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+ builder.setAutomaticNattKeepaliveTimerEnabled(true);
+ builder.setAutomaticIpVersionSelectionEnabled(true);
+
+ builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+ final Ikev2VpnProfile ikeProfile = builder.build();
+
+ assertEquals(ikeProfile, Ikev2VpnProfile.fromVpnProfile(ikeProfile.toVpnProfile()));
+ }
+
+ @Test
+ public void testAutomaticNattAndIpVersionDefaults() throws Exception {
+ final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
+
+ builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
+ final Ikev2VpnProfile ikeProfile = builder.build();
+
+ assertEquals(false, ikeProfile.isAutomaticNattKeepaliveTimerEnabled());
+ assertEquals(false, ikeProfile.isAutomaticIpVersionSelectionEnabled());
+ }
+
+ @Test
public void testEquals() throws Exception {
// Verify building without IkeTunnelConnectionParams
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
diff --git a/tests/unit/java/android/net/NetworkStatsAccessTest.java b/tests/unit/java/android/net/NetworkStatsAccessTest.java
index a74056b..8b86211 100644
--- a/tests/unit/java/android/net/NetworkStatsAccessTest.java
+++ b/tests/unit/java/android/net/NetworkStatsAccessTest.java
@@ -78,6 +78,7 @@
setHasAppOpsPermission(AppOpsManager.MODE_DEFAULT, false);
setHasReadHistoryPermission(false);
setHasNetworkStackPermission(false);
+ setHasMainlineNetworkStackPermission(false);
}
@After
@@ -154,6 +155,10 @@
setHasNetworkStackPermission(false);
assertEquals(NetworkStatsAccess.Level.DEFAULT,
NetworkStatsAccess.checkAccessLevel(mContext, TEST_PID, TEST_UID, TEST_PKG));
+
+ setHasMainlineNetworkStackPermission(true);
+ assertEquals(NetworkStatsAccess.Level.DEVICE,
+ NetworkStatsAccess.checkAccessLevel(mContext, TEST_PID, TEST_UID, TEST_PKG));
}
private void setHasCarrierPrivileges(boolean hasPrivileges) {
@@ -189,4 +194,10 @@
TEST_PID, TEST_UID)).thenReturn(hasPermission ? PackageManager.PERMISSION_GRANTED
: PackageManager.PERMISSION_DENIED);
}
+
+ private void setHasMainlineNetworkStackPermission(boolean hasPermission) {
+ when(mContext.checkPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ TEST_PID, TEST_UID)).thenReturn(hasPermission ? PackageManager.PERMISSION_GRANTED
+ : PackageManager.PERMISSION_DENIED);
+ }
}
diff --git a/tests/unit/java/android/net/NetworkTemplateTest.kt b/tests/unit/java/android/net/NetworkTemplateTest.kt
index 78854fb..2f6c76b 100644
--- a/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -50,16 +50,17 @@
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.assertParcelSane
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertNotEquals
+import kotlin.test.assertTrue
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import kotlin.test.assertEquals
-import kotlin.test.assertFalse
-import kotlin.test.assertNotEquals
-import kotlin.test.assertTrue
private const val TEST_IMSI1 = "imsi1"
private const val TEST_IMSI2 = "imsi2"
@@ -70,6 +71,8 @@
@RunWith(DevSdkIgnoreRunner::class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
class NetworkTemplateTest {
+ @get:Rule
+ val ignoreRule = DevSdkIgnoreRule()
private val mockContext = mock(Context::class.java)
private val mockWifiInfo = mock(WifiInfo::class.java)
@@ -130,10 +133,17 @@
mockContext, buildWifiNetworkState(null, TEST_WIFI_KEY1), true, 0)
val identWifiImsi1Key1 = buildNetworkIdentity(
mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_WIFI_KEY1), true, 0)
+ // This identity with a null wifiNetworkKey is to test matchesWifiNetworkKey won't crash
+ // the system when a null wifiNetworkKey is provided, which happens because of a bug in wifi
+ // and it should still match the wifi wildcard template. See b/266598304.
+ val identWifiNullKey = buildNetworkIdentity(
+ mockContext, buildWifiNetworkState(null /* subscriberId */,
+ null /* wifiNetworkKey */), true, 0)
templateWifiWildcard.assertDoesNotMatch(identMobileImsi1)
templateWifiWildcard.assertMatches(identWifiImsiNullKey1)
templateWifiWildcard.assertMatches(identWifiImsi1Key1)
+ templateWifiWildcard.assertMatches(identWifiNullKey)
}
@Test
@@ -148,6 +158,9 @@
.setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build()
val templateWifiKeyAllImsi1 = NetworkTemplate.Builder(MATCH_WIFI)
.setSubscriberIds(setOf(TEST_IMSI1)).build()
+ val templateNullWifiKey = NetworkTemplate(MATCH_WIFI,
+ emptyArray<String>() /* subscriberIds */, arrayOf(null) /* wifiNetworkKeys */,
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
val identMobile1 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI1),
false, TelephonyManager.NETWORK_TYPE_UMTS)
@@ -159,6 +172,12 @@
mockContext, buildWifiNetworkState(TEST_IMSI2, TEST_WIFI_KEY1), true, 0)
val identWifiImsi1Key2 = buildNetworkIdentity(
mockContext, buildWifiNetworkState(TEST_IMSI1, TEST_WIFI_KEY2), true, 0)
+ // This identity with a null wifiNetworkKey is to test the matchesWifiNetworkKey won't crash
+ // the system when a null wifiNetworkKey is provided, which would happen in some unknown
+ // cases, see b/266598304.
+ val identWifiNullKey = buildNetworkIdentity(
+ mockContext, buildWifiNetworkState(null /* subscriberId */,
+ null /* wifiNetworkKey */), true, 0)
// Verify that template with WiFi Network Key only matches any subscriberId and
// specific WiFi Network Key.
@@ -191,6 +210,24 @@
templateWifiKeyAllImsi1.assertMatches(identWifiImsi1Key1)
templateWifiKeyAllImsi1.assertDoesNotMatch(identWifiImsi2Key1)
templateWifiKeyAllImsi1.assertMatches(identWifiImsi1Key2)
+
+ // Test a network identity with null wifiNetworkKey won't crash.
+ // It should not match a template with wifiNetworkKeys is non-null.
+ // Also, it should not match a template with wifiNetworkKeys that contains null.
+ templateWifiKey1.assertDoesNotMatch(identWifiNullKey)
+ templateNullWifiKey.assertDoesNotMatch(identWifiNullKey)
+ }
+
+ @DevSdkIgnoreRule.IgnoreAfter(Build.VERSION_CODES.TIRAMISU)
+ @Test
+ fun testBuildTemplateMobileAll_nullSubscriberId() {
+ val templateMobileAllWithNullImsi = buildTemplateMobileAll(null)
+ val setWithNull = HashSet<String?>().apply {
+ add(null)
+ }
+ val templateFromBuilder = NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES)
+ .setSubscriberIds(setWithNull).build()
+ assertEquals(templateFromBuilder, templateMobileAllWithNullImsi)
}
@Test
@@ -443,6 +480,35 @@
}
@Test
+ fun testEquals() {
+ val templateImsi1 = NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES)
+ .setSubscriberIds(setOf(TEST_IMSI1)).setRatType(TelephonyManager.NETWORK_TYPE_UMTS)
+ .build()
+ val dupTemplateImsi1 = NetworkTemplate(MATCH_MOBILE, arrayOf(TEST_IMSI1),
+ emptyArray<String>(), METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+ TelephonyManager.NETWORK_TYPE_UMTS, OEM_MANAGED_ALL)
+ val templateImsi2 = NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES)
+ .setSubscriberIds(setOf(TEST_IMSI2)).setRatType(TelephonyManager.NETWORK_TYPE_UMTS)
+ .build()
+
+ assertEquals(templateImsi1, dupTemplateImsi1)
+ assertEquals(dupTemplateImsi1, templateImsi1)
+ assertNotEquals(templateImsi1, templateImsi2)
+
+ val templateWifiKey1 = NetworkTemplate.Builder(MATCH_WIFI)
+ .setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build()
+ val dupTemplateWifiKey1 = NetworkTemplate(MATCH_WIFI, emptyArray<String>(),
+ arrayOf(TEST_WIFI_KEY1), METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+ NETWORK_TYPE_ALL, OEM_MANAGED_ALL)
+ val templateWifiKey2 = NetworkTemplate.Builder(MATCH_WIFI)
+ .setWifiNetworkKeys(setOf(TEST_WIFI_KEY2)).build()
+
+ assertEquals(templateWifiKey1, dupTemplateWifiKey1)
+ assertEquals(dupTemplateWifiKey1, templateWifiKey1)
+ assertNotEquals(templateWifiKey1, templateWifiKey2)
+ }
+
+ @Test
fun testParcelUnparcel() {
val templateMobile = NetworkTemplate(MATCH_MOBILE, arrayOf(TEST_IMSI1),
emptyArray<String>(), METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
diff --git a/tests/unit/java/android/net/nsd/NsdManagerTest.java b/tests/unit/java/android/net/nsd/NsdManagerTest.java
index 8a4932b..0965193 100644
--- a/tests/unit/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/unit/java/android/net/nsd/NsdManagerTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -32,6 +33,7 @@
import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
+import android.net.connectivity.ConnectivityCompatChanges;
import android.os.Build;
import androidx.test.filters.SmallTest;
@@ -72,79 +74,79 @@
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- doReturn(mServiceConn).when(mService).connect(any());
+ doReturn(mServiceConn).when(mService).connect(any(), anyBoolean());
mManager = new NsdManager(mContext, mService);
final ArgumentCaptor<INsdManagerCallback> cbCaptor = ArgumentCaptor.forClass(
INsdManagerCallback.class);
- verify(mService).connect(cbCaptor.capture());
+ verify(mService).connect(cbCaptor.capture(), anyBoolean());
mCallback = cbCaptor.getValue();
}
@Test
- @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testResolveServiceS() throws Exception {
verify(mServiceConn, never()).startDaemon();
doTestResolveService();
}
@Test
- @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testResolveServicePreS() throws Exception {
verify(mServiceConn).startDaemon();
doTestResolveService();
}
@Test
- @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testDiscoverServiceS() throws Exception {
verify(mServiceConn, never()).startDaemon();
doTestDiscoverService();
}
@Test
- @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testDiscoverServicePreS() throws Exception {
verify(mServiceConn).startDaemon();
doTestDiscoverService();
}
@Test
- @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testParallelResolveServiceS() throws Exception {
verify(mServiceConn, never()).startDaemon();
doTestParallelResolveService();
}
@Test
- @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testParallelResolveServicePreS() throws Exception {
verify(mServiceConn).startDaemon();
doTestParallelResolveService();
}
@Test
- @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testInvalidCallsS() throws Exception {
verify(mServiceConn, never()).startDaemon();
doTestInvalidCalls();
}
@Test
- @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testInvalidCallsPreS() throws Exception {
verify(mServiceConn).startDaemon();
doTestInvalidCalls();
}
@Test
- @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @EnableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testRegisterServiceS() throws Exception {
verify(mServiceConn, never()).startDaemon();
doTestRegisterService();
}
@Test
- @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @DisableCompatChanges(ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
public void testRegisterServicePreS() throws Exception {
verify(mServiceConn).startDaemon();
doTestRegisterService();
diff --git a/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt b/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt
index 9203f8f..cca0b66 100644
--- a/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt
+++ b/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt
@@ -104,7 +104,7 @@
// Check valid customization generates expected array.
val validRes = arrayOf("0,3", "1,0", "4,4")
- val expectedValidRes = intArrayOf(3, 0, 0, 0, 4, 0, 0, 0, 0)
+ val expectedValidRes = intArrayOf(3, 0, 0, 0, 4, 0, 0, 0, 0, 0)
val mockContext = getMockedContextWithStringArrayRes(
R.array.config_networkSupportedKeepaliveCount,
diff --git a/tests/unit/java/com/android/internal/net/VpnProfileTest.java b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
index 0a6d2f2..b2dff2e 100644
--- a/tests/unit/java/com/android/internal/net/VpnProfileTest.java
+++ b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
@@ -20,6 +20,7 @@
import static android.net.cts.util.IkeSessionTestUtils.IKE_PARAMS_V4;
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
+import static com.android.modules.utils.build.SdkLevel.isAtLeastU;
import static com.android.testutils.ParcelUtils.assertParcelSane;
import static org.junit.Assert.assertEquals;
@@ -55,6 +56,9 @@
private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24;
private static final int ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE = 25;
private static final int ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION = 26;
+ private static final int ENCODED_INDEX_IKE_TUN_CONN_PARAMS = 27;
+ private static final int ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED = 28;
+ private static final int ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED = 29;
@Test
public void testDefaults() throws Exception {
@@ -85,12 +89,15 @@
assertFalse(p.isRestrictedToTestNetworks);
assertFalse(p.excludeLocalRoutes);
assertFalse(p.requiresInternetValidation);
+ assertFalse(p.automaticNattKeepaliveTimerEnabled);
+ assertFalse(p.automaticIpVersionSelectionEnabled);
}
private VpnProfile getSampleIkev2Profile(String key) {
final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
false /* excludesLocalRoutes */, true /* requiresPlatformValidation */,
- null /* ikeTunConnParams */);
+ null /* ikeTunConnParams */, true /* mAutomaticNattKeepaliveTimerEnabled */,
+ true /* automaticIpVersionSelectionEnabled */);
p.name = "foo";
p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
@@ -128,7 +135,9 @@
private VpnProfile getSampleIkev2ProfileWithIkeTunConnParams(String key) {
final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
false /* excludesLocalRoutes */, true /* requiresPlatformValidation */,
- new IkeTunnelConnectionParams(IKE_PARAMS_V4, CHILD_PARAMS));
+ new IkeTunnelConnectionParams(IKE_PARAMS_V4, CHILD_PARAMS),
+ true /* mAutomaticNattKeepaliveTimerEnabled */,
+ true /* automaticIpVersionSelectionEnabled */);
p.name = "foo";
p.server = "bar";
@@ -166,7 +175,11 @@
@Test
public void testParcelUnparcel() {
- if (isAtLeastT()) {
+ if (isAtLeastU()) {
+ // automaticNattKeepaliveTimerEnabled, automaticIpVersionSelectionEnabled added in U.
+ assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 28);
+ assertParcelSane(getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY), 28);
+ } else if (isAtLeastT()) {
// excludeLocalRoutes, requiresPlatformValidation were added in T.
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 26);
assertParcelSane(getSampleIkev2ProfileWithIkeTunConnParams(DUMMY_PROFILE_KEY), 26);
@@ -221,16 +234,28 @@
ENCODED_INDEX_AUTH_PARAMS_INLINE,
ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
- ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION,
+ ENCODED_INDEX_IKE_TUN_CONN_PARAMS,
+ ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED,
+ ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED
+ /* missingIndices */);
assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()));
}
+ private String getEncodedDecodedIkev2ProfileWithtooFewValues() {
+ return getEncodedDecodedIkev2ProfileMissingValues(
+ ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
+ ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION,
+ ENCODED_INDEX_IKE_TUN_CONN_PARAMS,
+ ENCODED_INDEX_AUTOMATIC_NATT_KEEPALIVE_TIMER_ENABLED,
+ ENCODED_INDEX_AUTOMATIC_IP_VERSION_SELECTION_ENABLED /* missingIndices */);
+ }
+
@Test
public void testEncodeDecodeMissingIsRestrictedToTestNetworks() {
- final String tooFewValues =
- getEncodedDecodedIkev2ProfileMissingValues(
- ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */);
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
// Verify decoding without isRestrictedToTestNetworks defaults to false
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
@@ -239,10 +264,7 @@
@Test
public void testEncodeDecodeMissingExcludeLocalRoutes() {
- final String tooFewValues =
- getEncodedDecodedIkev2ProfileMissingValues(
- ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
- ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
// Verify decoding without excludeLocalRoutes defaults to false
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
@@ -251,9 +273,7 @@
@Test
public void testEncodeDecodeMissingRequiresValidation() {
- final String tooFewValues =
- getEncodedDecodedIkev2ProfileMissingValues(
- ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
// Verify decoding without requiresValidation defaults to false
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
@@ -261,6 +281,24 @@
}
@Test
+ public void testEncodeDecodeMissingAutomaticNattKeepaliveTimerEnabled() {
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
+
+ // Verify decoding without automaticNattKeepaliveTimerEnabled defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.automaticNattKeepaliveTimerEnabled);
+ }
+
+ @Test
+ public void testEncodeDecodeMissingAutomaticIpVersionSelectionEnabled() {
+ final String tooFewValues = getEncodedDecodedIkev2ProfileWithtooFewValues();
+
+ // Verify decoding without automaticIpVersionSelectionEnabled defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.automaticIpVersionSelectionEnabled);
+ }
+
+ @Test
public void testEncodeDecodeLoginsNotSaved() {
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
profile.saveLogin = false;
diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java
index 0e17cd7..d189848 100644
--- a/tests/unit/java/com/android/server/BpfNetMapsTest.java
+++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java
@@ -690,6 +690,80 @@
mBpfNetMaps.setUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, FIREWALL_RULE_ALLOW));
}
+ private void doTestGetUidRule(final List<Integer> enableChains) throws Exception {
+ mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(0, getMatch(enableChains)));
+
+ for (final int chain: FIREWALL_CHAINS) {
+ final String testCase = "EnabledChains: " + enableChains + " CheckedChain: " + chain;
+ if (enableChains.contains(chain)) {
+ final int expectedRule = mBpfNetMaps.isFirewallAllowList(chain)
+ ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DENY;
+ assertEquals(testCase, expectedRule, mBpfNetMaps.getUidRule(chain, TEST_UID));
+ } else {
+ final int expectedRule = mBpfNetMaps.isFirewallAllowList(chain)
+ ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW;
+ assertEquals(testCase, expectedRule, mBpfNetMaps.getUidRule(chain, TEST_UID));
+ }
+ }
+ }
+
+ private void doTestGetUidRule(final int enableChain) throws Exception {
+ doTestGetUidRule(List.of(enableChain));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testGetUidRule() throws Exception {
+ doTestGetUidRule(FIREWALL_CHAIN_DOZABLE);
+ doTestGetUidRule(FIREWALL_CHAIN_STANDBY);
+ doTestGetUidRule(FIREWALL_CHAIN_POWERSAVE);
+ doTestGetUidRule(FIREWALL_CHAIN_RESTRICTED);
+ doTestGetUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY);
+ doTestGetUidRule(FIREWALL_CHAIN_OEM_DENY_1);
+ doTestGetUidRule(FIREWALL_CHAIN_OEM_DENY_2);
+ doTestGetUidRule(FIREWALL_CHAIN_OEM_DENY_3);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testGetUidRuleMultipleChainEnabled() throws Exception {
+ doTestGetUidRule(List.of(
+ FIREWALL_CHAIN_DOZABLE,
+ FIREWALL_CHAIN_STANDBY));
+ doTestGetUidRule(List.of(
+ FIREWALL_CHAIN_DOZABLE,
+ FIREWALL_CHAIN_STANDBY,
+ FIREWALL_CHAIN_POWERSAVE,
+ FIREWALL_CHAIN_RESTRICTED));
+ doTestGetUidRule(FIREWALL_CHAINS);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testGetUidRuleNoEntry() throws Exception {
+ mUidOwnerMap.clear();
+ for (final int chain: FIREWALL_CHAINS) {
+ final int expectedRule = mBpfNetMaps.isFirewallAllowList(chain)
+ ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW;
+ assertEquals(expectedRule, mBpfNetMaps.getUidRule(chain, TEST_UID));
+ }
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testGetUidRuleInvalidChain() {
+ final Class<ServiceSpecificException> expected = ServiceSpecificException.class;
+ assertThrows(expected, () -> mBpfNetMaps.getUidRule(-1 /* childChain */, TEST_UID));
+ assertThrows(expected, () -> mBpfNetMaps.getUidRule(1000 /* childChain */, TEST_UID));
+ }
+
+ @Test
+ @IgnoreAfter(Build.VERSION_CODES.S_V2)
+ public void testGetUidRuleBeforeT() {
+ assertThrows(UnsupportedOperationException.class,
+ () -> mBpfNetMaps.getUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID));
+ }
+
@Test
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
public void testReplaceUidChain() throws Exception {
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index a2d284b..1cc0c89 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -27,6 +27,7 @@
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_FACTORY;
import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.NETWORK_SETUP_WIZARD;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
@@ -138,6 +139,7 @@
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
+import static android.net.Proxy.PROXY_CHANGE_ACTION;
import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED;
import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_REMOVED;
@@ -171,6 +173,7 @@
import static com.android.testutils.MiscAsserts.assertThrows;
import static com.android.testutils.RecorderCallback.CallbackEntry.AVAILABLE;
import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS;
+import static com.android.testutils.RecorderCallback.CallbackEntry.BLOCKED_STATUS_INT;
import static com.android.testutils.RecorderCallback.CallbackEntry.LINK_PROPERTIES_CHANGED;
import static com.android.testutils.RecorderCallback.CallbackEntry.LOSING;
import static com.android.testutils.RecorderCallback.CallbackEntry.LOST;
@@ -180,6 +183,8 @@
import static com.android.testutils.RecorderCallback.CallbackEntry.UNAVAILABLE;
import static com.android.testutils.TestPermissionUtil.runAsShell;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -225,6 +230,7 @@
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.app.usage.NetworkStatsManager;
+import android.compat.testing.PlatformCompatChangeRule;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -309,6 +315,7 @@
import android.net.Uri;
import android.net.VpnManager;
import android.net.VpnTransportInfo;
+import android.net.connectivity.ConnectivityCompatChanges;
import android.net.metrics.IpConnectivityLog;
import android.net.netd.aidl.NativeUidRangeConfig;
import android.net.networkstack.NetworkStackClientBase;
@@ -376,6 +383,8 @@
import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
import com.android.server.ConnectivityService.NetworkRequestInfo;
import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.ReportedInterfaces;
+import com.android.server.connectivity.ApplicationSelfCertifiedNetworkCapabilities;
+import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
import com.android.server.connectivity.ClatCoordinator;
import com.android.server.connectivity.ConnectivityFlags;
@@ -402,6 +411,9 @@
import com.android.testutils.TestableNetworkCallback;
import com.android.testutils.TestableNetworkOfferCallback;
+import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -471,6 +483,9 @@
@Rule
public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+ @Rule
+ public final PlatformCompatChangeRule compatChangeRule = new PlatformCompatChangeRule();
+
private static final int TIMEOUT_MS = 2_000;
// Broadcasts can take a long time to be delivered. The test will not wait for that long unless
// there is a failure, so use a long timeout.
@@ -537,6 +552,7 @@
private MockContext mServiceContext;
private HandlerThread mCsHandlerThread;
private ConnectivityServiceDependencies mDeps;
+ private AutomaticOnOffKeepaliveTrackerDependencies mAutoOnOffKeepaliveDependencies;
private ConnectivityService mService;
private WrappedConnectivityManager mCm;
private TestNetworkAgentWrapper mWiFiAgent;
@@ -848,7 +864,8 @@
verify(mBroadcastOptionsShim).setDeliveryGroupMatchingKey(
eq(CONNECTIVITY_ACTION),
eq(createDeliveryGroupKeyForConnectivityAction(ni)));
- verify(mBroadcastOptionsShim).setDeferUntilActive(eq(true));
+ verify(mBroadcastOptionsShim).setDeferralPolicy(
+ eq(ConstantsShim.DEFERRAL_POLICY_UNTIL_ACTIVE));
} catch (UnsupportedApiLevelException e) {
throw new RuntimeException(e);
}
@@ -1837,7 +1854,8 @@
doReturn(mResources).when(mockResContext).getResources();
ConnectivityResources.setResourcesContextForTest(mockResContext);
mDeps = new ConnectivityServiceDependencies(mockResContext);
-
+ mAutoOnOffKeepaliveDependencies =
+ new AutomaticOnOffKeepaliveTrackerDependencies(mServiceContext);
mService = new ConnectivityService(mServiceContext,
mMockDnsResolver,
mock(IpConnectivityLog.class),
@@ -1938,6 +1956,12 @@
}
@Override
+ public AutomaticOnOffKeepaliveTracker makeAutomaticOnOffKeepaliveTracker(final Context c,
+ final Handler h) {
+ return new AutomaticOnOffKeepaliveTracker(c, h, mAutoOnOffKeepaliveDependencies);
+ }
+
+ @Override
public ConnectivityResources getResources(final Context ctx) {
return mConnRes;
}
@@ -2093,6 +2117,51 @@
reset(mBroadcastOptionsShim);
return mBroadcastOptionsShim;
}
+
+ @GuardedBy("this")
+ private boolean mForceDisableCompatChangeCheck = true;
+
+ /**
+ * By default, the {@link #isChangeEnabled(long, String, UserHandle)} will always return
+ * true as the mForceDisableCompatChangeCheck is true and compat change check logic is
+ * never executed. The compat change check logic can be turned on by calling this method.
+ * If this method is called, the
+ * {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} or
+ * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges} must be
+ * used to turn on/off the compat change flag.
+ */
+ private void enableCompatChangeCheck() {
+ synchronized (this) {
+ mForceDisableCompatChangeCheck = false;
+ }
+ }
+
+ @Override
+ public boolean isChangeEnabled(long changeId,
+ @NonNull final String packageName,
+ @NonNull final UserHandle user) {
+ synchronized (this) {
+ if (mForceDisableCompatChangeCheck) {
+ return false;
+ } else {
+ return super.isChangeEnabled(changeId, packageName, user);
+ }
+ }
+ }
+ }
+
+ private class AutomaticOnOffKeepaliveTrackerDependencies
+ extends AutomaticOnOffKeepaliveTracker.Dependencies {
+ AutomaticOnOffKeepaliveTrackerDependencies(Context context) {
+ super(context);
+ }
+
+ @Override
+ public boolean isFeatureEnabled(@NonNull final String name, final boolean defaultEnabled) {
+ // Tests for enabling the feature are verified in AutomaticOnOffKeepaliveTrackerTest.
+ // Assuming enabled here to focus on ConnectivityService tests.
+ return true;
+ }
}
private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
@@ -2150,7 +2219,9 @@
ConnectivityResources.setResourcesContextForTest(null);
mCsHandlerThread.quitSafely();
+ mCsHandlerThread.join();
mAlarmManagerThread.quitSafely();
+ mAlarmManagerThread.join();
}
private void mockDefaultPackages() throws Exception {
@@ -2273,22 +2344,15 @@
}
}
- /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
- private ExpectedBroadcast registerConnectivityBroadcast(final int count) {
- return registerConnectivityBroadcastThat(count, intent -> true);
- }
-
- private ExpectedBroadcast registerConnectivityBroadcastThat(final int count,
+ private ExpectedBroadcast registerBroadcastReceiverThat(final String action, final int count,
@NonNull final Predicate<Intent> filter) {
- final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
+ final IntentFilter intentFilter = new IntentFilter(action);
// AtomicReference allows receiver to access expected even though it is constructed later.
final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
final BroadcastReceiver receiver = new BroadcastReceiver() {
private int mRemaining = count;
public void onReceive(Context context, Intent intent) {
- final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
- final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
- Log.d(TAG, "Received CONNECTIVITY_ACTION type=" + type + " ni=" + ni);
+ logIntent(intent);
if (!filter.test(intent)) return;
if (--mRemaining == 0) {
expectedRef.get().complete(intent);
@@ -2301,39 +2365,49 @@
return expected;
}
+ private void logIntent(Intent intent) {
+ final String action = intent.getAction();
+ if (CONNECTIVITY_ACTION.equals(action)) {
+ final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
+ final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
+ Log.d(TAG, "Received " + action + ", type=" + type + " ni=" + ni);
+ } else if (PROXY_CHANGE_ACTION.equals(action)) {
+ final ProxyInfo proxy = (ProxyInfo) intent.getExtra(
+ Proxy.EXTRA_PROXY_INFO, ProxyInfo.buildPacProxy(Uri.EMPTY));
+ Log.d(TAG, "Received " + action + ", proxy = " + proxy);
+ } else {
+ throw new IllegalArgumentException("Unsupported logging " + action);
+ }
+ }
+
+ /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
+ private ExpectedBroadcast expectConnectivityAction(final int count) {
+ return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, count, intent -> true);
+ }
+
+ private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
+ return registerBroadcastReceiverThat(CONNECTIVITY_ACTION, 1, intent -> {
+ final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
+ final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
+ return type == actualType
+ && state == ni.getDetailedState()
+ && extraInfoInBroadcastHasExpectedNullness(ni);
+ });
+ }
+
+ /** Expects that PROXY_CHANGE_ACTION broadcast is received. */
+ private ExpectedBroadcast expectProxyChangeAction() {
+ return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> true);
+ }
+
private ExpectedBroadcast expectProxyChangeAction(ProxyInfo proxy) {
- return registerPacProxyBroadcastThat(intent -> {
+ return registerBroadcastReceiverThat(PROXY_CHANGE_ACTION, 1, intent -> {
final ProxyInfo actualProxy = (ProxyInfo) intent.getExtra(Proxy.EXTRA_PROXY_INFO,
ProxyInfo.buildPacProxy(Uri.EMPTY));
return proxy.equals(actualProxy);
});
}
- private ExpectedBroadcast registerPacProxyBroadcast() {
- return registerPacProxyBroadcastThat(intent -> true);
- }
-
- private ExpectedBroadcast registerPacProxyBroadcastThat(
- @NonNull final Predicate<Intent> filter) {
- final IntentFilter intentFilter = new IntentFilter(Proxy.PROXY_CHANGE_ACTION);
- // AtomicReference allows receiver to access expected even though it is constructed later.
- final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
- final BroadcastReceiver receiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- final ProxyInfo proxy = (ProxyInfo) intent.getExtra(
- Proxy.EXTRA_PROXY_INFO, ProxyInfo.buildPacProxy(Uri.EMPTY));
- Log.d(TAG, "Receive PROXY_CHANGE_ACTION, proxy = " + proxy);
- if (filter.test(intent)) {
- expectedRef.get().complete(intent);
- }
- }
- };
- final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
- expectedRef.set(expected);
- mServiceContext.registerReceiver(receiver, intentFilter);
- return expected;
- }
-
private boolean extraInfoInBroadcastHasExpectedNullness(NetworkInfo ni) {
final DetailedState state = ni.getDetailedState();
if (state == DetailedState.CONNECTED && ni.getExtraInfo() == null) return false;
@@ -2349,16 +2423,6 @@
return true;
}
- private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
- return registerConnectivityBroadcastThat(1, intent -> {
- final int actualType = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
- final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
- return type == actualType
- && state == ni.getDetailedState()
- && extraInfoInBroadcastHasExpectedNullness(ni);
- });
- }
-
@Test
public void testNetworkTypes() {
// Ensure that our mocks for the networkAttributes config variable work as expected. If they
@@ -2393,7 +2457,7 @@
ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
// File request, withdraw it and make sure no broadcast is sent
- b = registerConnectivityBroadcast(1);
+ b = expectConnectivityAction(1);
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.requestNetwork(legacyRequest, callback);
callback.expect(AVAILABLE, mCellAgent);
@@ -2424,7 +2488,7 @@
assertTrue(mCm.getAllNetworks()[0].equals(mWiFiAgent.getNetwork())
|| mCm.getAllNetworks()[1].equals(mWiFiAgent.getNetwork()));
// Test bringing up validated WiFi.
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mWiFiAgent.connect(true);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -2441,7 +2505,7 @@
assertLength(1, mCm.getAllNetworks());
assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
// Test WiFi disconnect.
- b = registerConnectivityBroadcast(1);
+ b = expectConnectivityAction(1);
mWiFiAgent.disconnect();
b.expectBroadcast();
verifyNoNetwork();
@@ -2607,7 +2671,7 @@
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
// Test bringing up unvalidated WiFi
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ExpectedBroadcast b = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(1);
mWiFiAgent.connect(false);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -2622,17 +2686,17 @@
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mCellAgent.connect(true);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test cellular disconnect.
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mCellAgent.disconnect();
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi disconnect.
- b = registerConnectivityBroadcast(1);
+ b = expectConnectivityAction(1);
mWiFiAgent.disconnect();
b.expectBroadcast();
verifyNoNetwork();
@@ -2655,23 +2719,23 @@
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
// Test bringing up unvalidated cellular.
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ExpectedBroadcast b = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(1);
mCellAgent.connect(false);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up unvalidated WiFi.
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mWiFiAgent.connect(false);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi disconnect.
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mWiFiAgent.disconnect();
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test cellular disconnect.
- b = registerConnectivityBroadcast(1);
+ b = expectConnectivityAction(1);
mCellAgent.disconnect();
b.expectBroadcast();
verifyNoNetwork();
@@ -2694,7 +2758,7 @@
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
// Test bringing up unvalidated WiFi.
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ExpectedBroadcast b = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(1);
mWiFiAgent.connect(false);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -2702,14 +2766,14 @@
NET_CAPABILITY_VALIDATED));
// Test bringing up validated cellular.
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mCellAgent.connect(true);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
assertFalse(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
// Test cellular disconnect.
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mCellAgent.disconnect();
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -2771,7 +2835,7 @@
if (expectLingering) {
generalCb.expectLosing(net1);
}
- generalCb.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, net2);
+ generalCb.expectCaps(net2, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
defaultCb.expectAvailableDoubleValidatedCallbacks(net2);
// Make sure cell 1 is unwanted immediately if the radio can't time share, but only
@@ -2849,23 +2913,23 @@
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
// Test bringing up validated cellular.
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ExpectedBroadcast b = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(1);
mCellAgent.connect(true);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up validated WiFi.
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mWiFiAgent.connect(true);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi getting really weak.
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mWiFiAgent.adjustScore(-11);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test WiFi restoring signal strength.
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mWiFiAgent.adjustScore(11);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -2930,18 +2994,18 @@
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
// Test bringing up validated cellular.
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ExpectedBroadcast b = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(1);
mCellAgent.connect(true);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up validated WiFi.
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mWiFiAgent.connect(true);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Reevaluate WiFi (it'll instantly fail DNS).
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
assertTrue(mCm.getNetworkCapabilities(mWiFiAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
mCm.reportBadNetwork(mWiFiAgent.getNetwork());
@@ -2951,7 +3015,7 @@
NET_CAPABILITY_VALIDATED));
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Reevaluate cellular (it'll instantly fail DNS).
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
mCm.reportBadNetwork(mCellAgent.getNetwork());
@@ -2981,18 +3045,18 @@
mService.mCellularRadioTimesharingCapable = cellRadioTimesharingCapable;
// Test bringing up unvalidated WiFi.
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ExpectedBroadcast b = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(1);
mWiFiAgent.connect(false);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular.
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mCellAgent.connect(true);
b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Reevaluate cellular (it'll instantly fail DNS).
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
assertTrue(mCm.getNetworkCapabilities(mCellAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
mCm.reportBadNetwork(mCellAgent.getNetwork());
@@ -3070,9 +3134,8 @@
NetworkSpecifier specifier, TestNetworkCallback ... callbacks) {
for (TestNetworkCallback c : callbacks) {
c.expect(AVAILABLE, network);
- c.expectCapabilitiesThat(network, (nc) ->
- !nc.hasCapability(NET_CAPABILITY_VALIDATED)
- && Objects.equals(specifier, nc.getNetworkSpecifier()));
+ c.expectCaps(network, cb -> !cb.hasCapability(NET_CAPABILITY_VALIDATED)
+ && Objects.equals(specifier, cb.getNetworkSpecifier()));
c.expect(LINK_PROPERTIES_CHANGED, network);
c.expect(BLOCKED_STATUS, network);
}
@@ -3131,7 +3194,7 @@
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
// Test unvalidated networks
- ExpectedBroadcast b = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(1);
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellAgent.connect(false);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellAgent);
@@ -3146,7 +3209,7 @@
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiAgent.connect(false);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
@@ -3155,18 +3218,18 @@
b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
- b = registerConnectivityBroadcast(2);
+ b = expectConnectivityAction(2);
mWiFiAgent.disconnect();
- genericNetworkCallback.expect(LOST, mWiFiAgent);
- wifiNetworkCallback.expect(LOST, mWiFiAgent);
+ genericNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
+ wifiNetworkCallback.expect(CallbackEntry.LOST, mWiFiAgent);
cellNetworkCallback.assertNoCallback();
b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
- b = registerConnectivityBroadcast(1);
+ b = expectConnectivityAction(1);
mCellAgent.disconnect();
- genericNetworkCallback.expect(LOST, mCellAgent);
- cellNetworkCallback.expect(LOST, mCellAgent);
+ genericNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
+ cellNetworkCallback.expect(CallbackEntry.LOST, mCellAgent);
b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
@@ -3188,7 +3251,8 @@
mWiFiAgent.connect(true);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
genericNetworkCallback.expectLosing(mCellAgent);
- genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ genericNetworkCallback.expectCaps(mWiFiAgent,
+ c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
cellNetworkCallback.expectLosing(mCellAgent);
assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
@@ -3229,17 +3293,17 @@
final Uri expectedCapportUrl = sanitized ? null : capportUrl;
newLp.setCaptivePortalApiUrl(capportUrl);
mWiFiAgent.sendLinkProperties(newLp);
- callback.expectLinkPropertiesThat(mWiFiAgent, lp ->
- Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
- defaultCallback.expectLinkPropertiesThat(mWiFiAgent, lp ->
- Objects.equals(expectedCapportUrl, lp.getCaptivePortalApiUrl()));
+ callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
+ Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
+ defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
+ Objects.equals(expectedCapportUrl, cb.getLp().getCaptivePortalApiUrl()));
final CaptivePortalData expectedCapportData = sanitized ? null : capportData;
mWiFiAgent.notifyCapportApiDataChanged(capportData);
- callback.expectLinkPropertiesThat(mWiFiAgent, lp ->
- Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
- defaultCallback.expectLinkPropertiesThat(mWiFiAgent, lp ->
- Objects.equals(expectedCapportData, lp.getCaptivePortalData()));
+ callback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
+ Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
+ defaultCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent, cb ->
+ Objects.equals(expectedCapportData, cb.getLp().getCaptivePortalData()));
final LinkProperties lp = mCm.getLinkProperties(mWiFiAgent.getNetwork());
assertEquals(expectedCapportUrl, lp.getCaptivePortalApiUrl());
@@ -3337,7 +3401,7 @@
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
// TODO: Investigate sending validated before losing.
callback.expectLosing(mCellAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -3346,7 +3410,7 @@
callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
// TODO: Investigate sending validated before losing.
callback.expectLosing(mWiFiAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetAgent);
+ callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -3381,7 +3445,7 @@
// if the network is still up.
mWiFiAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
// We expect a notification about the capabilities change, and nothing else.
- defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiAgent);
+ defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
defaultCallback.assertNoCallback();
callback.expect(LOST, mWiFiAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -3440,7 +3504,7 @@
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
// TODO: Investigate sending validated before losing.
callback.expectLosing(mCellAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiAgent);
assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -3467,7 +3531,7 @@
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
// TODO: Investigate sending validated before losing.
callback.expectLosing(mCellAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
NetworkRequest cellRequest = new NetworkRequest.Builder()
@@ -3517,7 +3581,7 @@
mEthernetAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
callback.expectLosing(mWiFiAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetAgent);
+ callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -3577,7 +3641,7 @@
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiAgent);
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
callback.expectLosing(mCellAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
// File a request for cellular, then release it.
NetworkRequest cellRequest = new NetworkRequest.Builder()
@@ -3590,7 +3654,8 @@
// Let linger run its course.
callback.assertNoCallback();
final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
- callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellAgent, lingerTimeoutMs);
+ callback.expectCaps(mCellAgent, lingerTimeoutMs,
+ c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
// Clean up.
mCm.unregisterNetworkCallback(defaultCallback);
@@ -3752,13 +3817,13 @@
@Test
public void testExplicitlySelected() throws Exception {
- NetworkRequest request = new NetworkRequest.Builder()
+ final NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
.build();
- TestNetworkCallback callback = new TestNetworkCallback();
+ final TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerNetworkCallback(request, callback);
- // Bring up validated cell.
+ // Bring up validated cell
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellAgent.connect(true);
callback.expectAvailableThenValidatedCallbacks(mCellAgent);
@@ -3812,15 +3877,21 @@
mWiFiAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
callback.expectLosing(mCellAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
expectUnvalidationCheckWillNotNotify(mWiFiAgent);
+ // Now request cell so it doesn't disconnect during the test
+ final NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .clearCapabilities().addTransportType(TRANSPORT_CELLULAR).build();
+ final TestNetworkCallback cellCallback = new TestNetworkCallback();
+ mCm.requestNetwork(cellRequest, cellCallback);
+
mEthernetAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
mEthernetAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mEthernetAgent);
callback.expectLosing(mWiFiAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetAgent);
+ callback.expectCaps(mEthernetAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
assertEquals(mEthernetAgent.getNetwork(), mCm.getActiveNetwork());
callback.assertNoCallback();
@@ -3857,6 +3928,7 @@
callback.expect(LOST, mWiFiAgent);
callback.expect(LOST, mCellAgent);
+ mCm.unregisterNetworkCallback(cellCallback);
}
private void doTestFirstEvaluation(
@@ -4268,7 +4340,7 @@
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiAgent.connectWithPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
// Mobile data should be the default network.
assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
@@ -4296,8 +4368,8 @@
// validated.
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
callback.expectLosing(mCellAgent);
- NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
- mWiFiAgent);
+ NetworkCapabilities nc =
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
@@ -4311,7 +4383,7 @@
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiAgent.connectWithPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
// Mobile data should be the default network.
assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
@@ -4343,7 +4415,7 @@
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectLosing(mCellAgent);
- nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ nc = callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
// Wifi should be the default network.
@@ -4364,7 +4436,7 @@
verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectLosing(mCellAgent);
assertEquals(mWiFiAgent.getNetwork(), mCm.getActiveNetwork());
- callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
expectUnvalidationCheckWillNotNotify(mWiFiAgent);
mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
@@ -4372,7 +4444,7 @@
// Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
// validated.
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
mWiFiAgent.disconnect();
callback.expect(LOST, mWiFiAgent);
@@ -4388,8 +4460,8 @@
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
verify(mWiFiAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectLosing(mCellAgent);
- callback.expectCapabilitiesWith(
- NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
+ && c.hasCapability(NET_CAPABILITY_VALIDATED));
expectUnvalidationCheckWillNotNotify(mWiFiAgent);
mWiFiAgent.disconnect();
callback.expect(LOST, mWiFiAgent);
@@ -4420,7 +4492,7 @@
// This is necessary because of b/245893397, the same bug that happens where we use
// expectAvailableDoubleValidatedCallbacks.
// TODO : fix b/245893397 and remove this.
- wifiCallback.expectCapabilitiesWith(NET_CAPABILITY_CAPTIVE_PORTAL, mWiFiAgent);
+ wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
// Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
mCm.startCaptivePortalApp(mWiFiAgent.getNetwork());
@@ -4431,9 +4503,9 @@
mWiFiAgent.setNetworkPartial();
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
waitForIdle();
- wifiCallback.expectCapabilitiesThat(mWiFiAgent, nc ->
- nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
- && !nc.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
+ wifiCallback.expectCaps(mWiFiAgent,
+ c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)
+ && !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
// Report partial connectivity is accepted.
mWiFiAgent.setNetworkPartialValid(false /* privateDnsProbeSent */);
@@ -4441,9 +4513,10 @@
false /* always */);
waitForIdle();
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
- wifiCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ wifiCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
validatedCallback.expectAvailableCallbacksValidated(mWiFiAgent);
- validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiAgent);
+ validatedCallback.expectCaps(mWiFiAgent,
+ c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
mCm.unregisterNetworkCallback(wifiCallback);
mCm.unregisterNetworkCallback(validatedCallback);
@@ -4552,7 +4625,7 @@
// This is necessary because of b/245893397, the same bug that happens where we use
// expectAvailableDoubleValidatedCallbacks.
// TODO : fix b/245893397 and remove this.
- captivePortalCallback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
+ captivePortalCallback.expectCaps(mWiFiAgent);
startCaptivePortalApp(mWiFiAgent);
@@ -4645,15 +4718,16 @@
mWiFiAgent.notifyCapportApiDataChanged(testData);
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> testData.equals(lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> testData.equals(cb.getLp().getCaptivePortalData()));
final LinkProperties newLps = new LinkProperties();
newLps.setMtu(1234);
mWiFiAgent.sendLinkProperties(newLps);
// CaptivePortalData is not lost and unchanged when LPs are received from the NetworkAgent
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> testData.equals(lp.getCaptivePortalData()) && lp.getMtu() == 1234);
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> testData.equals(cb.getLp().getCaptivePortalData())
+ && cb.getLp().getMtu() == 1234);
}
private TestNetworkCallback setupNetworkCallbackAndConnectToWifi() throws Exception {
@@ -4747,8 +4821,8 @@
// Baseline capport data
mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
// Venue URL, T&C URL and friendly name from Network agent with Passpoint source, confirm
// that API data gets precedence on the bytes remaining.
@@ -4757,9 +4831,9 @@
mWiFiAgent.sendLinkProperties(linkProperties);
// Make sure that the capport data is merged
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mExpectedMergedPasspointData
- .equals(lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
+ cb.getLp().getCaptivePortalData()));
// Now send this information from non-Passpoint source, confirm that Capport data takes
// precedence
@@ -4767,9 +4841,9 @@
mWiFiAgent.sendLinkProperties(linkProperties);
// Make sure that the capport data is merged
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mExpectedMergedOtherData
- .equals(lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
+ cb.getLp().getCaptivePortalData()));
// Create a new LP with no Network agent capport data
final LinkProperties newLps = new LinkProperties();
@@ -4777,21 +4851,22 @@
mWiFiAgent.sendLinkProperties(newLps);
// CaptivePortalData is not lost and has the original values when LPs are received from the
// NetworkAgent
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData())
- && lp.getMtu() == 1234);
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData())
+ && cb.getLp().getMtu() == 1234);
// Now send capport data only from the Network agent
mWiFiAgent.notifyCapportApiDataChanged(null);
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> lp.getCaptivePortalData() == null);
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> cb.getLp().getCaptivePortalData() == null);
newLps.setCaptivePortalData(captivePortalTestData.mNaPasspointData);
mWiFiAgent.sendLinkProperties(newLps);
// Make sure that only the network agent capport data is available
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mNaPasspointData.equals(
+ cb.getLp().getCaptivePortalData()));
}
@Test
@@ -4806,25 +4881,26 @@
mWiFiAgent.sendLinkProperties(linkProperties);
// Make sure that the data is saved correctly
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mNaPasspointData.equals(lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mNaPasspointData.equals(
+ cb.getLp().getCaptivePortalData()));
// Expected merged data: Network agent data is preferred, and values that are not used by
// it are merged from capport data
mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
// Make sure that the Capport data is merged correctly
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mExpectedMergedPasspointData.equals(
- lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mExpectedMergedPasspointData.equals(
+ cb.getLp().getCaptivePortalData()));
// Now set the naData to null
linkProperties.setCaptivePortalData(null);
mWiFiAgent.sendLinkProperties(linkProperties);
// Make sure that the Capport data is retained correctly
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mCapportData.equals(lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mCapportData.equals(cb.getLp().getCaptivePortalData()));
}
@Test
@@ -4840,17 +4916,17 @@
mWiFiAgent.sendLinkProperties(linkProperties);
// Make sure that the data is saved correctly
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mNaOtherData.equals(lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mNaOtherData.equals(cb.getLp().getCaptivePortalData()));
// Expected merged data: Network agent data is preferred, and values that are not used by
// it are merged from capport data
mWiFiAgent.notifyCapportApiDataChanged(captivePortalTestData.mCapportData);
// Make sure that the Capport data is merged correctly
- captivePortalCallback.expectLinkPropertiesThat(mWiFiAgent,
- lp -> captivePortalTestData.mExpectedMergedOtherData.equals(
- lp.getCaptivePortalData()));
+ captivePortalCallback.expect(LINK_PROPERTIES_CHANGED, mWiFiAgent,
+ cb -> captivePortalTestData.mExpectedMergedOtherData.equals(
+ cb.getLp().getCaptivePortalData()));
}
private NetworkRequest.Builder newWifiRequestBuilder() {
@@ -5239,7 +5315,8 @@
// Suspend the network.
mCellAgent.suspend();
- cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED, mCellAgent);
+ cellNetworkCallback.expectCaps(mCellAgent,
+ c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
cellNetworkCallback.expect(SUSPENDED, mCellAgent);
cellNetworkCallback.assertNoCallback();
assertEquals(NetworkInfo.State.SUSPENDED, mCm.getActiveNetworkInfo().getState());
@@ -5254,7 +5331,8 @@
mCm.unregisterNetworkCallback(dfltNetworkCallback);
mCellAgent.resume();
- cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED, mCellAgent);
+ cellNetworkCallback.expectCaps(mCellAgent,
+ c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
cellNetworkCallback.expect(RESUMED, mCellAgent);
cellNetworkCallback.assertNoCallback();
assertEquals(NetworkInfo.State.CONNECTED, mCm.getActiveNetworkInfo().getState());
@@ -5295,6 +5373,13 @@
callback.expectAvailableCallbacksUnvalidated(mCellAgent);
mCm.unregisterNetworkCallback(callback);
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_SETUP_WIZARD, PERMISSION_GRANTED);
+ mCm.registerSystemDefaultNetworkCallback(callback, handler);
+ callback.expectAvailableCallbacksUnvalidated(mCellAgent);
+ mCm.unregisterNetworkCallback(callback);
+
+ mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
mCm.registerDefaultNetworkCallbackForUid(APP1_UID, callback, handler);
callback.expectAvailableCallbacksUnvalidated(mCellAgent);
mCm.unregisterNetworkCallback(callback);
@@ -5481,10 +5566,10 @@
// When wifi connects, cell lingers.
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
callback.expectLosing(mCellAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
fgCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
fgCallback.expectLosing(mCellAgent);
- fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ fgCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
assertTrue(isForegroundNetwork(mCellAgent));
assertTrue(isForegroundNetwork(mWiFiAgent));
@@ -5493,7 +5578,7 @@
int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
fgCallback.expect(LOST, mCellAgent, timeoutMs);
// Expect a network capabilities update sans FOREGROUND.
- callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellAgent);
+ callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
assertFalse(isForegroundNetwork(mCellAgent));
assertTrue(isForegroundNetwork(mWiFiAgent));
@@ -5506,8 +5591,8 @@
fgCallback.expectAvailableCallbacksValidated(mCellAgent);
// Expect a network capabilities update with FOREGROUND, because the most recent
// request causes its state to change.
- cellCallback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellAgent);
- callback.expectCapabilitiesWith(NET_CAPABILITY_FOREGROUND, mCellAgent);
+ cellCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
+ callback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_FOREGROUND));
assertTrue(isForegroundNetwork(mCellAgent));
assertTrue(isForegroundNetwork(mWiFiAgent));
@@ -5516,7 +5601,7 @@
mCm.unregisterNetworkCallback(cellCallback);
fgCallback.expect(LOST, mCellAgent);
// Expect a network capabilities update sans FOREGROUND.
- callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellAgent);
+ callback.expectCaps(mCellAgent, c -> !c.hasCapability(NET_CAPABILITY_FOREGROUND));
assertFalse(isForegroundNetwork(mCellAgent));
assertTrue(isForegroundNetwork(mWiFiAgent));
@@ -5668,7 +5753,8 @@
// Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
// validated – see testPartialConnectivity.
mCm.reportNetworkConnectivity(mCellAgent.getNetwork(), true);
- cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellAgent);
+ cellNetworkCallback.expectCaps(mCellAgent,
+ c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
testFactory.expectRequestRemove();
testFactory.assertRequestCountEquals(0);
// Accordingly, the factory shouldn't be started.
@@ -5869,14 +5955,15 @@
mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
// Have CS reconsider the network (see testPartialConnectivity)
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
- wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
cellCallback.expectOnNetworkUnneeded(defaultCaps);
wifiCallback.assertNoCallback();
// Wifi is no longer validated. Cell is needed again.
mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
- wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent,
+ c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
cellCallback.expectOnNetworkNeeded(defaultCaps);
wifiCallback.assertNoCallback();
@@ -5898,7 +5985,8 @@
wifiCallback.assertNoCallback();
mWiFiAgent.setNetworkValid(true /* privateDnsProbeSent */);
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
- wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent,
+ c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
cellCallback.expectOnNetworkUnneeded(defaultCaps);
wifiCallback.assertNoCallback();
@@ -5906,7 +5994,8 @@
// not needed.
mWiFiAgent.setNetworkInvalid(true /* invalidBecauseOfPrivateDns */);
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
- wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent,
+ c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
cellCallback.assertNoCallback();
wifiCallback.assertNoCallback();
}
@@ -6001,7 +6090,7 @@
// Fail validation on wifi.
mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
mCm.reportNetworkConnectivity(wifiNetwork, false);
- defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
validatedWifiCallback.expect(LOST, mWiFiAgent);
expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
@@ -6052,7 +6141,7 @@
// Fail validation on wifi and expect the dialog to appear.
mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
mCm.reportNetworkConnectivity(wifiNetwork, false);
- defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ defaultCallback.expectCaps(mWiFiAgent, c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
validatedWifiCallback.expect(LOST, mWiFiAgent);
expectNotification(mWiFiAgent, NotificationType.LOST_INTERNET);
@@ -6273,6 +6362,142 @@
}
}
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @DisableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void testSelfCertifiedCapabilitiesDisabled()
+ throws Exception {
+ mDeps.enableCompatChangeCheck();
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ mCm.requestNetwork(networkRequest, cb);
+ mCm.unregisterNetworkCallback(cb);
+ }
+
+ /** Set the networkSliceResourceId to 0 will result in NameNotFoundException be thrown. */
+ private void setupMockForNetworkCapabilitiesResources(int networkSliceResourceId)
+ throws PackageManager.NameNotFoundException {
+ if (networkSliceResourceId == 0) {
+ doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getProperty(
+ ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
+ mContext.getPackageName());
+ } else {
+ final PackageManager.Property property = new PackageManager.Property(
+ ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
+ networkSliceResourceId,
+ true /* isResource */,
+ mContext.getPackageName(),
+ "dummyClass"
+ );
+ doReturn(property).when(mPackageManager).getProperty(
+ ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
+ mContext.getPackageName());
+ doReturn(mContext.getResources()).when(mPackageManager).getResourcesForApplication(
+ mContext.getPackageName());
+ }
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withoutPrioritizeBandwidthDeclaration_shouldThrowException()
+ throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(
+ com.android.frameworks.tests.net.R.xml.self_certified_capabilities_latency);
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ final Exception e = assertThrows(SecurityException.class,
+ () -> mCm.requestNetwork(networkRequest, cb));
+ assertThat(e.getMessage(),
+ containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_BANDWIDTH));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withoutPrioritizeLatencyDeclaration_shouldThrowException()
+ throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(
+ com.android.frameworks.tests.net.R.xml.self_certified_capabilities_bandwidth);
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ final Exception e = assertThrows(SecurityException.class,
+ () -> mCm.requestNetwork(networkRequest, cb));
+ assertThat(e.getMessage(),
+ containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_LATENCY));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withoutNetworkSliceProperty_shouldThrowException() throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(0 /* networkSliceResourceId */);
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ final Exception e = assertThrows(SecurityException.class,
+ () -> mCm.requestNetwork(networkRequest, cb));
+ assertThat(e.getMessage(),
+ containsString(ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withNetworkSliceDeclaration_shouldSucceed() throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(
+ com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
+
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ mCm.requestNetwork(networkRequest, cb);
+ mCm.unregisterNetworkCallback(cb);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withNetworkSliceDeclaration_shouldUseCache() throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(
+ com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
+
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ mCm.requestNetwork(networkRequest, cb);
+ mCm.unregisterNetworkCallback(cb);
+
+ // Second call should use caches
+ mCm.requestNetwork(networkRequest, cb);
+ mCm.unregisterNetworkCallback(cb);
+
+ // PackageManager's API only called once because the second call is using cache.
+ verify(mPackageManager, times(1)).getProperty(
+ ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
+ mContext.getPackageName());
+ verify(mPackageManager, times(1)).getResourcesForApplication(
+ mContext.getPackageName());
+ }
+
/**
* Validate the service throws if request with CBS but without carrier privilege.
*/
@@ -6998,7 +7223,7 @@
assertNotPinnedToWifi();
// Disconnect cell and wifi.
- ExpectedBroadcast b = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
+ ExpectedBroadcast b = expectConnectivityAction(3); // cell down, wifi up, wifi down.
mCellAgent.disconnect();
mWiFiAgent.disconnect();
b.expectBroadcast();
@@ -7011,7 +7236,7 @@
assertPinnedToWifiWithWifiDefault();
// ... and is maintained even when that network is no longer the default.
- b = registerConnectivityBroadcast(1);
+ b = expectConnectivityAction(1);
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mCellAgent.connect(true);
b.expectBroadcast();
@@ -7188,7 +7413,7 @@
@Test
public void testNetworkInfoOfTypeNone() throws Exception {
- ExpectedBroadcast b = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(1);
verifyNoNetwork();
TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
@@ -7269,7 +7494,7 @@
CallbackEntry.LinkPropertiesChanged cbi =
networkCallback.expect(LINK_PROPERTIES_CHANGED, networkAgent);
networkCallback.expect(BLOCKED_STATUS, networkAgent);
- networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
+ networkCallback.expectCaps(networkAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
networkCallback.assertNoCallback();
checkDirectlyConnectedRoutes(cbi.getLp(), asList(myIpv4Address),
asList(myIpv4DefaultRoute));
@@ -7583,8 +7808,7 @@
TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(callback);
callback.expect(AVAILABLE, mCellAgent);
- callback.expectCapabilitiesThat(
- mCellAgent, nc -> Arrays.equals(adminUids, nc.getAdministratorUids()));
+ callback.expectCaps(mCellAgent, c -> Arrays.equals(adminUids, c.getAdministratorUids()));
mCm.unregisterNetworkCallback(callback);
// Verify case where caller does NOT have permission
@@ -7594,7 +7818,7 @@
callback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(callback);
callback.expect(AVAILABLE, mCellAgent);
- callback.expectCapabilitiesThat(mCellAgent, nc -> nc.getAdministratorUids().length == 0);
+ callback.expectCaps(mCellAgent, c -> c.getAdministratorUids().length == 0);
}
@Test
@@ -8177,8 +8401,7 @@
mMockVpn.setUnderlyingNetworks(new Network[]{wifiNetwork});
// onCapabilitiesChanged() should be called because
// NetworkCapabilities#mUnderlyingNetworks is updated.
- CallbackEntry ce = callback.expect(NETWORK_CAPS_UPDATED, mMockVpn);
- final NetworkCapabilities vpnNc1 = ((CallbackEntry.CapabilitiesChanged) ce).getCaps();
+ final NetworkCapabilities vpnNc1 = callback.expectCaps(mMockVpn);
// Since the wifi network hasn't brought up,
// ConnectivityService#applyUnderlyingCapabilities cannot find it. Update
// NetworkCapabilities#mUnderlyingNetworks to an empty array, and it will be updated to
@@ -8213,8 +8436,7 @@
// 2. When a network connects, updateNetworkInfo propagates underlying network
// capabilities before rematching networks.
// Given that this scenario can't really happen, this is probably fine for now.
- ce = callback.expect(NETWORK_CAPS_UPDATED, mMockVpn);
- final NetworkCapabilities vpnNc2 = ((CallbackEntry.CapabilitiesChanged) ce).getCaps();
+ final NetworkCapabilities vpnNc2 = callback.expectCaps(mMockVpn);
// The wifi network is brought up, NetworkCapabilities#mUnderlyingNetworks is updated to
// it.
underlyingNetwork.add(wifiNetwork);
@@ -8228,8 +8450,8 @@
// Disconnect the network, and expect to see the VPN capabilities change accordingly.
mWiFiAgent.disconnect();
callback.expect(LOST, mWiFiAgent);
- callback.expectCapabilitiesThat(mMockVpn, (nc) ->
- nc.getTransportTypes().length == 1 && nc.hasTransport(TRANSPORT_VPN));
+ callback.expectCaps(mMockVpn, c -> c.getTransportTypes().length == 1
+ && c.hasTransport(TRANSPORT_VPN));
mMockVpn.disconnect();
mCm.unregisterNetworkCallback(callback);
@@ -8255,9 +8477,8 @@
// Connect cellular data.
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellAgent.connect(false /* validated */);
- callback.expectCapabilitiesThat(mMockVpn,
- nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
- && nc.hasTransport(TRANSPORT_CELLULAR));
+ callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ && c.hasTransport(TRANSPORT_CELLULAR));
callback.assertNoCallback();
assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
@@ -8270,9 +8491,8 @@
// Suspend the cellular network and expect the VPN to be suspended.
mCellAgent.suspend();
- callback.expectCapabilitiesThat(mMockVpn,
- nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
- && nc.hasTransport(TRANSPORT_CELLULAR));
+ callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ && c.hasTransport(TRANSPORT_CELLULAR));
callback.expect(SUSPENDED, mMockVpn);
callback.assertNoCallback();
@@ -8288,9 +8508,8 @@
// Switch to another network. The VPN should no longer be suspended.
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiAgent.connect(false /* validated */);
- callback.expectCapabilitiesThat(mMockVpn,
- nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
- && nc.hasTransport(TRANSPORT_WIFI));
+ callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ && c.hasTransport(TRANSPORT_WIFI));
callback.expect(RESUMED, mMockVpn);
callback.assertNoCallback();
@@ -8306,13 +8525,11 @@
mCellAgent.resume();
callback.assertNoCallback();
mWiFiAgent.disconnect();
- callback.expectCapabilitiesThat(mMockVpn,
- nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
- && nc.hasTransport(TRANSPORT_CELLULAR));
+ callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ && c.hasTransport(TRANSPORT_CELLULAR));
// Spurious double callback?
- callback.expectCapabilitiesThat(mMockVpn,
- nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
- && nc.hasTransport(TRANSPORT_CELLULAR));
+ callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ && c.hasTransport(TRANSPORT_CELLULAR));
callback.assertNoCallback();
assertTrue(mCm.getNetworkCapabilities(mMockVpn.getNetwork())
@@ -8325,9 +8542,8 @@
// Suspend cellular and expect no connectivity.
mCellAgent.suspend();
- callback.expectCapabilitiesThat(mMockVpn,
- nc -> !nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
- && nc.hasTransport(TRANSPORT_CELLULAR));
+ callback.expectCaps(mMockVpn, c -> !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ && c.hasTransport(TRANSPORT_CELLULAR));
callback.expect(SUSPENDED, mMockVpn);
callback.assertNoCallback();
@@ -8341,9 +8557,8 @@
// Resume cellular and expect that connectivity comes back.
mCellAgent.resume();
- callback.expectCapabilitiesThat(mMockVpn,
- nc -> nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
- && nc.hasTransport(TRANSPORT_CELLULAR));
+ callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)
+ && c.hasTransport(TRANSPORT_CELLULAR));
callback.expect(RESUMED, mMockVpn);
callback.assertNoCallback();
@@ -8432,7 +8647,7 @@
// can't currently update their UIDs without disconnecting, so this does not matter too
// much, but that is the reason the test here has to check for an update to the
// capabilities instead of the expected LOST then AVAILABLE.
- defaultCallback.expect(NETWORK_CAPS_UPDATED, mMockVpn);
+ defaultCallback.expectCaps(mMockVpn);
systemDefaultCallback.assertNoCallback();
ranges.add(new UidRange(uid, uid));
@@ -8444,7 +8659,7 @@
vpnNetworkCallback.expectAvailableCallbacksValidated(mMockVpn);
// TODO : Here like above, AVAILABLE would be correct, but because this can't actually
// happen outside of the test, ConnectivityService does not rematch callbacks.
- defaultCallback.expect(NETWORK_CAPS_UPDATED, mMockVpn);
+ defaultCallback.expectCaps(mMockVpn);
systemDefaultCallback.assertNoCallback();
mWiFiAgent.disconnect();
@@ -8565,7 +8780,7 @@
mMockVpn.getAgent().mNetworkMonitor.forceReevaluation(Process.myUid());
// Expect to see the validated capability, but no other changes, because the VPN is already
// the default network for the app.
- callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mMockVpn);
+ callback.expectCaps(mMockVpn, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
callback.assertNoCallback();
mMockVpn.disconnect();
@@ -8597,8 +8812,8 @@
vpnNetworkCallback.expectAvailableCallbacks(mMockVpn.getNetwork(),
false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS);
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn.getNetwork(), TIMEOUT_MS,
- nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED));
+ vpnNetworkCallback.expectCaps(mMockVpn.getNetwork(), TIMEOUT_MS,
+ c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
final NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
assertTrue(nc.hasTransport(TRANSPORT_VPN));
@@ -8660,11 +8875,12 @@
mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
- && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_CELLULAR)
+ && !c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+ && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
assertDefaultNetworkCapabilities(userId, mCellAgent);
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
@@ -8675,62 +8891,68 @@
mMockVpn.setUnderlyingNetworks(
new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
- && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_CELLULAR)
+ && c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+ && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
// Don't disconnect, but note the VPN is not using wifi any more.
mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
- && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_CELLULAR)
+ && !c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+ && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
// The return value of getDefaultNetworkCapabilitiesForUser always includes the default
// network (wifi) as well as the underlying networks (cell).
assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
// Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
mCellAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
- && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_CELLULAR)
+ && !c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+ && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
// Add NOT_SUSPENDED again and observe VPN is no longer suspended.
mCellAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
- && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_CELLULAR)
+ && !c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+ && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
vpnNetworkCallback.expect(RESUMED, mMockVpn);
// Use Wifi but not cell. Note the VPN is now unmetered and not suspended.
mMockVpn.setUnderlyingNetworks(new Network[] { mWiFiAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && caps.hasCapability(NET_CAPABILITY_NOT_METERED)
- && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && !c.hasTransport(TRANSPORT_CELLULAR)
+ && c.hasTransport(TRANSPORT_WIFI)
+ && c.hasCapability(NET_CAPABILITY_NOT_METERED)
+ && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
assertDefaultNetworkCapabilities(userId, mWiFiAgent);
// Use both again.
mMockVpn.setUnderlyingNetworks(
new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
- && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_CELLULAR)
+ && c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+ && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
// Cell is suspended again. As WiFi is not, this should not cause a callback.
@@ -8739,11 +8961,11 @@
// Stop using WiFi. The VPN is suspended again.
mMockVpn.setUnderlyingNetworks(new Network[] { mCellAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_CELLULAR)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
- && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_CELLULAR)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+ && !c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
vpnNetworkCallback.expect(SUSPENDED, mMockVpn);
assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
@@ -8751,29 +8973,32 @@
mMockVpn.setUnderlyingNetworks(
new Network[] { mCellAgent.getNetwork(), mWiFiAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
- && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_CELLULAR)
+ && c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED)
+ && c.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
vpnNetworkCallback.expect(RESUMED, mMockVpn);
assertDefaultNetworkCapabilities(userId, mCellAgent, mWiFiAgent);
// Disconnect cell. Receive update without even removing the dead network from the
// underlying networks – it's dead anyway. Not metered any more.
mCellAgent.disconnect();
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && !c.hasTransport(TRANSPORT_CELLULAR)
+ && c.hasTransport(TRANSPORT_WIFI)
+ && c.hasCapability(NET_CAPABILITY_NOT_METERED));
assertDefaultNetworkCapabilities(userId, mWiFiAgent);
// Disconnect wifi too. No underlying networks means this is now metered.
mWiFiAgent.disconnect();
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && !c.hasTransport(TRANSPORT_CELLULAR)
+ && !c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
// When a network disconnects, the callbacks are fired before all state is updated, so for a
// short time, synchronous calls will behave as if the network is still connected. Wait for
// things to settle.
@@ -8814,20 +9039,22 @@
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellAgent.connect(true);
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_CELLULAR)
+ && !c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
// Connect to WiFi; WiFi is the new default.
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiAgent.connect(true);
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && !c.hasTransport(TRANSPORT_CELLULAR)
+ && c.hasTransport(TRANSPORT_WIFI)
+ && c.hasCapability(NET_CAPABILITY_NOT_METERED));
// Disconnect Cell. The default network did not change, so there shouldn't be any changes in
// the capabilities.
@@ -8836,10 +9063,11 @@
// Disconnect wifi too. Now we have no default network.
mWiFiAgent.disconnect();
- vpnNetworkCallback.expectCapabilitiesThat(mMockVpn,
- (caps) -> caps.hasTransport(TRANSPORT_VPN)
- && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ vpnNetworkCallback.expectCaps(mMockVpn,
+ c -> c.hasTransport(TRANSPORT_VPN)
+ && !c.hasTransport(TRANSPORT_CELLULAR)
+ && !c.hasTransport(TRANSPORT_WIFI)
+ && !c.hasCapability(NET_CAPABILITY_NOT_METERED));
mMockVpn.disconnect();
}
@@ -8855,6 +9083,14 @@
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerNetworkCallback(request, callback);
+ // File a VPN request to prevent VPN network being lingered.
+ final NetworkRequest vpnRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_VPN)
+ .removeCapability(NET_CAPABILITY_NOT_VPN)
+ .build();
+ final TestNetworkCallback vpnCallback = new TestNetworkCallback();
+ mCm.requestNetwork(vpnRequest, vpnCallback);
+
// Bring up a VPN
mMockVpn.establishForMyUid();
assertUidRangesUpdatedForMyUid(true);
@@ -8871,11 +9107,9 @@
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
- callback.expectCapabilitiesThat(mMockVpn, (caps)
- -> caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_WIFI));
- callback.expectCapabilitiesThat(mWiFiAgent, (caps)
- -> caps.hasCapability(NET_CAPABILITY_VALIDATED));
+ callback.expectCaps(mMockVpn, c -> c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_WIFI));
+ callback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
doReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)).when(mPackageManager)
.getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER);
@@ -8886,35 +9120,38 @@
// Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
// restricted user.
final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
- final Range<Integer> restrictUidRange = new Range<Integer>(rRange.start, rRange.stop);
- final Range<Integer> singleUidRange = new Range<Integer>(uid, uid);
- callback.expectCapabilitiesThat(mMockVpn, (caps)
- -> caps.getUids().size() == 2
- && caps.getUids().contains(singleUidRange)
- && caps.getUids().contains(restrictUidRange)
- && caps.hasTransport(TRANSPORT_VPN)
- && caps.hasTransport(TRANSPORT_WIFI));
+ final Range<Integer> restrictUidRange = new Range<>(rRange.start, rRange.stop);
+ final Range<Integer> singleUidRange = new Range<>(uid, uid);
+ callback.expectCaps(mMockVpn, c ->
+ c.getUids().size() == 2
+ && c.getUids().contains(singleUidRange)
+ && c.getUids().contains(restrictUidRange)
+ && c.hasTransport(TRANSPORT_VPN)
+ && c.hasTransport(TRANSPORT_WIFI));
// Change the VPN's capabilities somehow (specifically, disconnect wifi).
mWiFiAgent.disconnect();
callback.expect(LOST, mWiFiAgent);
- callback.expectCapabilitiesThat(mMockVpn, (caps)
- -> caps.getUids().size() == 2
- && caps.getUids().contains(singleUidRange)
- && caps.getUids().contains(restrictUidRange)
- && caps.hasTransport(TRANSPORT_VPN)
- && !caps.hasTransport(TRANSPORT_WIFI));
+ callback.expectCaps(mMockVpn, c ->
+ c.getUids().size() == 2
+ && c.getUids().contains(singleUidRange)
+ && c.getUids().contains(restrictUidRange)
+ && c.hasTransport(TRANSPORT_VPN)
+ && !c.hasTransport(TRANSPORT_WIFI));
// User removed and expect to lose the UID range for the restricted user.
mMockVpn.onUserRemoved(RESTRICTED_USER);
// Expect that the VPN gains the UID range for the restricted user, and that the capability
// change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
- callback.expectCapabilitiesThat(mMockVpn, (caps)
- -> caps.getUids().size() == 1
- && caps.getUids().contains(singleUidRange)
- && caps.hasTransport(TRANSPORT_VPN)
- && !caps.hasTransport(TRANSPORT_WIFI));
+ callback.expectCaps(mMockVpn, c ->
+ c.getUids().size() == 1
+ && c.getUids().contains(singleUidRange)
+ && c.hasTransport(TRANSPORT_VPN)
+ && !c.hasTransport(TRANSPORT_WIFI));
+
+ mCm.unregisterNetworkCallback(callback);
+ mCm.unregisterNetworkCallback(vpnCallback);
}
@Test
@@ -9162,11 +9399,6 @@
public void expectAvailableThenValidatedCallbacks(HasNetwork n, int blockedStatus) {
super.expectAvailableThenValidatedCallbacks(n.getNetwork(), blockedStatus, TIMEOUT_MS);
}
- public void expectBlockedStatusCallback(HasNetwork n, int blockedStatus) {
- // This doesn't work:
- // super.expectBlockedStatusCallback(blockedStatus, n.getNetwork());
- super.expectBlockedStatusCallback(blockedStatus, n.getNetwork(), TIMEOUT_MS);
- }
public void onBlockedStatusChanged(Network network, int blockedReasons) {
getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
}
@@ -9194,8 +9426,9 @@
assertExtraInfoFromCmPresent(mCellAgent);
setBlockedReasonChanged(BLOCKED_REASON_BATTERY_SAVER);
- cellNetworkCallback.expectBlockedStatusCallback(true, mCellAgent);
- detailedCallback.expectBlockedStatusCallback(mCellAgent, BLOCKED_REASON_BATTERY_SAVER);
+ cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+ detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+ cb -> cb.getReason() == BLOCKED_REASON_BATTERY_SAVER);
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
@@ -9204,21 +9437,23 @@
// If blocked state does not change but blocked reason does, the boolean callback is called.
// TODO: investigate de-duplicating.
setBlockedReasonChanged(BLOCKED_METERED_REASON_USER_RESTRICTED);
- cellNetworkCallback.expectBlockedStatusCallback(true, mCellAgent);
- detailedCallback.expectBlockedStatusCallback(mCellAgent,
- BLOCKED_METERED_REASON_USER_RESTRICTED);
+ cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+ detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+ cb -> cb.getReason() == BLOCKED_METERED_REASON_USER_RESTRICTED);
setBlockedReasonChanged(BLOCKED_REASON_NONE);
- cellNetworkCallback.expectBlockedStatusCallback(false, mCellAgent);
- detailedCallback.expectBlockedStatusCallback(mCellAgent, BLOCKED_REASON_NONE);
+ cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
+ detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+ cb -> cb.getReason() == BLOCKED_REASON_NONE);
assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
assertExtraInfoFromCmPresent(mCellAgent);
setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
- cellNetworkCallback.expectBlockedStatusCallback(true, mCellAgent);
- detailedCallback.expectBlockedStatusCallback(mCellAgent, BLOCKED_METERED_REASON_DATA_SAVER);
+ cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+ detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+ cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
@@ -9226,28 +9461,34 @@
// Restrict the network based on UID rule and NOT_METERED capability change.
mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
- cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellAgent);
- cellNetworkCallback.expectBlockedStatusCallback(false, mCellAgent);
- detailedCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellAgent);
- detailedCallback.expectBlockedStatusCallback(mCellAgent, BLOCKED_REASON_NONE);
+ cellNetworkCallback.expectCaps(mCellAgent,
+ c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
+ cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
+ detailedCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
+ detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+ cb -> cb.getReason() == BLOCKED_REASON_NONE);
assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
assertExtraInfoFromCmPresent(mCellAgent);
mCellAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
- cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mCellAgent);
- cellNetworkCallback.expectBlockedStatusCallback(true, mCellAgent);
- detailedCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mCellAgent);
- detailedCallback.expectBlockedStatusCallback(mCellAgent, BLOCKED_METERED_REASON_DATA_SAVER);
+ cellNetworkCallback.expectCaps(mCellAgent,
+ c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
+ cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+ detailedCallback.expectCaps(mCellAgent,
+ c -> !c.hasCapability(NET_CAPABILITY_NOT_METERED));
+ detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+ cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
assertExtraInfoFromCmBlocked(mCellAgent);
setBlockedReasonChanged(BLOCKED_REASON_NONE);
- cellNetworkCallback.expectBlockedStatusCallback(false, mCellAgent);
- detailedCallback.expectBlockedStatusCallback(mCellAgent, BLOCKED_REASON_NONE);
+ cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
+ detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+ cb -> cb.getReason() == BLOCKED_REASON_NONE);
assertEquals(mCellAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
@@ -9259,8 +9500,9 @@
// Restrict background data. Networking is not blocked because the network is unmetered.
setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
- cellNetworkCallback.expectBlockedStatusCallback(true, mCellAgent);
- detailedCallback.expectBlockedStatusCallback(mCellAgent, BLOCKED_METERED_REASON_DATA_SAVER);
+ cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> cb.getBlocked());
+ detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+ cb -> cb.getReason() == BLOCKED_METERED_REASON_DATA_SAVER);
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
@@ -9269,8 +9511,9 @@
cellNetworkCallback.assertNoCallback();
setBlockedReasonChanged(BLOCKED_REASON_NONE);
- cellNetworkCallback.expectBlockedStatusCallback(false, mCellAgent);
- detailedCallback.expectBlockedStatusCallback(mCellAgent, BLOCKED_REASON_NONE);
+ cellNetworkCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
+ detailedCallback.expect(BLOCKED_STATUS_INT, mCellAgent,
+ cb -> cb.getReason() == BLOCKED_REASON_NONE);
assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
assertExtraInfoFromCmPresent(mCellAgent);
@@ -9301,7 +9544,7 @@
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellAgent.connect(true);
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
- defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mCellAgent);
+ defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
// Allow to use the network after switching to NOT_METERED network.
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
@@ -9316,8 +9559,8 @@
// Network becomes NOT_METERED.
mCellAgent.addCapability(NET_CAPABILITY_NOT_METERED);
- defaultCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_METERED, mCellAgent);
- defaultCallback.expectBlockedStatusCallback(false, mCellAgent);
+ defaultCallback.expectCaps(mCellAgent, c -> c.hasCapability(NET_CAPABILITY_NOT_METERED));
+ defaultCallback.expect(BLOCKED_STATUS, mCellAgent, cb -> !cb.getBlocked());
// Verify there's no Networkcallbacks invoked after data saver on/off.
setBlockedReasonChanged(BLOCKED_METERED_REASON_DATA_SAVER);
@@ -9458,8 +9701,8 @@
// Disable lockdown, expect to see the network unblocked.
mMockVpn.setAlwaysOnPackage(null, false /* lockdown */, allowList);
- callback.expectBlockedStatusCallback(false, mWiFiAgent);
- defaultCallback.expectBlockedStatusCallback(false, mWiFiAgent);
+ callback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
+ defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
vpnDefaultCallbackAsUid.assertNoCallback();
@@ -9517,7 +9760,7 @@
mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
waitForIdle();
expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
- defaultCallback.expectBlockedStatusCallback(true, mWiFiAgent);
+ defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
@@ -9530,7 +9773,7 @@
// Disable lockdown. Everything is unblocked.
mMockVpn.setAlwaysOnPackage(null, false /* lockdown */, allowList);
- defaultCallback.expectBlockedStatusCallback(false, mWiFiAgent);
+ defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> !cb.getBlocked());
assertBlockedCallbackInAnyOrder(callback, false, mWiFiAgent, mCellAgent);
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
@@ -9571,7 +9814,7 @@
// Enable lockdown and connect a VPN. The VPN is not blocked.
mMockVpn.setAlwaysOnPackage(ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
- defaultCallback.expectBlockedStatusCallback(true, mWiFiAgent);
+ defaultCallback.expect(BLOCKED_STATUS, mWiFiAgent, cb -> cb.getBlocked());
assertBlockedCallbackInAnyOrder(callback, true, mWiFiAgent, mCellAgent);
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
@@ -9886,12 +10129,13 @@
callback.expect(LOST, mWiFiAgent);
systemDefaultCallback.expect(LOST, mWiFiAgent);
b1.expectBroadcast();
- callback.expectCapabilitiesThat(mMockVpn, nc -> !nc.hasTransport(TRANSPORT_WIFI));
+ callback.expectCaps(mMockVpn, c -> !c.hasTransport(TRANSPORT_WIFI));
mMockVpn.expectStopVpnRunnerPrivileged();
callback.expect(LOST, mMockVpn);
b2.expectBroadcast();
VMSHandlerThread.quitSafely();
+ VMSHandlerThread.join();
}
@Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
@@ -10055,7 +10299,7 @@
// changes back to cellular.
mWiFiAgent.removeCapability(testCap);
callbackWithCap.expectAvailableCallbacksValidated(mCellAgent);
- callbackWithoutCap.expectCapabilitiesWithout(testCap, mWiFiAgent);
+ callbackWithoutCap.expectCaps(mWiFiAgent, c -> !c.hasCapability(testCap));
verify(mMockNetd).networkSetDefault(eq(mCellAgent.getNetwork().netId));
reset(mMockNetd);
@@ -10325,19 +10569,19 @@
// Expect clatd to be stopped and started with the new prefix.
mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
cellNetId, PREFIX_OPERATION_ADDED, kOtherNat64PrefixString, 96));
- networkCallback.expectLinkPropertiesThat(mCellAgent,
- (lp) -> lp.getStackedLinks().size() == 0);
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ cb -> cb.getLp().getStackedLinks().size() == 0);
verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
assertRoutesRemoved(cellNetId, stackedDefault);
verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId,
kOtherNat64Prefix.toString());
- networkCallback.expectLinkPropertiesThat(mCellAgent,
- (lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix));
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ cb -> cb.getLp().getNat64Prefix().equals(kOtherNat64Prefix));
clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
- networkCallback.expectLinkPropertiesThat(mCellAgent,
- (lp) -> lp.getStackedLinks().size() == 1);
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ cb -> cb.getLp().getStackedLinks().size() == 1);
assertRoutesAdded(cellNetId, stackedDefault);
verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
reset(mMockNetd);
@@ -10378,7 +10622,8 @@
// Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
cellNetId, PREFIX_OPERATION_REMOVED, kOtherNat64PrefixString, 96));
- networkCallback.expectLinkPropertiesThat(mCellAgent, lp -> lp.getNat64Prefix() == null);
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ cb -> cb.getLp().getNat64Prefix() == null);
// Remove IPv4 address and expect prefix discovery and clatd to be started again.
cellLp.removeLinkAddress(myIpv4);
@@ -10395,22 +10640,24 @@
// Clat iface comes up. Expect stacked link to be added.
clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true);
- networkCallback.expectLinkPropertiesThat(mCellAgent,
- lp -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ cb -> cb.getLp().getStackedLinks().size() == 1
+ && cb.getLp().getNat64Prefix() != null);
assertRoutesAdded(cellNetId, stackedDefault);
verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
// NAT64 prefix is removed. Expect that clat is stopped.
mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent(
cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96));
- networkCallback.expectLinkPropertiesThat(mCellAgent,
- lp -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ cb -> cb.getLp().getStackedLinks().size() == 0
+ && cb.getLp().getNat64Prefix() == null);
assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
// Stop has no effect because clat is already stopped.
verifyClatdStop(null /* inOrder */, MOBILE_IFNAME);
- networkCallback.expectLinkPropertiesThat(mCellAgent,
- lp -> lp.getStackedLinks().size() == 0);
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ cb -> cb.getLp().getStackedLinks().size() == 0);
verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_MOBILE_IFNAME);
verify(mMockNetd, times(1)).interfaceGetCfg(CLAT_MOBILE_IFNAME);
// Clean up.
@@ -10420,7 +10667,11 @@
verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_CELLULAR)));
verify(mMockNetd).networkDestroy(cellNetId);
- verify(mMockNetd).setNetworkAllowlist(any());
+ if (SdkLevel.isAtLeastU()) {
+ verify(mMockNetd).setNetworkAllowlist(any());
+ } else {
+ verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
verifyNoMoreInteractions(mMockNetd);
verifyNoMoreInteractions(mClatCoordinator);
reset(mMockNetd);
@@ -10444,9 +10695,9 @@
verifyClatdStart(null /* inOrder */, MOBILE_IFNAME, cellNetId, kNat64Prefix.toString());
clat = getNat464Xlat(mCellAgent);
clat.interfaceLinkStateChanged(CLAT_MOBILE_IFNAME, true /* up */);
- networkCallback.expectLinkPropertiesThat(mCellAgent,
- lp -> lp.getStackedLinks().size() == 1
- && lp.getNat64Prefix().equals(kNat64Prefix));
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ cb -> cb.getLp().getStackedLinks().size() == 1
+ && cb.getLp().getNat64Prefix().equals(kNat64Prefix));
verify(mMockNetd).networkAddInterface(cellNetId, CLAT_MOBILE_IFNAME);
// assertRoutesAdded sees all calls since last mMockNetd reset, so expect IPv6 routes again.
assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default, stackedDefault);
@@ -10461,7 +10712,11 @@
verify(mMockNetd).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_CELLULAR)));
verify(mMockNetd).networkDestroy(cellNetId);
- verify(mMockNetd).setNetworkAllowlist(any());
+ if (SdkLevel.isAtLeastU()) {
+ verify(mMockNetd).setNetworkAllowlist(any());
+ } else {
+ verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
verifyNoMoreInteractions(mMockNetd);
verifyNoMoreInteractions(mClatCoordinator);
@@ -10470,7 +10725,8 @@
private void expectNat64PrefixChange(TestNetworkCallback callback,
TestNetworkAgentWrapper agent, IpPrefix prefix) {
- callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix));
+ callback.expect(LINK_PROPERTIES_CHANGED, agent,
+ x -> Objects.equals(x.getLp().getNat64Prefix(), prefix));
}
@Test
@@ -10705,7 +10961,7 @@
mWiFiAgent.connect(true);
networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
networkCallback.expectLosing(mCellAgent);
- networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_WIFI)));
verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
@@ -10729,7 +10985,7 @@
mWiFiAgent.connect(true);
networkCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
networkCallback.expectLosing(mCellAgent);
- networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ networkCallback.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(),
eq(Integer.toString(TRANSPORT_WIFI)));
verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(),
@@ -11445,9 +11701,9 @@
// callback.
mWiFiAgent.setNetworkCapabilities(ncTemplate.setTransportInfo(actualTransportInfo), true);
- wifiNetworkCallback.expectCapabilitiesThat(mWiFiAgent,
- nc -> Objects.equals(expectedOwnerUid, nc.getOwnerUid())
- && Objects.equals(expectedTransportInfo, nc.getTransportInfo()));
+ wifiNetworkCallback.expectCaps(mWiFiAgent,
+ c -> Objects.equals(expectedOwnerUid, c.getOwnerUid())
+ && Objects.equals(expectedTransportInfo, c.getTransportInfo()));
}
@Test
@@ -12109,7 +12365,8 @@
lp.addRoute(rio1);
lp.addRoute(defaultRoute);
mCellAgent.sendLinkProperties(lp);
- networkCallback.expectLinkPropertiesThat(mCellAgent, x -> x.getRoutes().size() == 3);
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ x -> x.getLp().getRoutes().size() == 3);
assertRoutesAdded(netId, direct, rio1, defaultRoute);
reset(mMockNetd);
@@ -12124,7 +12381,8 @@
assertTrue(lp.getRoutes().contains(defaultWithMtu));
mCellAgent.sendLinkProperties(lp);
- networkCallback.expectLinkPropertiesThat(mCellAgent, x -> x.getRoutes().contains(rio2));
+ networkCallback.expect(LINK_PROPERTIES_CHANGED, mCellAgent,
+ x -> x.getLp().getRoutes().contains(rio2));
assertRoutesRemoved(netId, rio1);
assertRoutesAdded(netId, rio2);
@@ -12241,7 +12499,7 @@
assertNull(mService.getProxyForNetwork(null));
assertNull(mCm.getDefaultProxy());
- final ExpectedBroadcast b1 = registerPacProxyBroadcast();
+ final ExpectedBroadcast b1 = expectProxyChangeAction();
final LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
@@ -12254,7 +12512,7 @@
b1.expectNoBroadcast(500);
// Update to new range which is old range minus APP1, i.e. only APP2
- final ExpectedBroadcast b2 = registerPacProxyBroadcast();
+ final ExpectedBroadcast b2 = expectProxyChangeAction();
final Set<UidRange> newRanges = new HashSet<>(asList(
new UidRange(vpnRange.start, APP1_UID - 1),
new UidRange(APP1_UID + 1, vpnRange.stop)));
@@ -12268,20 +12526,20 @@
b2.expectNoBroadcast(500);
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
- final ExpectedBroadcast b3 = registerPacProxyBroadcast();
+ final ExpectedBroadcast b3 = expectProxyChangeAction();
lp.setHttpProxy(testProxyInfo);
mMockVpn.sendLinkProperties(lp);
waitForIdle();
// Proxy is set, so send a proxy broadcast.
b3.expectBroadcast();
- final ExpectedBroadcast b4 = registerPacProxyBroadcast();
+ final ExpectedBroadcast b4 = expectProxyChangeAction();
mMockVpn.setUids(vpnRanges);
waitForIdle();
// Uid has changed and proxy is already set, so send a proxy broadcast.
b4.expectBroadcast();
- final ExpectedBroadcast b5 = registerPacProxyBroadcast();
+ final ExpectedBroadcast b5 = expectProxyChangeAction();
// Proxy is removed, send a proxy broadcast.
lp.setHttpProxy(null);
mMockVpn.sendLinkProperties(lp);
@@ -12314,7 +12572,7 @@
lp.setHttpProxy(testProxyInfo);
final UidRange vpnRange = PRIMARY_UIDRANGE;
final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
- final ExpectedBroadcast b1 = registerPacProxyBroadcast();
+ final ExpectedBroadcast b1 = expectProxyChangeAction();
mMockVpn.setOwnerAndAdminUid(VPN_UID);
mMockVpn.registerAgent(false, vpnRanges, lp);
// In any case, the proxy broadcast won't be sent before VPN goes into CONNECTED state.
@@ -12322,7 +12580,7 @@
// proxy broadcast will get null.
b1.expectNoBroadcast(500);
- final ExpectedBroadcast b2 = registerPacProxyBroadcast();
+ final ExpectedBroadcast b2 = expectProxyChangeAction();
mMockVpn.connect(true /* validated */, true /* hasInternet */,
false /* privateDnsProbeSent */);
waitForIdle();
@@ -12358,7 +12616,7 @@
final LinkProperties cellularLp = new LinkProperties();
cellularLp.setInterfaceName(MOBILE_IFNAME);
final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
- final ExpectedBroadcast b = registerPacProxyBroadcast();
+ final ExpectedBroadcast b = expectProxyChangeAction();
cellularLp.setHttpProxy(testProxyInfo);
mCellAgent.sendLinkProperties(cellularLp);
b.expectBroadcast();
@@ -12403,7 +12661,7 @@
// sees the network come up and validate later
allNetworksCb.expectAvailableCallbacksUnvalidated(mWiFiAgent);
allNetworksCb.expectLosing(mCellAgent);
- allNetworksCb.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiAgent);
+ allNetworksCb.expectCaps(mWiFiAgent, c -> c.hasCapability(NET_CAPABILITY_VALIDATED));
allNetworksCb.expect(LOST, mCellAgent, TEST_LINGER_DELAY_MS * 2);
// The cell network has disconnected (see LOST above) because it was outscored and
@@ -14428,10 +14686,10 @@
mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent);
mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
- mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellAgent, nc ->
- nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
- mDefaultNetworkCallback.expectCapabilitiesThat(mCellAgent, nc ->
- nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
+ c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ mDefaultNetworkCallback.expectCaps(mCellAgent,
+ c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
// default callbacks will be unregistered in tearDown
}
@@ -14818,20 +15076,19 @@
// not to the other apps.
workAgent.setNetworkValid(true /* privateDnsProbeSent */);
workAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
- profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent,
- nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)
- && nc.hasCapability(NET_CAPABILITY_ENTERPRISE)
- && nc.hasEnterpriseId(
- profileNetworkPreference.getPreferenceEnterpriseId())
- && nc.getEnterpriseIds().length == 1);
+ profileDefaultNetworkCallback.expectCaps(workAgent,
+ c -> c.hasCapability(NET_CAPABILITY_VALIDATED)
+ && c.hasCapability(NET_CAPABILITY_ENTERPRISE)
+ && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
+ && c.getEnterpriseIds().length == 1);
if (disAllowProfileDefaultNetworkCallback != null) {
assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
}
assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
- profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, nc ->
- nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ profileDefaultNetworkCallback.expectCaps(workAgent,
+ c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
if (disAllowProfileDefaultNetworkCallback != null) {
assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
}
@@ -14840,13 +15097,13 @@
// Conversely, change a capability on the system-wide default network and make sure
// that only the apps outside of the work profile receive the callbacks.
mCellAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
- mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellAgent, nc ->
- nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
- mDefaultNetworkCallback.expectCapabilitiesThat(mCellAgent, nc ->
- nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ mSystemDefaultNetworkCallback.expectCaps(mCellAgent,
+ c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ mDefaultNetworkCallback.expectCaps(mCellAgent,
+ c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
if (disAllowProfileDefaultNetworkCallback != null) {
- disAllowProfileDefaultNetworkCallback.expectCapabilitiesThat(mCellAgent, nc ->
- nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ disAllowProfileDefaultNetworkCallback.expectCaps(mCellAgent,
+ c -> c.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
}
profileDefaultNetworkCallback.assertNoCallback();
@@ -14928,12 +15185,11 @@
workAgent2.setNetworkValid(true /* privateDnsProbeSent */);
workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid());
- profileDefaultNetworkCallback.expectCapabilitiesThat(workAgent2,
- nc -> nc.hasCapability(NET_CAPABILITY_ENTERPRISE)
- && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
- && nc.hasEnterpriseId(
- profileNetworkPreference.getPreferenceEnterpriseId())
- && nc.getEnterpriseIds().length == 1);
+ profileDefaultNetworkCallback.expectCaps(workAgent2,
+ c -> c.hasCapability(NET_CAPABILITY_ENTERPRISE)
+ && !c.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ && c.hasEnterpriseId(profileNetworkPreference.getPreferenceEnterpriseId())
+ && c.getEnterpriseIds().length == 1);
if (disAllowProfileDefaultNetworkCallback != null) {
assertNoCallbacks(disAllowProfileDefaultNetworkCallback);
}
@@ -15771,7 +16027,11 @@
mCellAgent.getNetwork().netId,
toUidRangeStableParcels(allowedRanges),
0 /* subPriority */);
- inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[] { config1User });
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config1User});
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
doReturn(asList(PRIMARY_USER_HANDLE, SECONDARY_USER_HANDLE))
.when(mUserManager).getUserHandles(anyBoolean());
@@ -15785,7 +16045,11 @@
mCellAgent.getNetwork().netId,
toUidRangeStableParcels(allowedRanges),
0 /* subPriority */);
- inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[] { config2Users });
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{config2Users});
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
}
@Test
@@ -15812,8 +16076,12 @@
mCellAgent.getNetwork().netId,
allowAllUidRangesParcel,
0 /* subPriority */);
- inOrder.verify(mMockNetd).setNetworkAllowlist(
- new NativeUidRangeConfig[]{cellAllAllowedConfig});
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(
+ new NativeUidRangeConfig[]{cellAllAllowedConfig});
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
// Verify the same uid ranges are also applied for enterprise network.
final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
@@ -15827,9 +16095,13 @@
// making the order of the list undeterministic. Thus, verify this in order insensitive way.
final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
NativeUidRangeConfig[].class);
- inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
- assertContainsAll(List.of(configsCaptor.getValue()),
- List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+ assertContainsAll(List.of(configsCaptor.getValue()),
+ List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
// Setup profile preference which only applies to test app uid on the managed profile.
ProfileNetworkPreference.Builder prefBuilder = new ProfileNetworkPreference.Builder();
@@ -15857,24 +16129,36 @@
mCellAgent.getNetwork().netId,
excludeAppRangesParcel,
0 /* subPriority */);
- inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
- assertContainsAll(List.of(configsCaptor.getValue()),
- List.of(cellExcludeAppConfig, enterpriseAllAllowedConfig));
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+ assertContainsAll(List.of(configsCaptor.getValue()),
+ List.of(cellExcludeAppConfig, enterpriseAllAllowedConfig));
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
// Verify unset by giving all allowed set for all users when the preference got removed.
mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
r -> r.run(), listener);
listener.expectOnComplete();
- inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
- assertContainsAll(List.of(configsCaptor.getValue()),
- List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+ assertContainsAll(List.of(configsCaptor.getValue()),
+ List.of(cellAllAllowedConfig, enterpriseAllAllowedConfig));
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
// Verify issuing with cellular set only when a network with enterprise capability
// disconnects.
enterpriseAgent.disconnect();
waitForIdle();
- inOrder.verify(mMockNetd).setNetworkAllowlist(
- new NativeUidRangeConfig[]{cellAllAllowedConfig});
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(
+ new NativeUidRangeConfig[]{cellAllAllowedConfig});
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
}
@Test
@@ -15894,7 +16178,11 @@
List.of(prefBuilder.build()),
r -> r.run(), listener);
listener.expectOnComplete();
- inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
// Start with 1 default network, which should be restricted since the blocking
// preference is already set.
@@ -15918,8 +16206,12 @@
mCellAgent.getNetwork().netId,
excludeAppRangesParcel,
0 /* subPriority */);
- inOrder.verify(mMockNetd).setNetworkAllowlist(
- new NativeUidRangeConfig[]{cellExcludeAppConfig});
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(
+ new NativeUidRangeConfig[]{cellExcludeAppConfig});
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
// Verify enterprise network is not blocked for test app.
final TestNetworkAgentWrapper enterpriseAgent = makeEnterpriseNetworkAgent(
@@ -15938,19 +16230,31 @@
// making the order of the list undeterministic. Thus, verify this in order insensitive way.
final ArgumentCaptor<NativeUidRangeConfig[]> configsCaptor = ArgumentCaptor.forClass(
NativeUidRangeConfig[].class);
- inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
- assertContainsAll(List.of(configsCaptor.getValue()),
- List.of(enterpriseAllAllowedConfig, cellExcludeAppConfig));
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(configsCaptor.capture());
+ assertContainsAll(List.of(configsCaptor.getValue()),
+ List.of(enterpriseAllAllowedConfig, cellExcludeAppConfig));
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
// Verify issuing with cellular set only when enterprise network disconnects.
enterpriseAgent.disconnect();
waitForIdle();
- inOrder.verify(mMockNetd).setNetworkAllowlist(
- new NativeUidRangeConfig[]{cellExcludeAppConfig});
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(
+ new NativeUidRangeConfig[]{cellExcludeAppConfig});
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
mCellAgent.disconnect();
waitForIdle();
- inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
+ if (SdkLevel.isAtLeastU()) {
+ inOrder.verify(mMockNetd).setNetworkAllowlist(new NativeUidRangeConfig[]{});
+ } else {
+ inOrder.verify(mMockNetd, never()).setNetworkAllowlist(any());
+ }
}
/**
@@ -16119,7 +16423,7 @@
nc.setAllowedUids(uids);
agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
if (SdkLevel.isAtLeastT()) {
- cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().equals(uids));
+ cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
} else {
cb.assertNoCallback();
}
@@ -16136,7 +16440,7 @@
nc.setAllowedUids(uids);
agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
if (SdkLevel.isAtLeastT()) {
- cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().equals(uids));
+ cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids200Parcel);
} else {
cb.assertNoCallback();
@@ -16147,7 +16451,7 @@
nc.setAllowedUids(uids);
agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
if (SdkLevel.isAtLeastT()) {
- cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().equals(uids));
+ cb.expectCaps(agent, c -> c.getAllowedUids().equals(uids));
} else {
cb.assertNoCallback();
}
@@ -16164,7 +16468,7 @@
nc.setAllowedUids(uids);
agent.setNetworkCapabilities(nc, true /* sendToConnectivityService */);
if (SdkLevel.isAtLeastT()) {
- cb.expectCapabilitiesThat(agent, caps -> caps.getAllowedUids().isEmpty());
+ cb.expectCaps(agent, c -> c.getAllowedUids().isEmpty());
inOrder.verify(mMockNetd, times(1)).networkRemoveUidRangesParcel(uids600Parcel);
} else {
cb.assertNoCallback();
@@ -16217,8 +16521,7 @@
ncb.setAllowedUids(serviceUidSet);
mEthernetAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
if (SdkLevel.isAtLeastT() && hasAutomotiveFeature) {
- cb.expectCapabilitiesThat(mEthernetAgent,
- caps -> caps.getAllowedUids().equals(serviceUidSet));
+ cb.expectCaps(mEthernetAgent, c -> c.getAllowedUids().equals(serviceUidSet));
} else {
// S and no automotive feature must ignore access UIDs.
cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
@@ -16271,7 +16574,7 @@
ncb.setAllowedUids(serviceUidSet);
mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
if (SdkLevel.isAtLeastT()) {
- cb.expectCapabilitiesThat(mCellAgent, cp -> cp.getAllowedUids().equals(serviceUidSet));
+ cb.expectCaps(mCellAgent, c -> c.getAllowedUids().equals(serviceUidSet));
} else {
// S must ignore access UIDs.
cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
@@ -16281,7 +16584,7 @@
ncb.setAllowedUids(nonServiceUidSet);
mCellAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
if (SdkLevel.isAtLeastT()) {
- cb.expectCapabilitiesThat(mCellAgent, cp -> cp.getAllowedUids().isEmpty());
+ cb.expectCaps(mCellAgent, c -> c.getAllowedUids().isEmpty());
} else {
// S must ignore access UIDs.
cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
@@ -16681,6 +16984,7 @@
} finally {
cellFactory.terminate();
handlerThread.quitSafely();
+ handlerThread.join();
}
}
@@ -17117,40 +17421,42 @@
mWiFiAgent.setNetworkCapabilities(wifiNc2, true /* sendToConnectivityService */);
// The only thing changed in this CAPS is the BSSID, which can't be tested for in this
// test because it's redacted.
- wifiNetworkCallback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
- mDefaultNetworkCallback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent);
+ mDefaultNetworkCallback.expectCaps(mWiFiAgent);
mWiFiAgent.setNetworkPortal(TEST_REDIRECT_URL, false /* privateDnsProbeSent */);
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
// Wi-Fi is now detected to have a portal : cell should become the default network.
mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
- wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiAgent);
- wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_CAPTIVE_PORTAL, mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent,
+ c -> !c.hasCapability(NET_CAPABILITY_VALIDATED));
+ wifiNetworkCallback.expectCaps(mWiFiAgent,
+ c -> c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
// Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
- wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_CAPTIVE_PORTAL,
- mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent,
+ c -> !c.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
// Wi-Fi roaming from wifiNc2 to wifiNc1, and the network now has partial connectivity.
mWiFiAgent.setNetworkCapabilities(wifiNc1, true);
- wifiNetworkCallback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
- mDefaultNetworkCallback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent);
+ mDefaultNetworkCallback.expectCaps(mWiFiAgent);
mWiFiAgent.setNetworkPartial();
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
// Wi-Fi now only offers partial connectivity, so in the absence of accepting partial
// connectivity explicitly for this network, it loses default status to cell.
mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellAgent);
- wifiNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
- mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent,
+ c -> c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
// Wi-Fi becomes valid again. The default network goes back to Wi-Fi.
mWiFiAgent.setNetworkValid(false /* privateDnsProbeSent */);
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), true);
mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiAgent);
- wifiNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
- mWiFiAgent);
+ wifiNetworkCallback.expectCaps(mWiFiAgent,
+ c -> !c.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
}
mCm.unregisterNetworkCallback(wifiNetworkCallback);
@@ -17158,7 +17464,7 @@
// failures after roam are not ignored, this will cause cell to become the default network.
// If they are ignored, this will not cause a switch until later.
mWiFiAgent.setNetworkCapabilities(wifiNc2, true);
- mDefaultNetworkCallback.expect(NETWORK_CAPS_UPDATED, mWiFiAgent);
+ mDefaultNetworkCallback.expectCaps(mWiFiAgent);
mWiFiAgent.setNetworkInvalid(false /* invalidBecauseOfPrivateDns */);
mCm.reportNetworkConnectivity(mWiFiAgent.getNetwork(), false);
diff --git a/tests/unit/java/com/android/server/IpSecServiceTest.java b/tests/unit/java/com/android/server/IpSecServiceTest.java
index 6955620..4b6857c 100644
--- a/tests/unit/java/com/android/server/IpSecServiceTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceTest.java
@@ -82,7 +82,7 @@
private static final int MAX_NUM_ENCAP_SOCKETS = 100;
private static final int MAX_NUM_SPIS = 100;
private static final int TEST_UDP_ENCAP_INVALID_PORT = 100;
- private static final int TEST_UDP_ENCAP_PORT_OUT_RANGE = 100000;
+ private static final int TEST_UDP_ENCAP_PORT_OUT_RANGE = 200000;
private static final InetAddress INADDR_ANY;
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 98a8ed2..2ed989e 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -17,10 +17,13 @@
package com.android.server;
import static android.net.InetAddresses.parseNumericAddress;
+import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_PLATFORM_MDNS_BACKEND;
+import static android.net.connectivity.ConnectivityCompatChanges.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER;
import static android.net.nsd.NsdManager.FAILURE_BAD_PARAMETERS;
import static android.net.nsd.NsdManager.FAILURE_INTERNAL_ERROR;
import static android.net.nsd.NsdManager.FAILURE_OPERATION_NOT_RUNNING;
+import static com.android.server.NsdService.constructServiceType;
import static com.android.testutils.ContextUtils.mockService;
import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
@@ -45,6 +48,7 @@
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.compat.testing.PlatformCompatChangeRule;
@@ -98,6 +102,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.List;
@@ -170,6 +175,9 @@
doReturn(true).when(mMockMDnsM).resolve(
anyInt(), anyString(), anyString(), anyString(), anyInt());
doReturn(false).when(mDeps).isMdnsDiscoveryManagerEnabled(any(Context.class));
+ doReturn(mDiscoveryManager).when(mDeps).makeMdnsDiscoveryManager(any(), any());
+ doReturn(mSocketProvider).when(mDeps).makeMdnsSocketProvider(any(), any());
+ doReturn(mAdvertiser).when(mDeps).makeMdnsAdvertiser(any(), any(), any());
mService = makeService();
}
@@ -183,7 +191,9 @@
}
@Test
- @DisableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @DisableCompatChanges({
+ RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER,
+ ENABLE_PLATFORM_MDNS_BACKEND})
public void testPreSClients() throws Exception {
// Pre S client connected, the daemon should be started.
connectClient(mService);
@@ -210,7 +220,8 @@
}
@Test
- @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @EnableCompatChanges(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testNoDaemonStartedWhenClientsConnect() throws Exception {
// Creating an NsdManager will not cause daemon startup.
connectClient(mService);
@@ -244,7 +255,8 @@
}
@Test
- @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @EnableCompatChanges(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testClientRequestsAreGCedAtDisconnection() throws Exception {
final NsdManager client = connectClient(mService);
final INsdManagerCallback cb1 = getCallback();
@@ -287,7 +299,8 @@
}
@Test
- @EnableCompatChanges(NsdManager.RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @EnableCompatChanges(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS_T_AND_LATER)
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testCleanupDelayNoRequestActive() throws Exception {
final NsdManager client = connectClient(mService);
@@ -323,6 +336,7 @@
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testDiscoverOnTetheringDownstream() throws Exception {
final NsdManager client = connectClient(mService);
final int interfaceIdx = 123;
@@ -413,6 +427,7 @@
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testDiscoverOnBlackholeNetwork() throws Exception {
final NsdManager client = connectClient(mService);
final DiscoveryListener discListener = mock(DiscoveryListener.class);
@@ -442,6 +457,7 @@
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testServiceRegistrationSuccessfulAndFailed() throws Exception {
final NsdManager client = connectClient(mService);
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
@@ -488,6 +504,7 @@
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testServiceDiscoveryFailed() throws Exception {
final NsdManager client = connectClient(mService);
final DiscoveryListener discListener = mock(DiscoveryListener.class);
@@ -514,6 +531,7 @@
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testServiceResolutionFailed() throws Exception {
final NsdManager client = connectClient(mService);
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
@@ -544,6 +562,7 @@
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testGettingAddressFailed() throws Exception {
final NsdManager client = connectClient(mService);
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
@@ -590,6 +609,7 @@
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testNoCrashWhenProcessResolutionAfterBinderDied() throws Exception {
final NsdManager client = connectClient(mService);
final INsdManagerCallback cb = getCallback();
@@ -609,6 +629,7 @@
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testStopServiceResolution() {
final NsdManager client = connectClient(mService);
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
@@ -625,12 +646,13 @@
waitForIdle();
verify(mMockMDnsM).stopOperation(resolveId);
- verify(resolveListener, timeout(TIMEOUT_MS)).onResolveStopped(argThat(ns ->
+ verify(resolveListener, timeout(TIMEOUT_MS)).onResolutionStopped(argThat(ns ->
request.getServiceName().equals(ns.getServiceName())
&& request.getServiceType().equals(ns.getServiceType())));
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testStopResolutionFailed() {
final NsdManager client = connectClient(mService);
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
@@ -655,6 +677,7 @@
}
@Test @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testStopResolutionDuringGettingAddress() throws RemoteException {
final NsdManager client = connectClient(mService);
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
@@ -692,125 +715,108 @@
waitForIdle();
verify(mMockMDnsM).stopOperation(getAddrId);
- verify(resolveListener, timeout(TIMEOUT_MS)).onResolveStopped(argThat(ns ->
+ verify(resolveListener, timeout(TIMEOUT_MS)).onResolutionStopped(argThat(ns ->
request.getServiceName().equals(ns.getServiceName())
&& request.getServiceType().equals(ns.getServiceType())));
}
private void verifyUpdatedServiceInfo(NsdServiceInfo info, String serviceName,
- String serviceType, String address, int port, int interfaceIndex, Network network) {
+ String serviceType, List<InetAddress> address, int port, int interfaceIndex,
+ Network network) {
assertEquals(serviceName, info.getServiceName());
assertEquals(serviceType, info.getServiceType());
- assertTrue(info.getHostAddresses().contains(parseNumericAddress(address)));
+ assertEquals(address, info.getHostAddresses());
assertEquals(port, info.getPort());
assertEquals(network, info.getNetwork());
assertEquals(interfaceIndex, info.getInterfaceIndex());
}
@Test
- public void testRegisterAndUnregisterServiceInfoCallback() throws RemoteException {
+ public void testRegisterAndUnregisterServiceInfoCallback() {
final NsdManager client = connectClient(mService);
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
final NsdManager.ServiceInfoCallback serviceInfoCallback = mock(
NsdManager.ServiceInfoCallback.class);
+ final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
+ final Network network = new Network(999);
+ request.setNetwork(network);
client.registerServiceInfoCallback(request, Runnable::run, serviceInfoCallback);
waitForIdle();
+ // Verify the registration callback start.
+ final ArgumentCaptor<MdnsServiceBrowserListener> listenerCaptor =
+ ArgumentCaptor.forClass(MdnsServiceBrowserListener.class);
+ verify(mSocketProvider).startMonitoringSockets();
+ verify(mDiscoveryManager).registerListener(eq(serviceTypeWithLocalDomain),
+ listenerCaptor.capture(), argThat(options -> network.equals(options.getNetwork())));
- final IMDnsEventListener eventListener = getEventListener();
- final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
- verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
- eq("local.") /* domain */, eq(IFACE_IDX_ANY));
-
- // Resolve service successfully.
- final ResolutionInfo resolutionInfo = new ResolutionInfo(
- resolvIdCaptor.getValue(),
- IMDnsEventListener.SERVICE_RESOLVED,
- null /* serviceName */,
- null /* serviceType */,
- null /* domain */,
- SERVICE_FULL_NAME,
- DOMAIN_NAME,
+ final MdnsServiceBrowserListener listener = listenerCaptor.getValue();
+ final MdnsServiceInfo mdnsServiceInfo = new MdnsServiceInfo(
+ SERVICE_NAME,
+ serviceTypeWithLocalDomain.split("\\."),
+ List.of(), /* subtypes */
+ new String[]{"android", "local"}, /* hostName */
PORT,
- new byte[0] /* txtRecord */,
- IFACE_IDX_ANY);
- doReturn(true).when(mMockMDnsM).getServiceAddress(anyInt(), any(), anyInt());
- eventListener.onServiceResolutionStatus(resolutionInfo);
- waitForIdle();
+ List.of(IPV4_ADDRESS),
+ List.of(IPV6_ADDRESS),
+ List.of() /* textStrings */,
+ List.of() /* textEntries */,
+ 1234,
+ network);
- final ArgumentCaptor<Integer> getAddrIdCaptor = ArgumentCaptor.forClass(Integer.class);
- verify(mMockMDnsM).getServiceAddress(getAddrIdCaptor.capture(), eq(DOMAIN_NAME),
- eq(IFACE_IDX_ANY));
-
- // First address info
- final String v4Address = "192.0.2.1";
- final String v6Address = "2001:db8::";
- final GetAddressInfo addressInfo1 = new GetAddressInfo(
- getAddrIdCaptor.getValue(),
- IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS,
- SERVICE_FULL_NAME,
- v4Address,
- IFACE_IDX_ANY,
- 999 /* netId */);
- eventListener.onGettingServiceAddressStatus(addressInfo1);
- waitForIdle();
-
+ // Verify onServiceFound callback
+ listener.onServiceFound(mdnsServiceInfo);
final ArgumentCaptor<NsdServiceInfo> updateInfoCaptor =
ArgumentCaptor.forClass(NsdServiceInfo.class);
verify(serviceInfoCallback, timeout(TIMEOUT_MS).times(1))
.onServiceUpdated(updateInfoCaptor.capture());
verifyUpdatedServiceInfo(updateInfoCaptor.getAllValues().get(0) /* info */, SERVICE_NAME,
- "." + SERVICE_TYPE, v4Address, PORT, IFACE_IDX_ANY, new Network(999));
+ SERVICE_TYPE,
+ List.of(parseNumericAddress(IPV4_ADDRESS), parseNumericAddress(IPV6_ADDRESS)),
+ PORT, IFACE_IDX_ANY, new Network(999));
- // Second address info
- final GetAddressInfo addressInfo2 = new GetAddressInfo(
- getAddrIdCaptor.getValue(),
- IMDnsEventListener.SERVICE_GET_ADDR_SUCCESS,
- SERVICE_FULL_NAME,
- v6Address,
- IFACE_IDX_ANY,
- 999 /* netId */);
- eventListener.onGettingServiceAddressStatus(addressInfo2);
- waitForIdle();
+ // Service addresses changed.
+ final String v4Address = "192.0.2.1";
+ final String v6Address = "2001:db8::1";
+ final MdnsServiceInfo updatedServiceInfo = new MdnsServiceInfo(
+ SERVICE_NAME,
+ serviceTypeWithLocalDomain.split("\\."),
+ List.of(), /* subtypes */
+ new String[]{"android", "local"}, /* hostName */
+ PORT,
+ List.of(v4Address),
+ List.of(v6Address),
+ List.of() /* textStrings */,
+ List.of() /* textEntries */,
+ 1234,
+ network);
+ // Verify onServiceUpdated callback.
+ listener.onServiceUpdated(updatedServiceInfo);
verify(serviceInfoCallback, timeout(TIMEOUT_MS).times(2))
.onServiceUpdated(updateInfoCaptor.capture());
- verifyUpdatedServiceInfo(updateInfoCaptor.getAllValues().get(1) /* info */, SERVICE_NAME,
- "." + SERVICE_TYPE, v6Address, PORT, IFACE_IDX_ANY, new Network(999));
+ verifyUpdatedServiceInfo(updateInfoCaptor.getAllValues().get(2) /* info */, SERVICE_NAME,
+ SERVICE_TYPE,
+ List.of(parseNumericAddress(v4Address), parseNumericAddress(v6Address)),
+ PORT, IFACE_IDX_ANY, new Network(999));
+ // Verify service callback unregistration.
client.unregisterServiceInfoCallback(serviceInfoCallback);
waitForIdle();
-
verify(serviceInfoCallback, timeout(TIMEOUT_MS)).onServiceInfoCallbackUnregistered();
}
@Test
- public void testRegisterServiceCallbackFailed() throws Exception {
+ public void testRegisterServiceCallbackFailed() {
final NsdManager client = connectClient(mService);
- final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
- final NsdManager.ServiceInfoCallback subscribeListener = mock(
+ final String invalidServiceType = "a_service";
+ final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, invalidServiceType);
+ final NsdManager.ServiceInfoCallback serviceInfoCallback = mock(
NsdManager.ServiceInfoCallback.class);
- client.registerServiceInfoCallback(request, Runnable::run, subscribeListener);
+ client.registerServiceInfoCallback(request, Runnable::run, serviceInfoCallback);
waitForIdle();
- final IMDnsEventListener eventListener = getEventListener();
- final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
- verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
- eq("local.") /* domain */, eq(IFACE_IDX_ANY));
-
- // Fail to resolve service.
- final ResolutionInfo resolutionFailedInfo = new ResolutionInfo(
- resolvIdCaptor.getValue(),
- IMDnsEventListener.SERVICE_RESOLUTION_FAILED,
- null /* serviceName */,
- null /* serviceType */,
- null /* domain */,
- null /* serviceFullName */,
- null /* domainName */,
- 0 /* port */,
- new byte[0] /* txtRecord */,
- IFACE_IDX_ANY);
- eventListener.onServiceResolutionStatus(resolutionFailedInfo);
- verify(subscribeListener, timeout(TIMEOUT_MS))
+ // Fail to register service callback.
+ verify(serviceInfoCallback, timeout(TIMEOUT_MS))
.onServiceInfoCallbackRegistrationFailed(eq(FAILURE_BAD_PARAMETERS));
}
@@ -824,40 +830,51 @@
client.unregisterServiceInfoCallback(serviceInfoCallback));
}
- private void makeServiceWithMdnsDiscoveryManagerEnabled() {
+ private void setMdnsDiscoveryManagerEnabled() {
doReturn(true).when(mDeps).isMdnsDiscoveryManagerEnabled(any(Context.class));
- doReturn(mDiscoveryManager).when(mDeps).makeMdnsDiscoveryManager(any(), any());
- doReturn(mSocketProvider).when(mDeps).makeMdnsSocketProvider(any(), any());
-
- mService = makeService();
- verify(mDeps).makeMdnsDiscoveryManager(any(), any());
- verify(mDeps).makeMdnsSocketProvider(any(), any());
}
- private void makeServiceWithMdnsAdvertiserEnabled() {
+ private void setMdnsAdvertiserEnabled() {
doReturn(true).when(mDeps).isMdnsAdvertiserEnabled(any(Context.class));
- doReturn(mAdvertiser).when(mDeps).makeMdnsAdvertiser(any(), any(), any());
- doReturn(mSocketProvider).when(mDeps).makeMdnsSocketProvider(any(), any());
-
- mService = makeService();
- verify(mDeps).makeMdnsAdvertiser(any(), any(), any());
- verify(mDeps).makeMdnsSocketProvider(any(), any());
}
@Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
public void testMdnsDiscoveryManagerFeature() {
// Create NsdService w/o feature enabled.
- connectClient(mService);
- verify(mDeps, never()).makeMdnsDiscoveryManager(any(), any());
- verify(mDeps, never()).makeMdnsSocketProvider(any(), any());
+ final NsdManager client = connectClient(mService);
+ final DiscoveryListener discListenerWithoutFeature = mock(DiscoveryListener.class);
+ client.discoverServices(SERVICE_TYPE, PROTOCOL, discListenerWithoutFeature);
+ waitForIdle();
- // Create NsdService again w/ feature enabled.
- makeServiceWithMdnsDiscoveryManagerEnabled();
+ final ArgumentCaptor<Integer> legacyIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).discover(legacyIdCaptor.capture(), any(), anyInt());
+ verifyNoMoreInteractions(mDiscoveryManager);
+
+ setMdnsDiscoveryManagerEnabled();
+ final DiscoveryListener discListenerWithFeature = mock(DiscoveryListener.class);
+ client.discoverServices(SERVICE_TYPE, PROTOCOL, discListenerWithFeature);
+ waitForIdle();
+
+ final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
+ final ArgumentCaptor<MdnsServiceBrowserListener> listenerCaptor =
+ ArgumentCaptor.forClass(MdnsServiceBrowserListener.class);
+ verify(mDiscoveryManager).registerListener(eq(serviceTypeWithLocalDomain),
+ listenerCaptor.capture(), any());
+
+ client.stopServiceDiscovery(discListenerWithoutFeature);
+ waitForIdle();
+ verify(mMockMDnsM).stopOperation(legacyIdCaptor.getValue());
+
+ client.stopServiceDiscovery(discListenerWithFeature);
+ waitForIdle();
+ verify(mDiscoveryManager).unregisterListener(serviceTypeWithLocalDomain,
+ listenerCaptor.getValue());
}
@Test
public void testDiscoveryWithMdnsDiscoveryManager() {
- makeServiceWithMdnsDiscoveryManagerEnabled();
+ setMdnsDiscoveryManagerEnabled();
final NsdManager client = connectClient(mService);
final DiscoveryListener discListener = mock(DiscoveryListener.class);
@@ -880,8 +897,8 @@
List.of(), /* subtypes */
new String[] {"android", "local"}, /* hostName */
12345, /* port */
- IPV4_ADDRESS,
- IPV6_ADDRESS,
+ List.of(IPV4_ADDRESS),
+ List.of(IPV6_ADDRESS),
List.of(), /* textStrings */
List.of(), /* textEntries */
1234, /* interfaceIndex */
@@ -900,8 +917,8 @@
null, /* subtypes */
null, /* hostName */
0, /* port */
- null, /* ipv4Address */
- null, /* ipv6Address */
+ List.of(), /* ipv4Address */
+ List.of(), /* ipv6Address */
null, /* textStrings */
null, /* textEntries */
1234, /* interfaceIndex */
@@ -917,12 +934,12 @@
waitForIdle();
verify(mDiscoveryManager).unregisterListener(eq(serviceTypeWithLocalDomain), any());
verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStopped(SERVICE_TYPE);
- verify(mSocketProvider, timeout(CLEANUP_DELAY_MS + TIMEOUT_MS)).stopMonitoringSockets();
+ verify(mSocketProvider, timeout(CLEANUP_DELAY_MS + TIMEOUT_MS)).requestStopWhenInactive();
}
@Test
public void testDiscoveryWithMdnsDiscoveryManager_FailedWithInvalidServiceType() {
- makeServiceWithMdnsDiscoveryManagerEnabled();
+ setMdnsDiscoveryManagerEnabled();
final NsdManager client = connectClient(mService);
final DiscoveryListener discListener = mock(DiscoveryListener.class);
@@ -951,7 +968,7 @@
@Test
public void testResolutionWithMdnsDiscoveryManager() throws UnknownHostException {
- makeServiceWithMdnsDiscoveryManagerEnabled();
+ setMdnsDiscoveryManagerEnabled();
final NsdManager client = connectClient(mService);
final ResolveListener resolveListener = mock(ResolveListener.class);
@@ -966,7 +983,9 @@
waitForIdle();
verify(mSocketProvider).startMonitoringSockets();
verify(mDiscoveryManager).registerListener(eq(constructedServiceType),
- listenerCaptor.capture(), argThat(options -> network.equals(options.getNetwork())));
+ listenerCaptor.capture(), argThat(options ->
+ network.equals(options.getNetwork())
+ && SERVICE_NAME.equals(options.getResolveInstanceName())));
final MdnsServiceBrowserListener listener = listenerCaptor.getValue();
final MdnsServiceInfo mdnsServiceInfo = new MdnsServiceInfo(
@@ -975,8 +994,8 @@
List.of(), /* subtypes */
new String[]{"android", "local"}, /* hostName */
PORT,
- IPV4_ADDRESS,
- IPV6_ADDRESS,
+ List.of(IPV4_ADDRESS),
+ List.of("2001:db8::1", "2001:db8::2"),
List.of() /* textStrings */,
List.of(MdnsServiceInfo.TextEntry.fromBytes(new byte[]{
'k', 'e', 'y', '=', (byte) 0xFF, (byte) 0xFE})) /* textEntries */,
@@ -996,17 +1015,107 @@
assertEquals(1, info.getAttributes().size());
assertArrayEquals(new byte[]{(byte) 0xFF, (byte) 0xFE}, info.getAttributes().get("key"));
assertEquals(parseNumericAddress(IPV4_ADDRESS), info.getHost());
+ assertEquals(3, info.getHostAddresses().size());
+ assertTrue(info.getHostAddresses().stream().anyMatch(
+ address -> address.equals(parseNumericAddress("2001:db8::1"))));
+ assertTrue(info.getHostAddresses().stream().anyMatch(
+ address -> address.equals(parseNumericAddress("2001:db8::2"))));
assertEquals(network, info.getNetwork());
// Verify the listener has been unregistered.
verify(mDiscoveryManager, timeout(TIMEOUT_MS))
.unregisterListener(eq(constructedServiceType), any());
- verify(mSocketProvider, timeout(CLEANUP_DELAY_MS + TIMEOUT_MS)).stopMonitoringSockets();
+ verify(mSocketProvider, timeout(CLEANUP_DELAY_MS + TIMEOUT_MS)).requestStopWhenInactive();
+ }
+
+ @Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
+ public void testMdnsAdvertiserFeatureFlagging() {
+ // Create NsdService w/o feature enabled.
+ final NsdManager client = connectClient(mService);
+ final NsdServiceInfo regInfo = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+ regInfo.setHost(parseNumericAddress("192.0.2.123"));
+ regInfo.setPort(12345);
+ final RegistrationListener regListenerWithoutFeature = mock(RegistrationListener.class);
+ client.registerService(regInfo, PROTOCOL, regListenerWithoutFeature);
+ waitForIdle();
+
+ final ArgumentCaptor<Integer> legacyIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).registerService(legacyIdCaptor.capture(), any(), any(), anyInt(),
+ any(), anyInt());
+ verifyNoMoreInteractions(mAdvertiser);
+
+ setMdnsAdvertiserEnabled();
+ final RegistrationListener regListenerWithFeature = mock(RegistrationListener.class);
+ client.registerService(regInfo, PROTOCOL, regListenerWithFeature);
+ waitForIdle();
+
+ final ArgumentCaptor<Integer> serviceIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mAdvertiser).addService(serviceIdCaptor.capture(),
+ argThat(info -> matches(info, regInfo)));
+
+ client.unregisterService(regListenerWithoutFeature);
+ waitForIdle();
+ verify(mMockMDnsM).stopOperation(legacyIdCaptor.getValue());
+ verify(mAdvertiser, never()).removeService(anyInt());
+
+ client.unregisterService(regListenerWithFeature);
+ waitForIdle();
+ verify(mAdvertiser).removeService(serviceIdCaptor.getValue());
+ }
+
+ @Test
+ @DisableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
+ public void testTypeSpecificFeatureFlagging() {
+ doReturn("_type1._tcp:flag1,_type2._tcp:flag2").when(mDeps).getTypeAllowlistFlags();
+ doReturn(true).when(mDeps).isFeatureEnabled(any(),
+ eq("mdns_discovery_manager_allowlist_flag1_version"));
+ doReturn(true).when(mDeps).isFeatureEnabled(any(),
+ eq("mdns_advertiser_allowlist_flag2_version"));
+
+ final NsdManager client = connectClient(mService);
+ final NsdServiceInfo service1 = new NsdServiceInfo(SERVICE_NAME, "_type1._tcp");
+ service1.setHostAddresses(List.of(parseNumericAddress("2001:db8::123")));
+ service1.setPort(1234);
+ final NsdServiceInfo service2 = new NsdServiceInfo(SERVICE_NAME, "_type2._tcp");
+ service2.setHostAddresses(List.of(parseNumericAddress("2001:db8::123")));
+ service2.setPort(1234);
+
+ client.discoverServices(service1.getServiceType(),
+ NsdManager.PROTOCOL_DNS_SD, mock(DiscoveryListener.class));
+ client.discoverServices(service2.getServiceType(),
+ NsdManager.PROTOCOL_DNS_SD, mock(DiscoveryListener.class));
+ waitForIdle();
+
+ // The DiscoveryManager is enabled for _type1 but not _type2
+ verify(mDiscoveryManager).registerListener(eq("_type1._tcp.local"), any(), any());
+ verify(mDiscoveryManager, never()).registerListener(
+ eq("_type2._tcp.local"), any(), any());
+
+ client.resolveService(service1, mock(ResolveListener.class));
+ client.resolveService(service2, mock(ResolveListener.class));
+ waitForIdle();
+
+ // Same behavior for resolve
+ verify(mDiscoveryManager, times(2)).registerListener(
+ eq("_type1._tcp.local"), any(), any());
+ verify(mDiscoveryManager, never()).registerListener(
+ eq("_type2._tcp.local"), any(), any());
+
+ client.registerService(service1, NsdManager.PROTOCOL_DNS_SD,
+ mock(RegistrationListener.class));
+ client.registerService(service2, NsdManager.PROTOCOL_DNS_SD,
+ mock(RegistrationListener.class));
+ waitForIdle();
+
+ // The advertiser is enabled for _type2 but not _type1
+ verify(mAdvertiser, never()).addService(anyInt(), argThat(info -> matches(info, service1)));
+ verify(mAdvertiser).addService(anyInt(), argThat(info -> matches(info, service2)));
}
@Test
public void testAdvertiseWithMdnsAdvertiser() {
- makeServiceWithMdnsAdvertiserEnabled();
+ setMdnsAdvertiserEnabled();
final NsdManager client = connectClient(mService);
final RegistrationListener regListener = mock(RegistrationListener.class);
@@ -1040,12 +1149,12 @@
verify(mAdvertiser).removeService(idCaptor.getValue());
verify(regListener, timeout(TIMEOUT_MS)).onServiceUnregistered(
argThat(info -> matches(info, regInfo)));
- verify(mSocketProvider, timeout(TIMEOUT_MS)).stopMonitoringSockets();
+ verify(mSocketProvider, timeout(TIMEOUT_MS)).requestStopWhenInactive();
}
@Test
public void testAdvertiseWithMdnsAdvertiser_FailedWithInvalidServiceType() {
- makeServiceWithMdnsAdvertiserEnabled();
+ setMdnsAdvertiserEnabled();
final NsdManager client = connectClient(mService);
final RegistrationListener regListener = mock(RegistrationListener.class);
@@ -1070,7 +1179,7 @@
@Test
public void testAdvertiseWithMdnsAdvertiser_LongServiceName() {
- makeServiceWithMdnsAdvertiserEnabled();
+ setMdnsAdvertiserEnabled();
final NsdManager client = connectClient(mService);
final RegistrationListener regListener = mock(RegistrationListener.class);
@@ -1100,6 +1209,81 @@
argThat(info -> matches(info, new NsdServiceInfo(regInfo.getServiceName(), null))));
}
+ @Test
+ public void testStopServiceResolutionWithMdnsDiscoveryManager() {
+ setMdnsDiscoveryManagerEnabled();
+
+ final NsdManager client = connectClient(mService);
+ final ResolveListener resolveListener = mock(ResolveListener.class);
+ final Network network = new Network(999);
+ final String serviceType = "_nsd._service._tcp";
+ final String constructedServiceType = "_nsd._sub._service._tcp.local";
+ final ArgumentCaptor<MdnsServiceBrowserListener> listenerCaptor =
+ ArgumentCaptor.forClass(MdnsServiceBrowserListener.class);
+ final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, serviceType);
+ request.setNetwork(network);
+ client.resolveService(request, resolveListener);
+ waitForIdle();
+ verify(mSocketProvider).startMonitoringSockets();
+ verify(mDiscoveryManager).registerListener(eq(constructedServiceType),
+ listenerCaptor.capture(), argThat(options -> network.equals(options.getNetwork())));
+
+ client.stopServiceResolution(resolveListener);
+ waitForIdle();
+
+ // Verify the listener has been unregistered.
+ verify(mDiscoveryManager, timeout(TIMEOUT_MS))
+ .unregisterListener(eq(constructedServiceType), eq(listenerCaptor.getValue()));
+ verify(resolveListener, timeout(TIMEOUT_MS)).onResolutionStopped(argThat(ns ->
+ request.getServiceName().equals(ns.getServiceName())
+ && request.getServiceType().equals(ns.getServiceType())));
+ verify(mSocketProvider, timeout(CLEANUP_DELAY_MS + TIMEOUT_MS)).requestStopWhenInactive();
+ }
+
+ @Test
+ public void testConstructServiceType() {
+ final String serviceType1 = "test._tcp";
+ final String serviceType2 = "_test._quic";
+ final String serviceType3 = "_123._udp.";
+ final String serviceType4 = "_TEST._999._tcp.";
+
+ assertEquals(null, constructServiceType(serviceType1));
+ assertEquals(null, constructServiceType(serviceType2));
+ assertEquals("_123._udp", constructServiceType(serviceType3));
+ assertEquals("_TEST._sub._999._tcp", constructServiceType(serviceType4));
+ }
+
+ @Test
+ @EnableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
+ public void testEnablePlatformMdnsBackend() {
+ final NsdManager client = connectClient(mService);
+ final NsdServiceInfo regInfo = new NsdServiceInfo("a".repeat(70), SERVICE_TYPE);
+ final Network network = new Network(999);
+ regInfo.setHostAddresses(List.of(parseNumericAddress("192.0.2.123")));
+ regInfo.setPort(12345);
+ regInfo.setAttribute("testattr", "testvalue");
+ regInfo.setNetwork(network);
+
+ // Verify the registration uses MdnsAdvertiser
+ final RegistrationListener regListener = mock(RegistrationListener.class);
+ client.registerService(regInfo, NsdManager.PROTOCOL_DNS_SD, Runnable::run, regListener);
+ waitForIdle();
+ verify(mSocketProvider).startMonitoringSockets();
+ verify(mAdvertiser).addService(anyInt(), any());
+
+ // Verify the discovery uses MdnsDiscoveryManager
+ final DiscoveryListener discListener = mock(DiscoveryListener.class);
+ client.discoverServices(SERVICE_TYPE, PROTOCOL, network, r -> r.run(), discListener);
+ waitForIdle();
+ verify(mDiscoveryManager).registerListener(anyString(), any(), any());
+
+ // Verify the discovery uses MdnsDiscoveryManager
+ final ResolveListener resolveListener = mock(ResolveListener.class);
+ client.resolveService(regInfo, r -> r.run(), resolveListener);
+ waitForIdle();
+ verify(mDiscoveryManager, times(2)).registerListener(anyString(), any(), any());
+ }
+
private void waitForIdle() {
HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS);
}
@@ -1107,7 +1291,8 @@
NsdService makeService() {
final NsdService service = new NsdService(mContext, mHandler, CLEANUP_DELAY_MS, mDeps) {
@Override
- public INsdServiceConnector connect(INsdManagerCallback baseCb) {
+ public INsdServiceConnector connect(INsdManagerCallback baseCb,
+ boolean runNewMdnsBackend) {
// Wrap the callback in a transparent mock, to mock asBinder returning a
// LinkToDeathRecorder. This will allow recording the binder death recipient
// registered on the callback. Use a transparent mock and not a spy as the actual
@@ -1116,7 +1301,7 @@
AdditionalAnswers.delegatesTo(baseCb));
doReturn(new LinkToDeathRecorder()).when(cb).asBinder();
mCreatedCallbacks.add(cb);
- return super.connect(cb);
+ return super.connect(cb, runNewMdnsBackend);
}
};
return service;
diff --git a/tests/unit/java/com/android/server/connectivity/ApplicationSelfCertifiedNetworkCapabilitiesTest.kt b/tests/unit/java/com/android/server/connectivity/ApplicationSelfCertifiedNetworkCapabilitiesTest.kt
new file mode 100644
index 0000000..f2d7aaa
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/ApplicationSelfCertifiedNetworkCapabilitiesTest.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 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.server.connectivity
+
+import android.net.NetworkCapabilities
+import android.os.Build
+import androidx.test.InstrumentationRegistry
+import androidx.test.filters.SmallTest
+import com.android.frameworks.tests.net.R
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(DevSdkIgnoreRunner::class)
+@SmallTest
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+class ApplicationSelfCertifiedNetworkCapabilitiesTest {
+ private val mResource = InstrumentationRegistry.getContext().getResources()
+ private val bandwidthCapability = NetworkCapabilities.Builder().apply {
+ addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ }.build()
+ private val latencyCapability = NetworkCapabilities.Builder().apply {
+ addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ }.build()
+ private val emptyCapability = NetworkCapabilities.Builder().build()
+ private val bothCapabilities = NetworkCapabilities.Builder().apply {
+ addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ }.build()
+
+ @Test
+ fun parseXmlWithWrongTag_shouldIgnoreWrongTag() {
+ val parser = mResource.getXml(
+ R.xml.self_certified_capabilities_wrong_tag
+ )
+ val selfDeclaredCaps = ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(latencyCapability)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(bandwidthCapability)
+ }
+
+ @Test
+ fun parseXmlWithWrongDeclaration_shouldThrowException() {
+ val parser = mResource.getXml(
+ R.xml.self_certified_capabilities_wrong_declaration
+ )
+ val exception = assertFailsWith<InvalidTagException> {
+ ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser)
+ }
+ assertThat(exception.message).contains("network-capabilities-declaration1")
+ }
+
+ @Test
+ fun checkIfSelfCertifiedNetworkCapabilitiesDeclared_shouldThrowExceptionWhenNoDeclaration() {
+ val parser = mResource.getXml(R.xml.self_certified_capabilities_other)
+ val selfDeclaredCaps = ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser)
+ val exception1 = assertFailsWith<SecurityException> {
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(latencyCapability)
+ }
+ assertThat(exception1.message).contains(
+ ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_LATENCY
+ )
+ val exception2 = assertFailsWith<SecurityException> {
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(bandwidthCapability)
+ }
+ assertThat(exception2.message).contains(
+ ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_BANDWIDTH
+ )
+ }
+
+ @Test
+ fun checkIfSelfCertifiedNetworkCapabilitiesDeclared_shouldPassIfDeclarationExist() {
+ val parser = mResource.getXml(R.xml.self_certified_capabilities_both)
+ val selfDeclaredCaps = ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(latencyCapability)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(bandwidthCapability)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(bothCapabilities)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(emptyCapability)
+ }
+}
diff --git a/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java b/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java
index 6c29d6e..3eb1b26 100644
--- a/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java
@@ -16,31 +16,70 @@
package com.android.server.connectivity;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.longThat;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import android.app.AlarmManager;
import android.content.Context;
+import android.content.res.Resources;
+import android.net.ConnectivityResources;
import android.net.INetd;
+import android.net.ISocketKeepaliveCallback;
+import android.net.KeepalivePacketData;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.net.MarkMaskParcel;
+import android.net.NattKeepalivePacketData;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.os.Binder;
import android.os.Build;
+import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.server.connectivity.KeepaliveTracker.KeepaliveInfo;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
+import com.android.testutils.HandlerUtils;
import libcore.util.HexEncoding;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.FileDescriptor;
+import java.net.InetAddress;
+import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -48,17 +87,23 @@
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
public class AutomaticOnOffKeepaliveTrackerTest {
+ private static final String TAG = AutomaticOnOffKeepaliveTrackerTest.class.getSimpleName();
private static final int TEST_NETID = 0xA85;
private static final int TEST_NETID_FWMARK = 0x0A85;
private static final int OTHER_NETID = 0x1A85;
private static final int NETID_MASK = 0xffff;
+ private static final int TIMEOUT_MS = 30_000;
+ private static final int MOCK_RESOURCE_ID = 5;
+ private static final int TEST_KEEPALIVE_INTERVAL_SEC = 10;
private AutomaticOnOffKeepaliveTracker mAOOKeepaliveTracker;
private HandlerThread mHandlerThread;
@Mock INetd mNetd;
@Mock AutomaticOnOffKeepaliveTracker.Dependencies mDependencies;
@Mock Context mCtx;
- @Mock KeepaliveTracker mKeepaliveTracker;
+ @Mock AlarmManager mAlarmManager;
+ TestKeepaliveTracker mKeepaliveTracker;
+ AOOTestHandler mTestHandler;
// Hexadecimal representation of a SOCK_DIAG response with tcp info.
private static final String SOCK_DIAG_TCP_INET_HEX =
@@ -157,11 +202,46 @@
private static final byte[] TEST_RESPONSE_BYTES =
HexEncoding.decode(TEST_RESPONSE_HEX.toCharArray(), false);
+ private class TestKeepaliveTracker extends KeepaliveTracker {
+ private KeepaliveInfo mKi;
+
+ TestKeepaliveTracker(@NonNull final Context context, @NonNull final Handler handler) {
+ super(context, handler);
+ }
+
+ public void setReturnedKeepaliveInfo(@NonNull final KeepaliveInfo ki) {
+ mKi = ki;
+ }
+
+ @NonNull
+ @Override
+ public KeepaliveInfo makeNattKeepaliveInfo(@Nullable final NetworkAgentInfo nai,
+ @Nullable final FileDescriptor fd, final int intervalSeconds,
+ @NonNull final ISocketKeepaliveCallback cb, @NonNull final String srcAddrString,
+ final int srcPort,
+ @NonNull final String dstAddrString, final int dstPort) {
+ if (null == mKi) {
+ throw new IllegalStateException("Must call setReturnedKeepaliveInfo");
+ }
+ return mKi;
+ }
+ }
+
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
+ doReturn(PERMISSION_GRANTED).when(mCtx).checkPermission(any() /* permission */,
+ anyInt() /* pid */, anyInt() /* uid */);
+ ConnectivityResources.setResourcesContextForTest(mCtx);
+ final Resources mockResources = mock(Resources.class);
+ doReturn(MOCK_RESOURCE_ID).when(mockResources).getIdentifier(any() /* name */,
+ any() /* defType */, any() /* defPackage */);
+ doReturn(new String[] { "0,3", "3,3" }).when(mockResources)
+ .getStringArray(MOCK_RESOURCE_ID);
+ doReturn(mockResources).when(mCtx).getResources();
doReturn(mNetd).when(mDependencies).getNetd();
+ doReturn(mAlarmManager).when(mDependencies).getAlarmManager(any());
doReturn(makeMarkMaskParcel(NETID_MASK, TEST_NETID_FWMARK)).when(mNetd)
.getFwmarkForNetwork(TEST_NETID);
@@ -169,11 +249,34 @@
mHandlerThread = new HandlerThread("KeepaliveTrackerTest");
mHandlerThread.start();
- doReturn(mKeepaliveTracker).when(mDependencies).newKeepaliveTracker(
- mCtx, mHandlerThread.getThreadHandler());
- doReturn(true).when(mDependencies).isFeatureEnabled(any());
- mAOOKeepaliveTracker = new AutomaticOnOffKeepaliveTracker(
- mCtx, mHandlerThread.getThreadHandler(), mDependencies);
+ mTestHandler = new AOOTestHandler(mHandlerThread.getLooper());
+ mKeepaliveTracker = new TestKeepaliveTracker(mCtx, mTestHandler);
+ doReturn(mKeepaliveTracker).when(mDependencies).newKeepaliveTracker(mCtx, mTestHandler);
+ doReturn(true).when(mDependencies).isFeatureEnabled(any(), anyBoolean());
+ mAOOKeepaliveTracker =
+ new AutomaticOnOffKeepaliveTracker(mCtx, mTestHandler, mDependencies);
+ }
+
+ private final class AOOTestHandler extends Handler {
+ public AutomaticOnOffKeepaliveTracker.AutomaticOnOffKeepalive mLastAutoKi = null;
+
+ AOOTestHandler(@NonNull final Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(@NonNull final Message msg) {
+ switch (msg.what) {
+ case AutomaticOnOffKeepaliveTracker.CMD_REQUEST_START_KEEPALIVE:
+ Log.d(TAG, "Test handler received CMD_REQUEST_START_KEEPALIVE : " + msg);
+ mAOOKeepaliveTracker.handleStartKeepalive(msg);
+ break;
+ case AutomaticOnOffKeepaliveTracker.CMD_MONITOR_AUTOMATIC_KEEPALIVE:
+ Log.d(TAG, "Test handler received CMD_MONITOR_AUTOMATIC_KEEPALIVE : " + msg);
+ mLastAutoKi = mAOOKeepaliveTracker.getKeepaliveForBinder((IBinder) msg.obj);
+ break;
+ }
+ }
}
@Test
@@ -186,24 +289,86 @@
@Test
public void testIsAnyTcpSocketConnected_withTargetNetId() throws Exception {
setupResponseWithSocketExisting();
- mHandlerThread.getThreadHandler().post(
+ mTestHandler.post(
() -> assertTrue(mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID)));
}
@Test
public void testIsAnyTcpSocketConnected_withIncorrectNetId() throws Exception {
setupResponseWithSocketExisting();
- mHandlerThread.getThreadHandler().post(
+ mTestHandler.post(
() -> assertFalse(mAOOKeepaliveTracker.isAnyTcpSocketConnected(OTHER_NETID)));
}
@Test
public void testIsAnyTcpSocketConnected_noSocketExists() throws Exception {
setupResponseWithoutSocketExisting();
- mHandlerThread.getThreadHandler().post(
+ mTestHandler.post(
() -> assertFalse(mAOOKeepaliveTracker.isAnyTcpSocketConnected(TEST_NETID)));
}
+ @Test
+ public void testAlarm() throws Exception {
+ final InetAddress srcAddress = InetAddress.getByAddress(
+ new byte[] { (byte) 192, 0, 0, (byte) 129 });
+ final int srcPort = 12345;
+ final InetAddress dstAddress = InetAddress.getByAddress(new byte[] { 8, 8, 8, 8});
+ final int dstPort = 12345;
+
+ final NetworkAgentInfo nai = mock(NetworkAgentInfo.class);
+ nai.networkCapabilities = new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ nai.networkInfo = new NetworkInfo(TYPE_MOBILE, 0 /* subtype */, "LTE", "LTE");
+ nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "test reason",
+ "test extra info");
+ nai.linkProperties = new LinkProperties();
+ nai.linkProperties.addLinkAddress(new LinkAddress(srcAddress, 24));
+
+ final Socket socket = new Socket();
+ socket.bind(null);
+ final FileDescriptor fd = socket.getFileDescriptor$();
+ final IBinder binder = new Binder();
+ final ISocketKeepaliveCallback cb = mock(ISocketKeepaliveCallback.class);
+ doReturn(binder).when(cb).asBinder();
+ final Network underpinnedNetwork = mock(Network.class);
+
+ final KeepalivePacketData kpd = new NattKeepalivePacketData(srcAddress, srcPort,
+ dstAddress, dstPort, new byte[] {1});
+ final KeepaliveInfo ki = mKeepaliveTracker.new KeepaliveInfo(cb, nai, kpd,
+ TEST_KEEPALIVE_INTERVAL_SEC, KeepaliveInfo.TYPE_NATT, fd);
+ mKeepaliveTracker.setReturnedKeepaliveInfo(ki);
+
+ // Mock elapsed real time to verify the alarm timer.
+ final long time = SystemClock.elapsedRealtime();
+ doReturn(time).when(mDependencies).getElapsedRealtime();
+
+ mAOOKeepaliveTracker.startNattKeepalive(nai, fd, 10 /* intervalSeconds */, cb,
+ srcAddress.toString(), srcPort, dstAddress.toString(), dstPort,
+ true /* automaticOnOffKeepalives */, underpinnedNetwork);
+ HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS);
+
+ final ArgumentCaptor<AlarmManager.OnAlarmListener> listenerCaptor =
+ ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
+ // The alarm timer should be smaller than the keepalive delay. Verify the alarm trigger time
+ // is higher than base time but smaller than the keepalive delay.
+ verify(mAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME),
+ longThat(t -> t > time + 1000L && t < time + TEST_KEEPALIVE_INTERVAL_SEC * 1000L),
+ any() /* tag */, listenerCaptor.capture(), eq(mTestHandler));
+ final AlarmManager.OnAlarmListener listener = listenerCaptor.getValue();
+
+ // For realism, the listener should be posted on the handler
+ mTestHandler.post(() -> listener.onAlarm());
+ // Wait for the listener to be called. The listener enqueues a message to the handler.
+ HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS);
+ // Wait for the message posted by the listener to be processed.
+ HandlerUtils.waitForIdle(mTestHandler, TIMEOUT_MS);
+
+ assertNotNull(mTestHandler.mLastAutoKi);
+ assertEquals(cb, mTestHandler.mLastAutoKi.getCallback());
+ assertEquals(underpinnedNetwork, mTestHandler.mLastAutoKi.getUnderpinnedNetwork());
+ socket.close();
+ }
+
private void setupResponseWithSocketExisting() throws Exception {
final ByteBuffer tcpBufferV6 = getByteBuffer(TEST_RESPONSE_BYTES);
final ByteBuffer tcpBufferV4 = getByteBuffer(TEST_RESPONSE_BYTES);
diff --git a/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 719314a..5881a8e 100644
--- a/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -80,6 +80,7 @@
private static final byte[] MAC_ADDR =
{(byte)0x84, (byte)0xc9, (byte)0xb2, (byte)0x6a, (byte)0xed, (byte)0x4b};
+ private static final long NET_HANDLE = new Network(4291).getNetworkHandle();
@Mock Context mCtx;
@Mock IIpConnectivityMetrics mMockService;
@@ -607,7 +608,7 @@
void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp,
String dstIp, int sport, int dport, long now) throws Exception {
- String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface;
+ String prefix = NET_HANDLE + ":" + iface;
mNetdListener.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now);
}
diff --git a/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 7d6c3ae..f4b6464 100644
--- a/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -60,6 +60,8 @@
private static final String EXAMPLE_IPV4 = "192.0.2.1";
private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
+ private static final long NET_HANDLE = new Network(5391).getNetworkHandle();
+
private static final byte[] MAC_ADDR =
{(byte)0x84, (byte)0xc9, (byte)0xb2, (byte)0x6a, (byte)0xed, (byte)0x4b};
@@ -498,7 +500,7 @@
void wakeupEvent(String iface, int uid, int ether, int ip, byte[] mac, String srcIp,
String dstIp, int sport, int dport, long now) throws Exception {
- String prefix = NetdEventListenerService.WAKEUP_EVENT_IFACE_PREFIX + iface;
+ String prefix = NET_HANDLE + ":" + iface;
mService.onWakeupEvent(prefix, uid, ether, ip, mac, srcIp, dstIp, sport, dport, now);
}
diff --git a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 9a5298d..e038c44 100644
--- a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -56,8 +56,10 @@
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
+import android.os.PowerManager;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
+import android.testing.PollingCheck;
import android.util.DisplayMetrics;
import android.widget.TextView;
@@ -391,7 +393,15 @@
final Instrumentation instr = InstrumentationRegistry.getInstrumentation();
final UiDevice uiDevice = UiDevice.getInstance(instr);
- UiDevice.getInstance(instr).pressHome();
+ final Context ctx = instr.getContext();
+ final PowerManager pm = ctx.getSystemService(PowerManager.class);
+
+ // Wake up the device (it has no effect if the device is already awake).
+ uiDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ uiDevice.executeShellCommand("wm dismiss-keyguard");
+ PollingCheck.check("Wait for the screen to be turned on failed, timeout=" + TEST_TIMEOUT_MS,
+ TEST_TIMEOUT_MS, () -> pm.isInteractive());
+ uiDevice.pressHome();
// UiDevice.getLauncherPackageName() requires the test manifest to have a <queries> tag for
// the launcher intent.
@@ -404,7 +414,6 @@
// Non-"no internet" notifications are not affected
verify(mNotificationManager).notify(eq(TEST_NOTIF_TAG), eq(NETWORK_SWITCH.eventId), any());
- final Context ctx = instr.getContext();
final String testAction = "com.android.connectivity.coverage.TEST_DIALOG";
final Intent intent = new Intent(testAction)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 3f87ffd..2926c9a 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -25,13 +25,35 @@
import static android.net.ConnectivityManager.NetworkCallback;
import static android.net.INetd.IF_STATE_DOWN;
import static android.net.INetd.IF_STATE_UP;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.net.VpnManager.TYPE_VPN_PLATFORM;
+import static android.net.cts.util.IkeSessionTestUtils.CHILD_PARAMS;
+import static android.net.cts.util.IkeSessionTestUtils.TEST_IDENTITY;
+import static android.net.cts.util.IkeSessionTestUtils.TEST_KEEPALIVE_TIMEOUT_UNSET;
+import static android.net.cts.util.IkeSessionTestUtils.getTestIkeSessionParams;
import static android.net.ipsec.ike.IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_AUTO;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_NONE;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_UDP;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_IPV4;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_IPV6;
import static android.os.Build.VERSION_CODES.S_V2;
import static android.os.UserHandle.PER_USER_RANGE;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_PREFERRED_IKE_PROTOCOL_INT;
import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
+import static com.android.server.connectivity.Vpn.AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+import static com.android.server.connectivity.Vpn.DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC;
+import static com.android.server.connectivity.Vpn.DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
+import static com.android.server.connectivity.Vpn.PREFERRED_IKE_PROTOCOL_AUTO;
+import static com.android.server.connectivity.Vpn.PREFERRED_IKE_PROTOCOL_IPV4_UDP;
+import static com.android.server.connectivity.Vpn.PREFERRED_IKE_PROTOCOL_IPV6_ESP;
+import static com.android.server.connectivity.Vpn.PREFERRED_IKE_PROTOCOL_IPV6_UDP;
import static com.android.testutils.Cleanup.testAndCleanup;
import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import static com.android.testutils.MiscAsserts.assertThrows;
@@ -50,6 +72,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.longThat;
import static org.mockito.Mockito.after;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
@@ -99,6 +122,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkInfo.DetailedState;
import android.net.RouteInfo;
+import android.net.TelephonyNetworkSpecifier;
import android.net.UidRangeParcel;
import android.net.VpnManager;
import android.net.VpnProfileState;
@@ -106,15 +130,19 @@
import android.net.VpnTransportInfo;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionConfiguration;
+import android.net.ipsec.ike.IkeFqdnIdentification;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionConfiguration;
import android.net.ipsec.ike.IkeSessionConnectionInfo;
+import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTrafficSelector;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeNetworkLostException;
import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.ipsec.ike.exceptions.IkeTimeoutException;
+import android.net.wifi.WifiInfo;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.ConditionVariable;
@@ -128,6 +156,10 @@
import android.os.test.TestLooper;
import android.provider.Settings;
import android.security.Credentials;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
@@ -147,7 +179,6 @@
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
-import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -248,10 +279,14 @@
private static final String TEST_IFACE_NAME = "TEST_IFACE";
private static final int TEST_TUNNEL_RESOURCE_ID = 0x2345;
private static final long TEST_TIMEOUT_MS = 500L;
+ private static final long TIMEOUT_CROSSTHREAD_MS = 20_000L;
private static final String PRIMARY_USER_APP_EXCLUDE_KEY =
"VPNAPPEXCLUDED_27_com.testvpn.vpn";
static final String PKGS_BYTES = getPackageByteString(List.of(PKGS));
private static final Range<Integer> PRIMARY_USER_RANGE = uidRangeForUser(PRIMARY_USER.id);
+ private static final int TEST_KEEPALIVE_TIMER = 800;
+ private static final int TEST_SUB_ID = 1234;
+ private static final String TEST_MCCMNC = "12345";
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
@Mock private UserManager mUserManager;
@@ -266,17 +301,57 @@
@Mock private Vpn.VpnNetworkAgentWrapper mMockNetworkAgent;
@Mock private ConnectivityManager mConnectivityManager;
@Mock private ConnectivityDiagnosticsManager mCdm;
+ @Mock private TelephonyManager mTelephonyManager;
+ @Mock private TelephonyManager mTmPerSub;
+ @Mock private CarrierConfigManager mConfigManager;
+ @Mock private SubscriptionManager mSubscriptionManager;
@Mock private IpSecService mIpSecService;
@Mock private VpnProfileStore mVpnProfileStore;
- @Mock private ScheduledThreadPoolExecutor mExecutor;
- @Mock private ScheduledFuture mScheduledFuture;
+ private final TestExecutor mExecutor;
@Mock DeviceIdleInternal mDeviceIdleInternal;
private final VpnProfile mVpnProfile;
private IpSecManager mIpSecManager;
-
private TestDeps mTestDeps;
+ public static class TestExecutor extends ScheduledThreadPoolExecutor {
+ public static final long REAL_DELAY = -1;
+
+ // For the purposes of the test, run all scheduled tasks after 10ms to save
+ // execution time, unless overridden by the specific test. Set to REAL_DELAY
+ // to actually wait for the delay specified by the real call to schedule().
+ public long delayMs = 10;
+ // If this is true, execute() will call the runnable inline. This is useful because
+ // super.execute() calls schedule(), which messes with checks that scheduled() is
+ // called a given number of times.
+ public boolean executeDirect = false;
+
+ public TestExecutor() {
+ super(1);
+ }
+
+ @Override
+ public void execute(final Runnable command) {
+ // See |executeDirect| for why this is necessary.
+ if (executeDirect) {
+ command.run();
+ } else {
+ super.execute(command);
+ }
+ }
+
+ @Override
+ public ScheduledFuture<?> schedule(final Runnable command, final long delay,
+ TimeUnit unit) {
+ if (0 == delay || delayMs == REAL_DELAY) {
+ // super.execute() calls schedule() with 0, so use the real delay if it's 0.
+ return super.schedule(command, delay, unit);
+ } else {
+ return super.schedule(command, delayMs, TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+
public VpnTest() throws Exception {
// Build an actual VPN profile that is capable of being converted to and from an
// Ikev2VpnProfile
@@ -284,6 +359,7 @@
new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY);
builder.setAuthPsk(TEST_VPN_PSK);
builder.setBypassable(true /* isBypassable */);
+ mExecutor = spy(new TestExecutor());
mVpnProfile = builder.build().toVpnProfile();
}
@@ -310,6 +386,11 @@
mockService(IpSecManager.class, Context.IPSEC_SERVICE, mIpSecManager);
mockService(ConnectivityDiagnosticsManager.class, Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
mCdm);
+ mockService(TelephonyManager.class, Context.TELEPHONY_SERVICE, mTelephonyManager);
+ mockService(CarrierConfigManager.class, Context.CARRIER_CONFIG_SERVICE, mConfigManager);
+ mockService(SubscriptionManager.class, Context.TELEPHONY_SUBSCRIPTION_SERVICE,
+ mSubscriptionManager);
+ doReturn(mTmPerSub).when(mTelephonyManager).createForSubscriptionId(anyInt());
when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))
.thenReturn(Resources.getSystem().getString(
R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
@@ -344,7 +425,6 @@
// Set up mIkev2SessionCreator and mExecutor
resetIkev2SessionCreator(mIkeSessionWrapper);
- resetExecutor(mScheduledFuture);
}
private void resetIkev2SessionCreator(Vpn.IkeSessionWrapper ikeSession) {
@@ -353,23 +433,6 @@
.thenReturn(ikeSession);
}
- private void resetExecutor(ScheduledFuture scheduledFuture) {
- doAnswer(
- (invocation) -> {
- ((Runnable) invocation.getArgument(0)).run();
- return null;
- })
- .when(mExecutor)
- .execute(any());
- when(mExecutor.schedule(
- any(Runnable.class), anyLong(), any())).thenReturn(mScheduledFuture);
- }
-
- @After
- public void tearDown() throws Exception {
- doReturn(PERMISSION_DENIED).when(mContext).checkCallingOrSelfPermission(any());
- }
-
private <T> void mockService(Class<T> clazz, String name, T service) {
doReturn(service).when(mContext).getSystemService(name);
doReturn(name).when(mContext).getSystemServiceName(clazz);
@@ -480,9 +543,9 @@
}
private void verifyPowerSaveTempWhitelistApp(String packageName) {
- verify(mDeviceIdleInternal).addPowerSaveTempWhitelistApp(anyInt(), eq(packageName),
- anyLong(), anyInt(), eq(false), eq(PowerWhitelistManager.REASON_VPN),
- eq("VpnManager event"));
+ verify(mDeviceIdleInternal, timeout(TEST_TIMEOUT_MS)).addPowerSaveTempWhitelistApp(
+ anyInt(), eq(packageName), anyLong(), anyInt(), eq(false),
+ eq(PowerWhitelistManager.REASON_VPN), eq("VpnManager event"));
}
@Test
@@ -721,7 +784,8 @@
@Test
public void testPrepare_throwSecurityExceptionWhenGivenPackageDoesNotBelongToTheCaller()
throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks();
+ mTestDeps.mIgnoreCallingUidChecks = false;
+ final Vpn vpn = createVpn();
assertThrows(SecurityException.class,
() -> vpn.prepare("com.not.vpn.owner", null, VpnManager.TYPE_VPN_SERVICE));
assertThrows(SecurityException.class,
@@ -733,7 +797,7 @@
@Test
public void testPrepare_bothOldPackageAndNewPackageAreNull() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks();
+ final Vpn vpn = createVpn();
assertTrue(vpn.prepare(null, null, VpnManager.TYPE_VPN_SERVICE));
}
@@ -816,17 +880,14 @@
assertEquals(expected, vpn.getProfileNameForPackage(TEST_VPN_PKG));
}
- private Vpn createVpnAndSetupUidChecks(String... grantedOps) throws Exception {
- return createVpnAndSetupUidChecks(PRIMARY_USER, grantedOps);
+ private Vpn createVpn(String... grantedOps) throws Exception {
+ return createVpn(PRIMARY_USER, grantedOps);
}
- private Vpn createVpnAndSetupUidChecks(UserInfo user, String... grantedOps) throws Exception {
+ private Vpn createVpn(UserInfo user, String... grantedOps) throws Exception {
final Vpn vpn = createVpn(user.id);
setMockedUsers(user);
- when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt()))
- .thenReturn(Process.myUid());
-
for (final String opStr : grantedOps) {
when(mAppOps.noteOpNoThrow(opStr, Process.myUid(), TEST_VPN_PKG,
null /* attributionTag */, null /* message */))
@@ -855,7 +916,7 @@
public void testProvisionVpnProfileNoIpsecTunnels() throws Exception {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS))
.thenReturn(false);
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
try {
checkProvisionVpnProfile(
@@ -866,7 +927,7 @@
}
private Vpn prepareVpnForVerifyAppExclusionList() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
.thenReturn(mVpnProfile.encode());
when(mVpnProfileStore.get(PRIMARY_USER_APP_EXCLUDE_KEY))
@@ -982,7 +1043,7 @@
@Test
public void testProvisionVpnProfilePreconsented() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
checkProvisionVpnProfile(
vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
@@ -990,7 +1051,7 @@
@Test
public void testProvisionVpnProfileNotPreconsented() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks();
+ final Vpn vpn = createVpn();
// Expect that both the ACTIVATE_VPN and ACTIVATE_PLATFORM_VPN were tried, but the caller
// had neither.
@@ -1000,14 +1061,14 @@
@Test
public void testProvisionVpnProfileVpnServicePreconsented() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_VPN);
checkProvisionVpnProfile(vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_VPN);
}
@Test
public void testProvisionVpnProfileTooLarge() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
final VpnProfile bigProfile = new VpnProfile("");
bigProfile.name = new String(new byte[Vpn.MAX_VPN_PROFILE_SIZE_BYTES + 1]);
@@ -1022,7 +1083,7 @@
@Test
public void testProvisionVpnProfileRestrictedUser() throws Exception {
final Vpn vpn =
- createVpnAndSetupUidChecks(
+ createVpn(
RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
try {
@@ -1034,7 +1095,7 @@
@Test
public void testDeleteVpnProfile() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks();
+ final Vpn vpn = createVpn();
vpn.deleteVpnProfile(TEST_VPN_PKG);
@@ -1045,7 +1106,7 @@
@Test
public void testDeleteVpnProfileRestrictedUser() throws Exception {
final Vpn vpn =
- createVpnAndSetupUidChecks(
+ createVpn(
RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
try {
@@ -1057,7 +1118,7 @@
@Test
public void testGetVpnProfilePrivileged() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks();
+ final Vpn vpn = createVpn();
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
.thenReturn(new VpnProfile("").encode());
@@ -1076,7 +1137,7 @@
eq(null) /* message */);
verify(mAppOps).startOp(
eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER),
- eq(Process.myUid()),
+ eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())),
eq(packageName),
eq(null) /* attributionTag */,
eq(null) /* message */);
@@ -1086,14 +1147,14 @@
// Add a small delay to double confirm that finishOp is only called once.
verify(mAppOps, after(100)).finishOp(
eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER),
- eq(Process.myUid()),
+ eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())),
eq(packageName),
eq(null) /* attributionTag */);
}
@Test
public void testStartVpnProfile() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
.thenReturn(mVpnProfile.encode());
@@ -1106,7 +1167,7 @@
@Test
public void testStartVpnProfileVpnServicePreconsented() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
.thenReturn(mVpnProfile.encode());
@@ -1120,7 +1181,7 @@
@Test
public void testStartVpnProfileNotConsented() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks();
+ final Vpn vpn = createVpn();
try {
vpn.startVpnProfile(TEST_VPN_PKG);
@@ -1145,7 +1206,7 @@
@Test
public void testStartVpnProfileMissingProfile() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))).thenReturn(null);
@@ -1167,9 +1228,7 @@
@Test
public void testStartVpnProfileRestrictedUser() throws Exception {
- final Vpn vpn =
- createVpnAndSetupUidChecks(
- RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
try {
vpn.startVpnProfile(TEST_VPN_PKG);
@@ -1180,9 +1239,7 @@
@Test
public void testStopVpnProfileRestrictedUser() throws Exception {
- final Vpn vpn =
- createVpnAndSetupUidChecks(
- RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(RESTRICTED_PROFILE_A, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
try {
vpn.stopVpnProfile(TEST_VPN_PKG);
@@ -1193,7 +1250,7 @@
@Test
public void testStartOpAndFinishOpWillBeCalledWhenPlatformVpnIsOnAndOff() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
.thenReturn(mVpnProfile.encode());
vpn.startVpnProfile(TEST_VPN_PKG);
@@ -1201,14 +1258,14 @@
// Add a small delay to make sure that startOp is only called once.
verify(mAppOps, after(100).times(1)).startOp(
eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER),
- eq(Process.myUid()),
+ eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())),
eq(TEST_VPN_PKG),
eq(null) /* attributionTag */,
eq(null) /* message */);
// Check that the startOp is not called with OPSTR_ESTABLISH_VPN_SERVICE.
verify(mAppOps, never()).startOp(
eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE),
- eq(Process.myUid()),
+ eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())),
eq(TEST_VPN_PKG),
eq(null) /* attributionTag */,
eq(null) /* message */);
@@ -1218,7 +1275,9 @@
@Test
public void testStartOpWithSeamlessHandover() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN);
+ // Create with SYSTEM_USER so that establish() will match the user ID when checking
+ // against Binder.getCallerUid
+ final Vpn vpn = createVpn(SYSTEM_USER, AppOpsManager.OPSTR_ACTIVATE_VPN);
assertTrue(vpn.prepare(TEST_VPN_PKG, null, VpnManager.TYPE_VPN_SERVICE));
final VpnConfig config = new VpnConfig();
config.user = "VpnTest";
@@ -1249,12 +1308,12 @@
}
private void verifyVpnManagerEvent(String sessionKey, String category, int errorClass,
- int errorCode, String[] packageName, VpnProfileState... profileState) {
+ int errorCode, String[] packageName, @NonNull VpnProfileState... profileState) {
final Context userContext =
mContext.createContextAsUser(UserHandle.of(PRIMARY_USER.id), 0 /* flags */);
final ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
- final int verifyTimes = (profileState == null) ? 1 : profileState.length;
+ final int verifyTimes = profileState.length;
verify(userContext, times(verifyTimes)).startService(intentArgumentCaptor.capture());
for (int i = 0; i < verifyTimes; i++) {
@@ -1285,10 +1344,8 @@
VpnManager.EXTRA_UNDERLYING_LINK_PROPERTIES));
}
- if (profileState != null) {
- assertEquals(profileState[i], intent.getParcelableExtra(
- VpnManager.EXTRA_VPN_PROFILE_STATE, VpnProfileState.class));
- }
+ assertEquals(profileState[i], intent.getParcelableExtra(
+ VpnManager.EXTRA_VPN_PROFILE_STATE, VpnProfileState.class));
}
reset(userContext);
}
@@ -1297,7 +1354,11 @@
// CATEGORY_EVENT_DEACTIVATED_BY_USER is not an error event, so both of errorClass and
// errorCode won't be set.
verifyVpnManagerEvent(sessionKey, VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER,
- -1 /* errorClass */, -1 /* errorCode */, packageName, null /* profileState */);
+ -1 /* errorClass */, -1 /* errorCode */, packageName,
+ // VPN NetworkAgnet does not switch to CONNECTED in the test, and the state is not
+ // important here. Verify that the state as it is, i.e. CONNECTING state.
+ new VpnProfileState(VpnProfileState.STATE_CONNECTING,
+ sessionKey, false /* alwaysOn */, false /* lockdown */));
}
private void verifyAlwaysOnStateChanged(String[] packageName, VpnProfileState... profileState) {
@@ -1314,7 +1375,7 @@
// this is checked with CONTROL_VPN so simulate holding CONTROL_VPN in order to pass the
// security checks.
doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN);
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
.thenReturn(mVpnProfile.encode());
@@ -1406,7 +1467,7 @@
@Test
public void testReconnectVpnManagerVpnWithAlwaysOnEnabled() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
.thenReturn(mVpnProfile.encode());
vpn.startVpnProfile(TEST_VPN_PKG);
@@ -1430,46 +1491,73 @@
}
@Test
+ public void testLockdown_enableDisableWhileConnected() throws Exception {
+ final PlatformVpnSnapshot vpnSnapShot = verifySetupPlatformVpn(
+ createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */));
+
+ final InOrder order = inOrder(mTestDeps);
+ order.verify(mTestDeps, timeout(TIMEOUT_CROSSTHREAD_MS))
+ .newNetworkAgent(any(), any(), any(), any(), any(), any(),
+ argThat(config -> config.allowBypass), any(), any());
+
+ // Make VPN lockdown.
+ assertTrue(vpnSnapShot.vpn.setAlwaysOnPackage(TEST_VPN_PKG, true /* lockdown */,
+ null /* lockdownAllowlist */));
+
+ order.verify(mTestDeps, timeout(TIMEOUT_CROSSTHREAD_MS))
+ .newNetworkAgent(any(), any(), any(), any(), any(), any(),
+ argThat(config -> !config.allowBypass), any(), any());
+
+ // Disable lockdown.
+ assertTrue(vpnSnapShot.vpn.setAlwaysOnPackage(TEST_VPN_PKG, false /* lockdown */,
+ null /* lockdownAllowlist */));
+
+ order.verify(mTestDeps, timeout(TIMEOUT_CROSSTHREAD_MS))
+ .newNetworkAgent(any(), any(), any(), any(), any(), any(),
+ argThat(config -> config.allowBypass), any(), any());
+ }
+
+ @Test
public void testSetPackageAuthorizationVpnService() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks();
+ final Vpn vpn = createVpn();
assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_SERVICE));
verify(mAppOps)
.setMode(
eq(AppOpsManager.OPSTR_ACTIVATE_VPN),
- eq(Process.myUid()),
+ eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())),
eq(TEST_VPN_PKG),
eq(AppOpsManager.MODE_ALLOWED));
}
@Test
public void testSetPackageAuthorizationPlatformVpn() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks();
+ final Vpn vpn = createVpn();
assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, TYPE_VPN_PLATFORM));
verify(mAppOps)
.setMode(
eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN),
- eq(Process.myUid()),
+ eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())),
eq(TEST_VPN_PKG),
eq(AppOpsManager.MODE_ALLOWED));
}
@Test
public void testSetPackageAuthorizationRevokeAuthorization() throws Exception {
- final Vpn vpn = createVpnAndSetupUidChecks();
+ final Vpn vpn = createVpn();
assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_NONE));
verify(mAppOps)
.setMode(
eq(AppOpsManager.OPSTR_ACTIVATE_VPN),
- eq(Process.myUid()),
+ eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())),
eq(TEST_VPN_PKG),
eq(AppOpsManager.MODE_IGNORED));
verify(mAppOps)
.setMode(
eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN),
- eq(Process.myUid()),
+ eq(UserHandle.getUid(PRIMARY_USER.id, Process.myUid())),
eq(TEST_VPN_PKG),
eq(AppOpsManager.MODE_IGNORED));
}
@@ -1507,7 +1595,7 @@
final ArgumentCaptor<IkeSessionCallback> captor =
ArgumentCaptor.forClass(IkeSessionCallback.class);
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
.thenReturn(mVpnProfile.encode());
@@ -1530,10 +1618,7 @@
// same process with the real case.
if (errorCode == VpnManager.ERROR_CODE_NETWORK_LOST) {
cb.onLost(TEST_NETWORK);
- final ArgumentCaptor<Runnable> runnableCaptor =
- ArgumentCaptor.forClass(Runnable.class);
- verify(mExecutor).schedule(runnableCaptor.capture(), anyLong(), any());
- runnableCaptor.getValue().run();
+ verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any());
} else {
final IkeSessionCallback ikeCb = captor.getValue();
ikeCb.onClosedWithException(exception);
@@ -1542,7 +1627,10 @@
verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG);
reset(mDeviceIdleInternal);
verifyVpnManagerEvent(sessionKey, category, errorType, errorCode,
- new String[] {TEST_VPN_PKG}, null /* profileState */);
+ // VPN NetworkAgnet does not switch to CONNECTED in the test, and the state is not
+ // important here. Verify that the state as it is, i.e. CONNECTING state.
+ new String[] {TEST_VPN_PKG}, new VpnProfileState(VpnProfileState.STATE_CONNECTING,
+ sessionKey, false /* alwaysOn */, false /* lockdown */));
if (errorType == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) {
verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS))
.unregisterNetworkCallback(eq(cb));
@@ -1558,25 +1646,23 @@
}
private IkeSessionCallback verifyRetryAndGetNewIkeCb(int retryIndex) {
- final ArgumentCaptor<Runnable> runnableCaptor =
- ArgumentCaptor.forClass(Runnable.class);
final ArgumentCaptor<IkeSessionCallback> ikeCbCaptor =
ArgumentCaptor.forClass(IkeSessionCallback.class);
// Verify retry is scheduled
- final long expectedDelay = mTestDeps.getNextRetryDelaySeconds(retryIndex);
- verify(mExecutor).schedule(runnableCaptor.capture(), eq(expectedDelay), any());
+ final long expectedDelayMs = mTestDeps.getNextRetryDelayMs(retryIndex);
+ final ArgumentCaptor<Long> delayCaptor = ArgumentCaptor.forClass(Long.class);
+ verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), delayCaptor.capture(),
+ eq(TimeUnit.MILLISECONDS));
+ final List<Long> delays = delayCaptor.getAllValues();
+ assertEquals(expectedDelayMs, (long) delays.get(delays.size() - 1));
- // Mock the event of firing the retry task
- runnableCaptor.getValue().run();
-
- verify(mIkev2SessionCreator)
+ verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS + expectedDelayMs))
.createIkeSession(any(), any(), any(), any(), ikeCbCaptor.capture(), any());
// Forget the mIkev2SessionCreator#createIkeSession call and mExecutor#schedule call
// for the next retry verification
resetIkev2SessionCreator(mIkeSessionWrapper);
- resetExecutor(mScheduledFuture);
return ikeCbCaptor.getValue();
}
@@ -1812,6 +1898,18 @@
private PlatformVpnSnapshot verifySetupPlatformVpn(
IkeSessionConfiguration ikeConfig, boolean mtuSupportsIpv6) throws Exception {
+ return verifySetupPlatformVpn(mVpnProfile, ikeConfig, mtuSupportsIpv6);
+ }
+
+ private PlatformVpnSnapshot verifySetupPlatformVpn(VpnProfile vpnProfile,
+ IkeSessionConfiguration ikeConfig, boolean mtuSupportsIpv6) throws Exception {
+ return verifySetupPlatformVpn(vpnProfile, ikeConfig, mtuSupportsIpv6,
+ false /* areLongLivedTcpConnectionsExpensive */);
+ }
+
+ private PlatformVpnSnapshot verifySetupPlatformVpn(VpnProfile vpnProfile,
+ IkeSessionConfiguration ikeConfig, boolean mtuSupportsIpv6,
+ boolean areLongLivedTcpConnectionsExpensive) throws Exception {
if (!mtuSupportsIpv6) {
doReturn(IPV6_MIN_MTU - 1).when(mTestDeps).calculateVpnMtu(any(), anyInt(), anyInt(),
anyBoolean());
@@ -1820,13 +1918,16 @@
doReturn(mMockNetworkAgent).when(mTestDeps)
.newNetworkAgent(
any(), any(), anyString(), any(), any(), any(), any(), any(), any());
+ doReturn(TEST_NETWORK).when(mMockNetworkAgent).getNetwork();
- final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ final Vpn vpn = createVpn(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
- .thenReturn(mVpnProfile.encode());
+ .thenReturn(vpnProfile.encode());
vpn.startVpnProfile(TEST_VPN_PKG);
final NetworkCallback nwCb = triggerOnAvailableAndGetCallback();
+ verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any());
+ reset(mExecutor);
// Mock the setup procedure by firing callbacks
final Pair<IkeSessionCallback, ChildSessionCallback> cbPair =
@@ -1850,7 +1951,7 @@
verify(mTestDeps).newNetworkAgent(
any(), any(), anyString(), ncCaptor.capture(), lpCaptor.capture(),
any(), nacCaptor.capture(), any(), any());
-
+ verify(mIkeSessionWrapper).setUnderpinnedNetwork(TEST_NETWORK);
// Check LinkProperties
final LinkProperties lp = lpCaptor.getValue();
final List<RouteInfo> expectedRoutes =
@@ -1893,8 +1994,10 @@
// Check if allowBypass is set or not.
assertTrue(nacCaptor.getValue().isBypassableVpn());
- assertTrue(((VpnTransportInfo) ncCaptor.getValue().getTransportInfo()).isBypassable());
-
+ final VpnTransportInfo info = (VpnTransportInfo) ncCaptor.getValue().getTransportInfo();
+ assertTrue(info.isBypassable());
+ assertEquals(areLongLivedTcpConnectionsExpensive,
+ info.areLongLivedTcpConnectionsExpensive());
return new PlatformVpnSnapshot(vpn, nwCb, ikeCb, childCb);
}
@@ -1906,6 +2009,384 @@
}
@Test
+ public void testMigrateIkeSession_FromIkeTunnConnParams_AutoTimerNoTimer() throws Exception {
+ doTestMigrateIkeSession_FromIkeTunnConnParams(
+ false /* isAutomaticIpVersionSelectionEnabled */,
+ true /* isAutomaticNattKeepaliveTimerEnabled */,
+ TEST_KEEPALIVE_TIMEOUT_UNSET /* keepaliveInProfile */,
+ ESP_IP_VERSION_AUTO /* ipVersionInProfile */,
+ ESP_ENCAP_TYPE_AUTO /* encapTypeInProfile */);
+ }
+
+ @Test
+ public void testMigrateIkeSession_FromIkeTunnConnParams_AutoTimerTimerSet() throws Exception {
+ doTestMigrateIkeSession_FromIkeTunnConnParams(
+ false /* isAutomaticIpVersionSelectionEnabled */,
+ true /* isAutomaticNattKeepaliveTimerEnabled */,
+ TEST_KEEPALIVE_TIMER /* keepaliveInProfile */,
+ ESP_IP_VERSION_AUTO /* ipVersionInProfile */,
+ ESP_ENCAP_TYPE_AUTO /* encapTypeInProfile */);
+ }
+
+ @Test
+ public void testMigrateIkeSession_FromIkeTunnConnParams_AutoIp() throws Exception {
+ doTestMigrateIkeSession_FromIkeTunnConnParams(
+ true /* isAutomaticIpVersionSelectionEnabled */,
+ false /* isAutomaticNattKeepaliveTimerEnabled */,
+ TEST_KEEPALIVE_TIMEOUT_UNSET /* keepaliveInProfile */,
+ ESP_IP_VERSION_AUTO /* ipVersionInProfile */,
+ ESP_ENCAP_TYPE_AUTO /* encapTypeInProfile */);
+ }
+
+ @Test
+ public void testMigrateIkeSession_FromIkeTunnConnParams_AssignedIpProtocol() throws Exception {
+ doTestMigrateIkeSession_FromIkeTunnConnParams(
+ false /* isAutomaticIpVersionSelectionEnabled */,
+ false /* isAutomaticNattKeepaliveTimerEnabled */,
+ TEST_KEEPALIVE_TIMEOUT_UNSET /* keepaliveInProfile */,
+ ESP_IP_VERSION_IPV4 /* ipVersionInProfile */,
+ ESP_ENCAP_TYPE_UDP /* encapTypeInProfile */);
+ }
+
+ @Test
+ public void testMigrateIkeSession_FromNotIkeTunnConnParams_AutoTimer() throws Exception {
+ doTestMigrateIkeSession_FromNotIkeTunnConnParams(
+ false /* isAutomaticIpVersionSelectionEnabled */,
+ true /* isAutomaticNattKeepaliveTimerEnabled */);
+ }
+
+ @Test
+ public void testMigrateIkeSession_FromNotIkeTunnConnParams_AutoIp() throws Exception {
+ doTestMigrateIkeSession_FromNotIkeTunnConnParams(
+ true /* isAutomaticIpVersionSelectionEnabled */,
+ false /* isAutomaticNattKeepaliveTimerEnabled */);
+ }
+
+ private void doTestMigrateIkeSession_FromNotIkeTunnConnParams(
+ boolean isAutomaticIpVersionSelectionEnabled,
+ boolean isAutomaticNattKeepaliveTimerEnabled) throws Exception {
+ final Ikev2VpnProfile ikeProfile =
+ new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY)
+ .setAuthPsk(TEST_VPN_PSK)
+ .setBypassable(true /* isBypassable */)
+ .setAutomaticNattKeepaliveTimerEnabled(isAutomaticNattKeepaliveTimerEnabled)
+ .setAutomaticIpVersionSelectionEnabled(isAutomaticIpVersionSelectionEnabled)
+ .build();
+
+ final int expectedKeepalive = isAutomaticNattKeepaliveTimerEnabled
+ ? AUTOMATIC_KEEPALIVE_DELAY_SECONDS
+ : DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
+ doTestMigrateIkeSession(ikeProfile.toVpnProfile(),
+ expectedKeepalive,
+ ESP_IP_VERSION_AUTO /* expectedIpVersion */,
+ ESP_ENCAP_TYPE_AUTO /* expectedEncapType */);
+ }
+
+ private void doTestMigrateIkeSession_FromIkeTunnConnParams(
+ boolean isAutomaticIpVersionSelectionEnabled,
+ boolean isAutomaticNattKeepaliveTimerEnabled,
+ int keepaliveInProfile,
+ int ipVersionInProfile,
+ int encapTypeInProfile) throws Exception {
+ // TODO: Update helper function in IkeSessionTestUtils to support building IkeSessionParams
+ // with IP version and encap type when mainline-prod branch support these two APIs.
+ final IkeSessionParams params = getTestIkeSessionParams(true /* testIpv6 */,
+ new IkeFqdnIdentification(TEST_IDENTITY), keepaliveInProfile);
+ final IkeSessionParams ikeSessionParams = new IkeSessionParams.Builder(params)
+ .setIpVersion(ipVersionInProfile)
+ .setEncapType(encapTypeInProfile)
+ .build();
+
+ final IkeTunnelConnectionParams tunnelParams =
+ new IkeTunnelConnectionParams(ikeSessionParams, CHILD_PARAMS);
+ final Ikev2VpnProfile ikeProfile = new Ikev2VpnProfile.Builder(tunnelParams)
+ .setBypassable(true)
+ .setAutomaticNattKeepaliveTimerEnabled(isAutomaticNattKeepaliveTimerEnabled)
+ .setAutomaticIpVersionSelectionEnabled(isAutomaticIpVersionSelectionEnabled)
+ .build();
+
+ final int expectedKeepalive = isAutomaticNattKeepaliveTimerEnabled
+ ? AUTOMATIC_KEEPALIVE_DELAY_SECONDS
+ : ikeSessionParams.getNattKeepAliveDelaySeconds();
+ final int expectedIpVersion = isAutomaticIpVersionSelectionEnabled
+ ? ESP_IP_VERSION_AUTO
+ : ikeSessionParams.getIpVersion();
+ final int expectedEncapType = isAutomaticIpVersionSelectionEnabled
+ ? ESP_ENCAP_TYPE_AUTO
+ : ikeSessionParams.getEncapType();
+ doTestMigrateIkeSession(ikeProfile.toVpnProfile(), expectedKeepalive,
+ expectedIpVersion, expectedEncapType);
+ }
+
+ private void doTestMigrateIkeSession(VpnProfile profile,
+ int expectedKeepalive, int expectedIpVersion, int expectedEncapType) throws Exception {
+ final PlatformVpnSnapshot vpnSnapShot =
+ verifySetupPlatformVpn(profile,
+ createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */),
+ false /* mtuSupportsIpv6 */,
+ expectedKeepalive < DEFAULT_LONG_LIVED_TCP_CONNS_EXPENSIVE_TIMEOUT_SEC);
+ // Simulate a new network coming up
+ vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
+ verify(mIkeSessionWrapper, never()).setNetwork(any(), anyInt(), anyInt(), anyInt());
+
+ vpnSnapShot.nwCb.onCapabilitiesChanged(
+ TEST_NETWORK_2, new NetworkCapabilities.Builder().build());
+ // Verify MOBIKE is triggered
+ verify(mIkeSessionWrapper, timeout(TEST_TIMEOUT_MS)).setNetwork(TEST_NETWORK_2,
+ expectedIpVersion, expectedEncapType, expectedKeepalive);
+
+ vpnSnapShot.vpn.mVpnRunner.exitVpnRunner();
+ }
+
+ @Test
+ public void testLinkPropertiesUpdateTriggerReevaluation() throws Exception {
+ final boolean hasV6 = true;
+
+ mockCarrierConfig(TEST_SUB_ID, TelephonyManager.SIM_STATE_LOADED, TEST_KEEPALIVE_TIMER,
+ PREFERRED_IKE_PROTOCOL_IPV6_ESP);
+ final IkeSessionParams params = getTestIkeSessionParams(hasV6,
+ new IkeFqdnIdentification(TEST_IDENTITY), TEST_KEEPALIVE_TIMER);
+ final IkeTunnelConnectionParams tunnelParams =
+ new IkeTunnelConnectionParams(params, CHILD_PARAMS);
+ final Ikev2VpnProfile ikeProfile = new Ikev2VpnProfile.Builder(tunnelParams)
+ .setBypassable(true)
+ .setAutomaticNattKeepaliveTimerEnabled(false)
+ .setAutomaticIpVersionSelectionEnabled(true)
+ .build();
+ final PlatformVpnSnapshot vpnSnapShot =
+ verifySetupPlatformVpn(ikeProfile.toVpnProfile(),
+ createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */),
+ hasV6 /* mtuSupportsIpv6 */,
+ false /* areLongLivedTcpConnectionsExpensive */);
+ reset(mExecutor);
+
+ // Simulate a new network coming up
+ final LinkProperties lp = new LinkProperties();
+ lp.addLinkAddress(new LinkAddress("192.0.2.2/32"));
+
+ // Have the executor use the real delay to make sure schedule() was called only
+ // once for all calls. Also, arrange for execute() not to call schedule() to avoid
+ // messing with the checks for schedule().
+ mExecutor.delayMs = TestExecutor.REAL_DELAY;
+ mExecutor.executeDirect = true;
+ vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
+ vpnSnapShot.nwCb.onCapabilitiesChanged(
+ TEST_NETWORK_2, new NetworkCapabilities.Builder().build());
+ vpnSnapShot.nwCb.onLinkPropertiesChanged(TEST_NETWORK_2, new LinkProperties(lp));
+ verify(mExecutor).schedule(any(Runnable.class), longThat(it -> it > 0), any());
+ reset(mExecutor);
+
+ final InOrder order = inOrder(mIkeSessionWrapper);
+
+ // Verify the network is started
+ order.verify(mIkeSessionWrapper, timeout(TIMEOUT_CROSSTHREAD_MS)).setNetwork(TEST_NETWORK_2,
+ ESP_IP_VERSION_AUTO, ESP_ENCAP_TYPE_AUTO, TEST_KEEPALIVE_TIMER);
+
+ // Send the same properties, check that no migration is scheduled
+ vpnSnapShot.nwCb.onLinkPropertiesChanged(TEST_NETWORK_2, new LinkProperties(lp));
+ verify(mExecutor, never()).schedule(any(Runnable.class), anyLong(), any());
+
+ // Add v6 address, verify MOBIKE is triggered
+ lp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
+ vpnSnapShot.nwCb.onLinkPropertiesChanged(TEST_NETWORK_2, new LinkProperties(lp));
+ order.verify(mIkeSessionWrapper, timeout(TIMEOUT_CROSSTHREAD_MS)).setNetwork(TEST_NETWORK_2,
+ ESP_IP_VERSION_AUTO, ESP_ENCAP_TYPE_AUTO, TEST_KEEPALIVE_TIMER);
+
+ // Add another v4 address, verify MOBIKE is triggered
+ final LinkProperties stacked = new LinkProperties();
+ stacked.setInterfaceName("v4-" + lp.getInterfaceName());
+ stacked.addLinkAddress(new LinkAddress("192.168.0.1/32"));
+ lp.addStackedLink(stacked);
+ vpnSnapShot.nwCb.onLinkPropertiesChanged(TEST_NETWORK_2, new LinkProperties(lp));
+ order.verify(mIkeSessionWrapper, timeout(TIMEOUT_CROSSTHREAD_MS)).setNetwork(TEST_NETWORK_2,
+ ESP_IP_VERSION_AUTO, ESP_ENCAP_TYPE_AUTO, TEST_KEEPALIVE_TIMER);
+
+ vpnSnapShot.vpn.mVpnRunner.exitVpnRunner();
+ }
+
+ private void mockCarrierConfig(int subId, int simStatus, int keepaliveTimer, int ikeProtocol) {
+ final SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class);
+ doReturn(subId).when(subscriptionInfo).getSubscriptionId();
+ doReturn(List.of(subscriptionInfo)).when(mSubscriptionManager)
+ .getActiveSubscriptionInfoList();
+
+ doReturn(simStatus).when(mTmPerSub).getSimApplicationState();
+ doReturn(TEST_MCCMNC).when(mTmPerSub).getSimOperator(subId);
+
+ final PersistableBundle persistableBundle = new PersistableBundle();
+ persistableBundle.putInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT, keepaliveTimer);
+ persistableBundle.putInt(KEY_PREFERRED_IKE_PROTOCOL_INT, ikeProtocol);
+ // For CarrierConfigManager.isConfigForIdentifiedCarrier check
+ persistableBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+ doReturn(persistableBundle).when(mConfigManager).getConfigForSubId(subId);
+ }
+
+ private CarrierConfigManager.CarrierConfigChangeListener getCarrierConfigListener() {
+ final ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+ verify(mConfigManager).registerCarrierConfigChangeListener(any(), listenerCaptor.capture());
+
+ return listenerCaptor.getValue();
+ }
+
+ @Test
+ public void testNattKeepaliveTimerFromCarrierConfig_noSubId() throws Exception {
+ doTestReadCarrierConfig(new NetworkCapabilities(),
+ TelephonyManager.SIM_STATE_LOADED,
+ PREFERRED_IKE_PROTOCOL_IPV4_UDP,
+ AUTOMATIC_KEEPALIVE_DELAY_SECONDS /* expectedKeepaliveTimer */,
+ ESP_IP_VERSION_AUTO /* expectedIpVersion */,
+ ESP_ENCAP_TYPE_AUTO /* expectedEncapType */,
+ false /* expectedReadFromCarrierConfig*/,
+ true /* areLongLivedTcpConnectionsExpensive */);
+ }
+
+ @Test
+ public void testNattKeepaliveTimerFromCarrierConfig_simAbsent() throws Exception {
+ doTestReadCarrierConfig(new NetworkCapabilities.Builder().build(),
+ TelephonyManager.SIM_STATE_ABSENT,
+ PREFERRED_IKE_PROTOCOL_IPV4_UDP,
+ AUTOMATIC_KEEPALIVE_DELAY_SECONDS /* expectedKeepaliveTimer */,
+ ESP_IP_VERSION_AUTO /* expectedIpVersion */,
+ ESP_ENCAP_TYPE_AUTO /* expectedEncapType */,
+ false /* expectedReadFromCarrierConfig*/,
+ true /* areLongLivedTcpConnectionsExpensive */);
+ }
+
+ @Test
+ public void testNattKeepaliveTimerFromCarrierConfig() throws Exception {
+ doTestReadCarrierConfig(createTestCellNc(),
+ TelephonyManager.SIM_STATE_LOADED,
+ PREFERRED_IKE_PROTOCOL_AUTO,
+ TEST_KEEPALIVE_TIMER /* expectedKeepaliveTimer */,
+ ESP_IP_VERSION_AUTO /* expectedIpVersion */,
+ ESP_ENCAP_TYPE_AUTO /* expectedEncapType */,
+ true /* expectedReadFromCarrierConfig*/,
+ false /* areLongLivedTcpConnectionsExpensive */);
+ }
+
+ @Test
+ public void testNattKeepaliveTimerFromCarrierConfig_NotCell() throws Exception {
+ final NetworkCapabilities nc = new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .setTransportInfo(new WifiInfo.Builder().build())
+ .build();
+ doTestReadCarrierConfig(nc,
+ TelephonyManager.SIM_STATE_LOADED,
+ PREFERRED_IKE_PROTOCOL_IPV4_UDP,
+ AUTOMATIC_KEEPALIVE_DELAY_SECONDS /* expectedKeepaliveTimer */,
+ ESP_IP_VERSION_AUTO /* expectedIpVersion */,
+ ESP_ENCAP_TYPE_AUTO /* expectedEncapType */,
+ false /* expectedReadFromCarrierConfig*/,
+ true /* areLongLivedTcpConnectionsExpensive */);
+ }
+
+ @Test
+ public void testPreferredIpProtocolFromCarrierConfig_v4UDP() throws Exception {
+ doTestReadCarrierConfig(createTestCellNc(),
+ TelephonyManager.SIM_STATE_LOADED,
+ PREFERRED_IKE_PROTOCOL_IPV4_UDP,
+ TEST_KEEPALIVE_TIMER /* expectedKeepaliveTimer */,
+ ESP_IP_VERSION_IPV4 /* expectedIpVersion */,
+ ESP_ENCAP_TYPE_UDP /* expectedEncapType */,
+ true /* expectedReadFromCarrierConfig*/,
+ false /* areLongLivedTcpConnectionsExpensive */);
+ }
+
+ @Test
+ public void testPreferredIpProtocolFromCarrierConfig_v6ESP() throws Exception {
+ doTestReadCarrierConfig(createTestCellNc(),
+ TelephonyManager.SIM_STATE_LOADED,
+ PREFERRED_IKE_PROTOCOL_IPV6_ESP,
+ TEST_KEEPALIVE_TIMER /* expectedKeepaliveTimer */,
+ ESP_IP_VERSION_IPV6 /* expectedIpVersion */,
+ ESP_ENCAP_TYPE_NONE /* expectedEncapType */,
+ true /* expectedReadFromCarrierConfig*/,
+ false /* areLongLivedTcpConnectionsExpensive */);
+ }
+
+ @Test
+ public void testPreferredIpProtocolFromCarrierConfig_v6UDP() throws Exception {
+ doTestReadCarrierConfig(createTestCellNc(),
+ TelephonyManager.SIM_STATE_LOADED,
+ PREFERRED_IKE_PROTOCOL_IPV6_UDP,
+ TEST_KEEPALIVE_TIMER /* expectedKeepaliveTimer */,
+ ESP_IP_VERSION_IPV6 /* expectedIpVersion */,
+ ESP_ENCAP_TYPE_UDP /* expectedEncapType */,
+ true /* expectedReadFromCarrierConfig*/,
+ false /* areLongLivedTcpConnectionsExpensive */);
+ }
+
+ private NetworkCapabilities createTestCellNc() {
+ return new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
+ .setSubscriptionId(TEST_SUB_ID)
+ .build())
+ .build();
+ }
+
+ private void doTestReadCarrierConfig(NetworkCapabilities nc, int simState, int preferredIpProto,
+ int expectedKeepaliveTimer, int expectedIpVersion, int expectedEncapType,
+ boolean expectedReadFromCarrierConfig,
+ boolean areLongLivedTcpConnectionsExpensive)
+ throws Exception {
+ final Ikev2VpnProfile ikeProfile =
+ new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY)
+ .setAuthPsk(TEST_VPN_PSK)
+ .setBypassable(true /* isBypassable */)
+ .setAutomaticNattKeepaliveTimerEnabled(true)
+ .setAutomaticIpVersionSelectionEnabled(true)
+ .build();
+
+ final PlatformVpnSnapshot vpnSnapShot =
+ verifySetupPlatformVpn(ikeProfile.toVpnProfile(),
+ createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */),
+ false /* mtuSupportsIpv6 */,
+ true /* areLongLivedTcpConnectionsExpensive */);
+
+ final CarrierConfigManager.CarrierConfigChangeListener listener =
+ getCarrierConfigListener();
+
+ // Simulate a new network coming up
+ vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
+ // Migration will not be started until receiving network capabilities change.
+ verify(mIkeSessionWrapper, never()).setNetwork(any(), anyInt(), anyInt(), anyInt());
+
+ reset(mIkeSessionWrapper);
+ mockCarrierConfig(TEST_SUB_ID, simState, TEST_KEEPALIVE_TIMER, preferredIpProto);
+ vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK_2, nc);
+ verify(mIkeSessionWrapper, timeout(TEST_TIMEOUT_MS)).setNetwork(TEST_NETWORK_2,
+ expectedIpVersion, expectedEncapType, expectedKeepaliveTimer);
+ if (expectedReadFromCarrierConfig) {
+ final ArgumentCaptor<NetworkCapabilities> ncCaptor =
+ ArgumentCaptor.forClass(NetworkCapabilities.class);
+ verify(mMockNetworkAgent).doSendNetworkCapabilities(ncCaptor.capture());
+
+ final VpnTransportInfo info =
+ (VpnTransportInfo) ncCaptor.getValue().getTransportInfo();
+ assertEquals(areLongLivedTcpConnectionsExpensive,
+ info.areLongLivedTcpConnectionsExpensive());
+ } else {
+ verify(mMockNetworkAgent, never()).doSendNetworkCapabilities(any());
+ }
+
+ reset(mExecutor);
+ reset(mIkeSessionWrapper);
+ reset(mMockNetworkAgent);
+
+ // Trigger carrier config change
+ listener.onCarrierConfigChanged(1 /* logicalSlotIndex */, TEST_SUB_ID,
+ -1 /* carrierId */, -1 /* specificCarrierId */);
+ verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2,
+ expectedIpVersion, expectedEncapType, expectedKeepaliveTimer);
+ // Expect no NetworkCapabilities change.
+ // Call to doSendNetworkCapabilities() will not be triggered.
+ verify(mMockNetworkAgent, never()).doSendNetworkCapabilities(any());
+ }
+
+ @Test
public void testStartPlatformVpn_mtuDoesNotSupportIpv6() throws Exception {
final PlatformVpnSnapshot vpnSnapShot =
verifySetupPlatformVpn(
@@ -1925,14 +2406,19 @@
// Mock network loss and verify a cleanup task is scheduled
vpnSnapShot.nwCb.onLost(TEST_NETWORK);
- verify(mExecutor).schedule(any(Runnable.class), anyLong(), any());
+ verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any());
// Mock new network comes up and the cleanup task is cancelled
vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
- verify(mScheduledFuture).cancel(anyBoolean());
+ verify(mIkeSessionWrapper, never()).setNetwork(any(), anyInt(), anyInt(), anyInt());
+ vpnSnapShot.nwCb.onCapabilitiesChanged(TEST_NETWORK_2,
+ new NetworkCapabilities.Builder().build());
// Verify MOBIKE is triggered
- verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2);
+ verify(mIkeSessionWrapper, timeout(TEST_TIMEOUT_MS)).setNetwork(eq(TEST_NETWORK_2),
+ eq(ESP_IP_VERSION_AUTO) /* ipVersion */,
+ eq(ESP_ENCAP_TYPE_AUTO) /* encapType */,
+ eq(DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT) /* keepaliveDelay */);
// Mock the MOBIKE procedure
vpnSnapShot.ikeCb.onIkeSessionConnectionInfoChanged(createIkeConnectInfo_2());
@@ -2022,9 +2508,13 @@
// Mock network switch
vpnSnapShot.nwCb.onLost(TEST_NETWORK);
vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
+ // The old IKE Session will not be killed until receiving network capabilities change.
+ verify(mIkeSessionWrapper, never()).kill();
+ vpnSnapShot.nwCb.onCapabilitiesChanged(
+ TEST_NETWORK_2, new NetworkCapabilities.Builder().build());
// Verify the old IKE Session is killed
- verify(mIkeSessionWrapper).kill();
+ verify(mIkeSessionWrapper, timeout(TEST_TIMEOUT_MS)).kill();
// Capture callbacks of the new IKE Session
final Pair<IkeSessionCallback, ChildSessionCallback> cbPair =
@@ -2056,19 +2546,16 @@
// Forget the #sendLinkProperties during first setup.
reset(mMockNetworkAgent);
- final ArgumentCaptor<Runnable> runnableCaptor =
- ArgumentCaptor.forClass(Runnable.class);
-
// Mock network loss
vpnSnapShot.nwCb.onLost(TEST_NETWORK);
// Mock the grace period expires
- verify(mExecutor).schedule(runnableCaptor.capture(), anyLong(), any());
- runnableCaptor.getValue().run();
+ verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any());
final ArgumentCaptor<LinkProperties> lpCaptor =
ArgumentCaptor.forClass(LinkProperties.class);
- verify(mMockNetworkAgent).doSendLinkProperties(lpCaptor.capture());
+ verify(mMockNetworkAgent, timeout(TEST_TIMEOUT_MS))
+ .doSendLinkProperties(lpCaptor.capture());
final LinkProperties lp = lpCaptor.getValue();
assertNull(lp.getInterfaceName());
@@ -2112,7 +2599,8 @@
private void verifyMobikeTriggered(List<Network> expected) {
final ArgumentCaptor<Network> networkCaptor = ArgumentCaptor.forClass(Network.class);
- verify(mIkeSessionWrapper).setNetwork(networkCaptor.capture());
+ verify(mIkeSessionWrapper).setNetwork(networkCaptor.capture(),
+ anyInt() /* ipVersion */, anyInt() /* encapType */, anyInt() /* keepaliveDelay */);
assertEquals(expected, Collections.singletonList(networkCaptor.getValue()));
}
@@ -2128,7 +2616,8 @@
connectivityDiagCallback.onDataStallSuspected(report);
// Should not trigger MOBIKE if MOBIKE is not enabled
- verify(mIkeSessionWrapper, never()).setNetwork(any());
+ verify(mIkeSessionWrapper, never()).setNetwork(any() /* network */,
+ anyInt() /* ipVersion */, anyInt() /* encapType */, anyInt() /* keepaliveDelay */);
}
@Test
@@ -2148,7 +2637,8 @@
// Expect to skip other data stall event if MOBIKE was started.
reset(mIkeSessionWrapper);
connectivityDiagCallback.onDataStallSuspected(report);
- verify(mIkeSessionWrapper, never()).setNetwork(any());
+ verify(mIkeSessionWrapper, never()).setNetwork(any() /* network */,
+ anyInt() /* ipVersion */, anyInt() /* encapType */, anyInt() /* keepaliveDelay */);
reset(mIkev2SessionCreator);
@@ -2163,9 +2653,7 @@
// variables(timer counter and boolean) was reset.
((Vpn.IkeV2VpnRunner) vpnSnapShot.vpn.mVpnRunner).onValidationStatus(
NetworkAgent.VALIDATION_STATUS_NOT_VALID);
- final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(mExecutor).schedule(runnableCaptor.capture(), anyLong(), any());
- runnableCaptor.getValue().run();
+ verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any());
verify(mIkev2SessionCreator, never()).createIkeSession(
any(), any(), any(), any(), any(), any());
}
@@ -2191,17 +2679,16 @@
NetworkAgent.VALIDATION_STATUS_NOT_VALID);
// Verify reset is scheduled and run.
- final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(mExecutor).schedule(runnableCaptor.capture(), anyLong(), any());
+ verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any());
// Another invalid status reported should not trigger other scheduled recovery.
reset(mExecutor);
((Vpn.IkeV2VpnRunner) vpnSnapShot.vpn.mVpnRunner).onValidationStatus(
NetworkAgent.VALIDATION_STATUS_NOT_VALID);
- verify(mExecutor, never()).schedule(runnableCaptor.capture(), anyLong(), any());
+ verify(mExecutor, never()).schedule(any(Runnable.class), anyLong(), any());
- runnableCaptor.getValue().run();
- verify(mIkev2SessionCreator).createIkeSession(any(), any(), any(), any(), any(), any());
+ verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS))
+ .createIkeSession(any(), any(), any(), any(), any(), any());
}
@Test
@@ -2473,15 +2960,23 @@
}
@Override
- public long getNextRetryDelaySeconds(int retryCount) {
+ public long getNextRetryDelayMs(int retryCount) {
// Simply return retryCount as the delay seconds for retrying.
- return retryCount;
+ return retryCount * 1000;
}
@Override
public ScheduledThreadPoolExecutor newScheduledThreadPoolExecutor() {
return mExecutor;
}
+
+ public boolean mIgnoreCallingUidChecks = true;
+ @Override
+ public void verifyCallingUidAndPackage(Context context, String packageName, int userId) {
+ if (!mIgnoreCallingUidChecks) {
+ super.verifyCallingUidAndPackage(context, packageName, userId);
+ }
+ }
}
/**
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
index 1febe6d..a917361 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
@@ -42,6 +42,7 @@
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
private const val SERVICE_ID_1 = 1
@@ -51,6 +52,7 @@
private val TEST_LINKADDR = LinkAddress(TEST_ADDR, 64 /* prefixLength */)
private val TEST_NETWORK_1 = mock(Network::class.java)
private val TEST_NETWORK_2 = mock(Network::class.java)
+private val TEST_HOSTNAME = arrayOf("Android_test", "local")
private val SERVICE_1 = NsdServiceInfo("TestServiceName", "_advertisertest._tcp").apply {
port = 12345
@@ -81,10 +83,13 @@
@Before
fun setUp() {
thread.start()
+ doReturn(TEST_HOSTNAME).`when`(mockDeps).generateHostname()
doReturn(mockInterfaceAdvertiser1).`when`(mockDeps).makeAdvertiser(eq(mockSocket1),
- any(), any(), any(), any())
+ any(), any(), any(), any(), eq(TEST_HOSTNAME)
+ )
doReturn(mockInterfaceAdvertiser2).`when`(mockDeps).makeAdvertiser(eq(mockSocket2),
- any(), any(), any(), any())
+ any(), any(), any(), any(), eq(TEST_HOSTNAME)
+ )
doReturn(true).`when`(mockInterfaceAdvertiser1).isProbing(anyInt())
doReturn(true).`when`(mockInterfaceAdvertiser2).isProbing(anyInt())
}
@@ -92,6 +97,7 @@
@After
fun tearDown() {
thread.quitSafely()
+ thread.join()
}
@Test
@@ -106,8 +112,14 @@
postSync { socketCb.onSocketCreated(TEST_NETWORK_1, mockSocket1, listOf(TEST_LINKADDR)) }
val intAdvCbCaptor = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
- verify(mockDeps).makeAdvertiser(eq(mockSocket1),
- eq(listOf(TEST_LINKADDR)), eq(thread.looper), any(), intAdvCbCaptor.capture())
+ verify(mockDeps).makeAdvertiser(
+ eq(mockSocket1),
+ eq(listOf(TEST_LINKADDR)),
+ eq(thread.looper),
+ any(),
+ intAdvCbCaptor.capture(),
+ eq(TEST_HOSTNAME)
+ )
doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
postSync { intAdvCbCaptor.value.onRegisterServiceSucceeded(
@@ -134,9 +146,11 @@
val intAdvCbCaptor1 = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
val intAdvCbCaptor2 = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
verify(mockDeps).makeAdvertiser(eq(mockSocket1), eq(listOf(TEST_LINKADDR)),
- eq(thread.looper), any(), intAdvCbCaptor1.capture())
+ eq(thread.looper), any(), intAdvCbCaptor1.capture(), eq(TEST_HOSTNAME)
+ )
verify(mockDeps).makeAdvertiser(eq(mockSocket2), eq(listOf(TEST_LINKADDR)),
- eq(thread.looper), any(), intAdvCbCaptor2.capture())
+ eq(thread.looper), any(), intAdvCbCaptor2.capture(), eq(TEST_HOSTNAME)
+ )
doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
postSync { intAdvCbCaptor1.value.onRegisterServiceSucceeded(
@@ -192,7 +206,8 @@
val intAdvCbCaptor = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
verify(mockDeps).makeAdvertiser(eq(mockSocket1), eq(listOf(TEST_LINKADDR)),
- eq(thread.looper), any(), intAdvCbCaptor.capture())
+ eq(thread.looper), any(), intAdvCbCaptor.capture(), eq(TEST_HOSTNAME)
+ )
verify(mockInterfaceAdvertiser1).addService(eq(SERVICE_ID_1),
argThat { it.matches(SERVICE_1) })
verify(mockInterfaceAdvertiser1).addService(eq(SERVICE_ID_2),
@@ -216,6 +231,15 @@
verify(mockInterfaceAdvertiser1, atLeastOnce()).destroyNow()
}
+ @Test
+ fun testRemoveService_whenAllServiceRemoved_thenUpdateHostName() {
+ val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps)
+ verify(mockDeps, times(1)).generateHostname()
+ postSync { advertiser.addService(SERVICE_ID_1, SERVICE_1) }
+ postSync { advertiser.removeService(SERVICE_ID_1) }
+ verify(mockDeps, times(2)).generateHostname()
+ }
+
private fun postSync(r: () -> Unit) {
handler.post(r)
handler.waitForIdle(TIMEOUT_MS)
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt
index 6c3f729..7c6cb3e 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAnnouncerTest.kt
@@ -63,6 +63,7 @@
@After
fun tearDown() {
thread.quitSafely()
+ thread.join()
}
private class TestAnnouncementInfo(
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
index 83e7696..7e7e6a4 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
@@ -18,24 +18,33 @@
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.Network;
import android.text.TextUtils;
+import android.util.Pair;
+import com.android.server.connectivity.mdns.MdnsSocketClientBase.SocketCreationCallback;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
/** Tests for {@link MdnsDiscoveryManager}. */
@RunWith(DevSdkIgnoreRunner.class)
@@ -44,6 +53,10 @@
private static final String SERVICE_TYPE_1 = "_googlecast._tcp.local";
private static final String SERVICE_TYPE_2 = "_test._tcp.local";
+ private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_1 =
+ Pair.create(SERVICE_TYPE_1, null);
+ private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_2 =
+ Pair.create(SERVICE_TYPE_2, null);
@Mock private ExecutorProvider executorProvider;
@Mock private MdnsSocketClientBase socketClient;
@@ -65,10 +78,13 @@
discoveryManager = new MdnsDiscoveryManager(executorProvider, socketClient) {
@Override
- MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType) {
- if (serviceType.equals(SERVICE_TYPE_1)) {
+ MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType,
+ @Nullable Network network) {
+ final Pair<String, Network> perNetworkServiceType =
+ Pair.create(serviceType, network);
+ if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_1)) {
return mockServiceTypeClientOne;
- } else if (serviceType.equals(SERVICE_TYPE_2)) {
+ } else if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_2)) {
return mockServiceTypeClientTwo;
}
return null;
@@ -76,13 +92,23 @@
};
}
+ private void verifyListenerRegistration(String serviceType, MdnsServiceBrowserListener listener,
+ MdnsServiceTypeClient client) throws IOException {
+ final ArgumentCaptor<SocketCreationCallback> callbackCaptor =
+ ArgumentCaptor.forClass(SocketCreationCallback.class);
+ discoveryManager.registerListener(serviceType, listener,
+ MdnsSearchOptions.getDefaultOptions());
+ verify(socketClient).startDiscovery();
+ verify(socketClient).notifyNetworkRequested(
+ eq(listener), any(), callbackCaptor.capture());
+ final SocketCreationCallback callback = callbackCaptor.getValue();
+ callback.onSocketCreated(null /* network */);
+ verify(client).startSendAndReceive(listener, MdnsSearchOptions.getDefaultOptions());
+ }
+
@Test
public void registerListener_unregisterListener() throws IOException {
- discoveryManager.registerListener(
- SERVICE_TYPE_1, mockListenerOne, MdnsSearchOptions.getDefaultOptions());
- verify(socketClient).startDiscovery();
- verify(mockServiceTypeClientOne)
- .startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
+ verifyListenerRegistration(SERVICE_TYPE_1, mockListenerOne, mockServiceTypeClientOne);
when(mockServiceTypeClientOne.stopSendAndReceive(mockListenerOne)).thenReturn(true);
discoveryManager.unregisterListener(SERVICE_TYPE_1, mockListenerOne);
@@ -92,44 +118,47 @@
@Test
public void registerMultipleListeners() throws IOException {
- discoveryManager.registerListener(
- SERVICE_TYPE_1, mockListenerOne, MdnsSearchOptions.getDefaultOptions());
- verify(socketClient).startDiscovery();
- verify(mockServiceTypeClientOne)
- .startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
-
- discoveryManager.registerListener(
- SERVICE_TYPE_2, mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
- verify(mockServiceTypeClientTwo)
- .startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
+ verifyListenerRegistration(SERVICE_TYPE_1, mockListenerOne, mockServiceTypeClientOne);
+ verifyListenerRegistration(SERVICE_TYPE_2, mockListenerTwo, mockServiceTypeClientTwo);
}
@Test
- public void onResponseReceived() {
- discoveryManager.registerListener(
- SERVICE_TYPE_1, mockListenerOne, MdnsSearchOptions.getDefaultOptions());
- discoveryManager.registerListener(
- SERVICE_TYPE_2, mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
+ public void onResponseReceived() throws IOException {
+ verifyListenerRegistration(SERVICE_TYPE_1, mockListenerOne, mockServiceTypeClientOne);
+ verifyListenerRegistration(SERVICE_TYPE_2, mockListenerTwo, mockServiceTypeClientTwo);
- MdnsResponse responseForServiceTypeOne = createMockResponse(SERVICE_TYPE_1);
- discoveryManager.onResponseReceived(responseForServiceTypeOne);
- verify(mockServiceTypeClientOne).processResponse(responseForServiceTypeOne);
+ MdnsPacket responseForServiceTypeOne = createMdnsPacket(SERVICE_TYPE_1);
+ final int ifIndex = 1;
+ discoveryManager.onResponseReceived(responseForServiceTypeOne, ifIndex, null /* network */);
+ verify(mockServiceTypeClientOne).processResponse(responseForServiceTypeOne, ifIndex,
+ null /* network */);
- MdnsResponse responseForServiceTypeTwo = createMockResponse(SERVICE_TYPE_2);
- discoveryManager.onResponseReceived(responseForServiceTypeTwo);
- verify(mockServiceTypeClientTwo).processResponse(responseForServiceTypeTwo);
+ MdnsPacket responseForServiceTypeTwo = createMdnsPacket(SERVICE_TYPE_2);
+ discoveryManager.onResponseReceived(responseForServiceTypeTwo, ifIndex, null /* network */);
+ verify(mockServiceTypeClientTwo).processResponse(responseForServiceTypeTwo, ifIndex,
+ null /* network */);
- MdnsResponse responseForSubtype = createMockResponse("subtype._sub._googlecast._tcp.local");
- discoveryManager.onResponseReceived(responseForSubtype);
- verify(mockServiceTypeClientOne).processResponse(responseForSubtype);
+ MdnsPacket responseForSubtype = createMdnsPacket("subtype._sub._googlecast._tcp.local");
+ discoveryManager.onResponseReceived(responseForSubtype, ifIndex, null /* network */);
+ verify(mockServiceTypeClientOne).processResponse(responseForSubtype, ifIndex,
+ null /* network */);
}
- private MdnsResponse createMockResponse(String serviceType) {
- MdnsPointerRecord mockPointerRecord = mock(MdnsPointerRecord.class);
- MdnsResponse mockResponse = mock(MdnsResponse.class);
- when(mockResponse.getPointerRecords())
- .thenReturn(Collections.singletonList(mockPointerRecord));
- when(mockPointerRecord.getName()).thenReturn(TextUtils.split(serviceType, "\\."));
- return mockResponse;
+ private MdnsPacket createMdnsPacket(String serviceType) {
+ final String[] type = TextUtils.split(serviceType, "\\.");
+ final ArrayList<String> name = new ArrayList<>(type.length + 1);
+ name.add("TestName");
+ name.addAll(Arrays.asList(type));
+ return new MdnsPacket(0 /* flags */,
+ Collections.emptyList() /* questions */,
+ List.of(new MdnsPointerRecord(
+ type,
+ 0L /* receiptTimeMillis */,
+ false /* cacheFlush */,
+ 120000 /* ttlMillis */,
+ name.toArray(new String[0])
+ )) /* answers */,
+ Collections.emptyList() /* authorityRecords */,
+ Collections.emptyList() /* additionalRecords */);
}
}
\ No newline at end of file
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt
index 4a806b1..0ca0835 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt
@@ -55,6 +55,7 @@
private val TEST_ADDRS = listOf(LinkAddress(parseNumericAddress("2001:db8::123"), 64))
private val TEST_BUFFER = ByteArray(1300)
+private val TEST_HOSTNAME = arrayOf("Android_test", "local")
private const val TEST_SERVICE_ID_1 = 42
private val TEST_SERVICE_1 = NsdServiceInfo().apply {
@@ -88,12 +89,23 @@
private val packetHandler get() = packetHandlerCaptor.value
private val advertiser by lazy {
- MdnsInterfaceAdvertiser(LOG_TAG, socket, TEST_ADDRS, thread.looper, TEST_BUFFER, cb, deps)
+ MdnsInterfaceAdvertiser(
+ LOG_TAG,
+ socket,
+ TEST_ADDRS,
+ thread.looper,
+ TEST_BUFFER,
+ cb,
+ deps,
+ TEST_HOSTNAME
+ )
}
@Before
fun setUp() {
- doReturn(repository).`when`(deps).makeRecordRepository(any())
+ doReturn(repository).`when`(deps).makeRecordRepository(any(),
+ eq(TEST_HOSTNAME)
+ )
doReturn(replySender).`when`(deps).makeReplySender(anyString(), any(), any(), any())
doReturn(announcer).`when`(deps).makeMdnsAnnouncer(anyString(), any(), any(), any())
doReturn(prober).`when`(deps).makeMdnsProber(anyString(), any(), any(), any())
@@ -124,6 +136,7 @@
@After
fun tearDown() {
thread.quitSafely()
+ thread.join()
}
@Test
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
index 9d42a65..90c43e5 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
@@ -19,9 +19,9 @@
import static com.android.server.connectivity.mdns.MdnsSocketProvider.SocketCallback;
import static com.android.server.connectivity.mdns.MulticastPacketReader.PacketHandler;
-import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.timeout;
@@ -62,6 +62,7 @@
@Mock private MdnsInterfaceSocket mSocket;
@Mock private MdnsServiceBrowserListener mListener;
@Mock private MdnsSocketClientBase.Callback mCallback;
+ @Mock private MdnsSocketClientBase.SocketCreationCallback mSocketCreationCallback;
private MdnsMultinetworkSocketClient mSocketClient;
private Handler mHandler;
@@ -78,7 +79,8 @@
private SocketCallback expectSocketCallback() {
final ArgumentCaptor<SocketCallback> callbackCaptor =
ArgumentCaptor.forClass(SocketCallback.class);
- mHandler.post(() -> mSocketClient.notifyNetworkRequested(mListener, mNetwork));
+ mHandler.post(() -> mSocketClient.notifyNetworkRequested(
+ mListener, mNetwork, mSocketCreationCallback));
verify(mProvider, timeout(DEFAULT_TIMEOUT))
.requestSocket(eq(mNetwork), callbackCaptor.capture());
return callbackCaptor.getValue();
@@ -107,6 +109,7 @@
doReturn(createEmptyNetworkInterface()).when(mSocket).getInterface();
// Notify socket created
callback.onSocketCreated(mNetwork, mSocket, List.of());
+ verify(mSocketCreationCallback).onSocketCreated(mNetwork);
// Send packet to IPv4 with target network and verify sending has been called.
mSocketClient.sendMulticastPacket(ipv4Packet, mNetwork);
@@ -138,6 +141,7 @@
doReturn(createEmptyNetworkInterface()).when(mSocket).getInterface();
// Notify socket created
callback.onSocketCreated(mNetwork, mSocket, List.of());
+ verify(mSocketCreationCallback).onSocketCreated(mNetwork);
final ArgumentCaptor<PacketHandler> handlerCaptor =
ArgumentCaptor.forClass(PacketHandler.class);
@@ -146,16 +150,23 @@
// Send the data and verify the received records.
final PacketHandler handler = handlerCaptor.getValue();
handler.handlePacket(data, data.length, null /* src */);
- final ArgumentCaptor<MdnsResponse> responseCaptor =
- ArgumentCaptor.forClass(MdnsResponse.class);
- verify(mCallback).onResponseReceived(responseCaptor.capture());
- final MdnsResponse response = responseCaptor.getValue();
- assertTrue(response.hasPointerRecords());
- assertArrayEquals("_testtype._tcp.local".split("\\."),
- response.getPointerRecords().get(0).getName());
- assertTrue(response.hasServiceRecord());
- assertEquals("testservice", response.getServiceRecord().getServiceInstanceName());
- assertEquals("Android.local".split("\\."),
- response.getServiceRecord().getServiceHost());
+ final ArgumentCaptor<MdnsPacket> responseCaptor =
+ ArgumentCaptor.forClass(MdnsPacket.class);
+ verify(mCallback).onResponseReceived(responseCaptor.capture(), anyInt(), any());
+ final MdnsPacket response = responseCaptor.getValue();
+ assertEquals(0, response.questions.size());
+ assertEquals(0, response.additionalRecords.size());
+ assertEquals(0, response.authorityRecords.size());
+
+ final String[] serviceName = "testservice._testtype._tcp.local".split("\\.");
+ assertEquals(List.of(
+ new MdnsPointerRecord("_testtype._tcp.local".split("\\."),
+ 0L /* receiptTimeMillis */, false /* cacheFlush */, 4500000 /* ttlMillis */,
+ serviceName),
+ new MdnsServiceRecord(serviceName, 0L /* receiptTimeMillis */,
+ false /* cacheFlush */, 4500000 /* ttlMillis */, 0 /* servicePriority */,
+ 0 /* serviceWeight */, 31234 /* servicePort */,
+ new String[] { "Android", "local" } /* serviceHost */)
+ ), response.answers);
}
}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsProberTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsProberTest.kt
index a2dbbc6..2b5423b 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsProberTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsProberTest.kt
@@ -68,6 +68,7 @@
@After
fun tearDown() {
thread.quitSafely()
+ thread.join()
}
private class TestProbeInfo(probeRecords: List<MdnsRecord>, private val delayMs: Long = 1L) :
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt
index ecc11ec..44e0d08 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt
@@ -67,7 +67,6 @@
class MdnsRecordRepositoryTest {
private val thread = HandlerThread(MdnsRecordRepositoryTest::class.simpleName)
private val deps = object : Dependencies() {
- override fun getHostname() = TEST_HOSTNAME
override fun getInterfaceInetAddresses(iface: NetworkInterface) =
Collections.enumeration(TEST_ADDRESSES.map { it.address })
}
@@ -80,11 +79,12 @@
@After
fun tearDown() {
thread.quitSafely()
+ thread.join()
}
@Test
fun testAddServiceAndProbe() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
assertEquals(0, repository.servicesCount)
assertEquals(-1, repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1))
assertEquals(1, repository.servicesCount)
@@ -117,7 +117,7 @@
@Test
fun testAddAndConflicts() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
assertFailsWith(NameConflictException::class) {
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_1)
@@ -126,7 +126,7 @@
@Test
fun testInvalidReuseOfServiceId() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
assertFailsWith(IllegalArgumentException::class) {
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_2)
@@ -135,7 +135,7 @@
@Test
fun testHasActiveService() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
assertFalse(repository.hasActiveService(TEST_SERVICE_ID_1))
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
@@ -152,7 +152,7 @@
@Test
fun testExitAnnouncements() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
repository.onAdvertisementSent(TEST_SERVICE_ID_1)
@@ -181,7 +181,7 @@
@Test
fun testExitingServiceReAdded() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
repository.onAdvertisementSent(TEST_SERVICE_ID_1)
repository.exitService(TEST_SERVICE_ID_1)
@@ -195,7 +195,7 @@
@Test
fun testOnProbingSucceeded() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
val announcementInfo = repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
repository.onAdvertisementSent(TEST_SERVICE_ID_1)
val packet = announcementInfo.getPacket(0)
@@ -319,7 +319,7 @@
@Test
fun testGetReply() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
val questions = listOf(MdnsPointerRecord(arrayOf("_testservice", "_tcp", "local"),
0L /* receiptTimeMillis */,
@@ -404,7 +404,7 @@
@Test
fun testGetConflictingServices() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2)
@@ -432,7 +432,7 @@
@Test
fun testGetConflictingServices_IdenticalService() {
- val repository = MdnsRecordRepository(thread.looper, deps)
+ val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2)
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsResponseDecoderTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsResponseDecoderTests.java
index 4cae447..b0a1f18 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsResponseDecoderTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsResponseDecoderTests.java
@@ -16,20 +16,26 @@
package com.android.server.connectivity.mdns;
+import static android.net.InetAddresses.parseNumericAddress;
+
import static com.android.server.connectivity.mdns.MdnsResponseDecoder.Clock;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
+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.mockito.Mockito.mock;
-import android.net.InetAddresses;
import android.net.Network;
+import android.util.ArraySet;
import com.android.net.module.util.HexDump;
+import com.android.server.connectivity.mdns.MdnsResponseTests.MdnsInet4AddressRecord;
+import com.android.server.connectivity.mdns.MdnsResponseTests.MdnsInet6AddressRecord;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -43,8 +49,11 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
-import java.util.LinkedList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
@RunWith(DevSdkIgnoreRunner.class)
@DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
@@ -147,6 +156,48 @@
+ "010001000000780004C0A8018A0000000000000000000000000000"
+ "000000");
+ // MDNS record for name "testhost1" with an IPv4 address of 10.1.2.3. Also set cache flush bit
+ // for the records changed.
+ private static final byte[] DATAIN_IPV4_1 = HexDump.hexStringToByteArray(
+ "0974657374686f73743100000180010000007800040a010203");
+ // MDNS record for name "testhost1" with an IPv4 address of 10.1.2.4. Also set cache flush bit
+ // for the records changed.
+ private static final byte[] DATAIN_IPV4_2 = HexDump.hexStringToByteArray(
+ "0974657374686f73743100000180010000007800040a010204");
+ // MDNS record w/name "testhost1" & IPv6 address of aabb:ccdd:1122:3344:a0b0:c0d0:1020:3040.
+ // Also set cache flush bit for the records changed.
+ private static final byte[] DATAIN_IPV6_1 = HexDump.hexStringToByteArray(
+ "0974657374686f73743100001c8001000000780010aabbccdd11223344a0b0c0d010203040");
+ // MDNS record w/name "testhost1" & IPv6 address of aabb:ccdd:1122:3344:a0b0:c0d0:1020:3030.
+ // Also set cache flush bit for the records changed.
+ private static final byte[] DATAIN_IPV6_2 = HexDump.hexStringToByteArray(
+ "0974657374686f73743100001c8001000000780010aabbccdd11223344a0b0c0d010203030");
+ // MDNS record w/name "test" & PTR to foo.bar.quxx
+ private static final byte[] DATAIN_PTR_1 = HexDump.hexStringToByteArray(
+ "047465737400000C000100001194000E03666F6F03626172047175787800");
+ // MDNS record w/name "test" & PTR to foo.bar.quxy
+ private static final byte[] DATAIN_PTR_2 = HexDump.hexStringToByteArray(
+ "047465737400000C000100001194000E03666F6F03626172047175787900");
+ // SRV record for: scapy.DNSRRSRV(rrname='foo.bar.quxx', ttl=120, port=1234, target='testhost1')
+ private static final byte[] DATAIN_SERVICE_1 = HexDump.hexStringToByteArray(
+ "03666f6f03626172047175787800002100010000007800110000000004d20974657374686f73743100");
+ // SRV record for: scapy.DNSRRSRV(rrname='foo.bar.quxx', ttl=120, port=1234, target='testhost2')
+ private static final byte[] DATAIN_SERVICE_2 = HexDump.hexStringToByteArray(
+ "03666f6f03626172047175787800002100010000007800110000000004d20974657374686f73743200");
+ // TXT record for: scapy.DNSRR(rrname='foo.bar.quxx', type='TXT', ttl=120,
+ // rdata=[b'a=hello there', b'b=1234567890', b'xyz=!$$$'])
+ private static final byte[] DATAIN_TEXT_1 = HexDump.hexStringToByteArray(
+ "03666f6f03626172047175787800001000010000007800240d613d68656c6c6f2074686572650c623d3132"
+ + "33343536373839300878797a3d21242424");
+
+ // TXT record for: scapy.DNSRR(rrname='foo.bar.quxx', type='TXT', ttl=120,
+ // rdata=[b'a=hello there', b'b=1234567890', b'xyz=!$$$'])
+ private static final byte[] DATAIN_TEXT_2 = HexDump.hexStringToByteArray(
+ "03666f6f03626172047175787800001000010000007800240d613d68656c6c6f2074686572650c623d3132"
+ + "33343536373839300878797a3d21402324");
+
+ private static final String[] DATAIN_SERVICE_NAME_1 = new String[] { "foo", "bar", "quxx" };
+
private static final String CAST_SERVICE_NAME = "_googlecast";
private static final String[] CAST_SERVICE_TYPE =
new String[] {CAST_SERVICE_NAME, "_tcp", "local"};
@@ -154,41 +205,28 @@
private static final String[] MATTER_SERVICE_TYPE =
new String[] {MATTER_SERVICE_NAME, "_tcp", "local"};
- private final List<MdnsResponse> responses = new LinkedList<>();
+ private ArraySet<MdnsResponse> responses;
private final Clock mClock = mock(Clock.class);
@Before
- public void setUp() {
+ public void setUp() throws Exception {
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
assertNotNull(data);
- DatagramPacket packet = new DatagramPacket(data, data.length);
- packet.setSocketAddress(
- new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT));
- responses.clear();
- int errorCode = decoder.decode(
- packet, responses, MdnsSocket.INTERFACE_INDEX_UNSPECIFIED, mock(Network.class));
- assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
+ responses = decode(decoder, data);
assertEquals(1, responses.size());
}
@Test
- public void testDecodeWithNullServiceType() {
+ public void testDecodeWithNullServiceType() throws Exception {
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
- assertNotNull(data);
- DatagramPacket packet = new DatagramPacket(data, data.length);
- packet.setSocketAddress(
- new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT));
- responses.clear();
- int errorCode = decoder.decode(
- packet, responses, MdnsSocket.INTERFACE_INDEX_UNSPECIFIED, mock(Network.class));
- assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
+ responses = decode(decoder, data);
assertEquals(2, responses.size());
}
@Test
public void testDecodeMultipleAnswerPacket() throws IOException {
- MdnsResponse response = responses.get(0);
+ MdnsResponse response = responses.valueAt(0);
assertTrue(response.isComplete());
MdnsInetAddressRecord inet4AddressRecord = response.getInet4AddressRecord();
@@ -235,16 +273,10 @@
public void testDecodeIPv6AnswerPacket() throws IOException {
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
assertNotNull(data6);
- DatagramPacket packet = new DatagramPacket(data6, data6.length);
- packet.setSocketAddress(
- new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT));
- responses.clear();
- int errorCode = decoder.decode(
- packet, responses, MdnsSocket.INTERFACE_INDEX_UNSPECIFIED, mock(Network.class));
- assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
-
- MdnsResponse response = responses.get(0);
+ responses = decode(decoder, data6);
+ assertEquals(1, responses.size());
+ MdnsResponse response = responses.valueAt(0);
assertTrue(response.isComplete());
MdnsInetAddressRecord inet6AddressRecord = response.getInet6AddressRecord();
@@ -259,104 +291,297 @@
@Test
public void testIsComplete() {
- MdnsResponse response = responses.get(0);
+ MdnsResponse response = new MdnsResponse(responses.valueAt(0));
assertTrue(response.isComplete());
response.clearPointerRecords();
+ // The service name is still known in MdnsResponse#getServiceName
+ assertTrue(response.isComplete());
+
+ response = new MdnsResponse(responses.valueAt(0));
+ response.clearInet4AddressRecords();
assertFalse(response.isComplete());
- response = responses.get(0);
- response.setInet4AddressRecord(null);
+ response.addInet6AddressRecord(new MdnsInetAddressRecord(new String[] { "testhostname" },
+ 0L /* receiptTimeMillis */, false /* cacheFlush */, 1234L /* ttlMillis */,
+ parseNumericAddress("2008:db1::123")));
+ assertTrue(response.isComplete());
+
+ response.clearInet6AddressRecords();
assertFalse(response.isComplete());
- response = responses.get(0);
- response.setInet6AddressRecord(null);
- assertFalse(response.isComplete());
-
- response = responses.get(0);
+ response = new MdnsResponse(responses.valueAt(0));
response.setServiceRecord(null);
assertFalse(response.isComplete());
- response = responses.get(0);
+ response = new MdnsResponse(responses.valueAt(0));
response.setTextRecord(null);
assertFalse(response.isComplete());
}
@Test
- public void decode_withInterfaceIndex_populatesInterfaceIndex() {
+ public void decode_withInterfaceIndex_populatesInterfaceIndex() throws Exception {
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
assertNotNull(data6);
DatagramPacket packet = new DatagramPacket(data6, data6.length);
packet.setSocketAddress(
new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT));
- responses.clear();
+ final MdnsPacket parsedPacket = MdnsResponseDecoder.parseResponse(data6, data6.length);
+ assertNotNull(parsedPacket);
+
final Network network = mock(Network.class);
- int errorCode = decoder.decode(
- packet, responses, /* interfaceIndex= */ 10, network);
- assertEquals(errorCode, MdnsResponseDecoder.SUCCESS);
+ responses = decoder.augmentResponses(parsedPacket,
+ /* existingResponses= */ Collections.emptyList(),
+ /* interfaceIndex= */ 10, network /* expireOnExit= */);
+
assertEquals(responses.size(), 1);
- assertEquals(responses.get(0).getInterfaceIndex(), 10);
- assertEquals(network, responses.get(0).getNetwork());
+ assertEquals(responses.valueAt(0).getInterfaceIndex(), 10);
+ assertEquals(network, responses.valueAt(0).getNetwork());
}
@Test
- public void decode_singleHostname_multipleSrvRecords_flagEnabled_multipleCompleteResponses() {
+ public void decode_singleHostname_multipleSrvRecords_flagEnabled_multipleCompleteResponses()
+ throws Exception {
//MdnsScannerConfigsFlagsImpl.allowMultipleSrvRecordsPerHost.override(true);
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, MATTER_SERVICE_TYPE);
assertNotNull(matterDuplicateHostname);
- DatagramPacket packet =
- new DatagramPacket(matterDuplicateHostname, matterDuplicateHostname.length);
-
- packet.setSocketAddress(
- new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT));
-
- responses.clear();
- int errorCode = decoder.decode(
- packet, responses, /* interfaceIndex= */ 0, mock(Network.class));
- assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
+ responses = decode(decoder, matterDuplicateHostname);
// This should emit two records:
assertEquals(2, responses.size());
- MdnsResponse response1 = responses.get(0);
- MdnsResponse response2 = responses.get(0);
+ MdnsResponse response1 = responses.valueAt(0);
+ MdnsResponse response2 = responses.valueAt(0);
// Both of which are complete:
assertTrue(response1.isComplete());
assertTrue(response2.isComplete());
// And should both have the same IPv6 address:
- assertEquals(InetAddresses.parseNumericAddress("2605:a601:a846:5700:3e61:5ff:fe0c:89f8"),
- response1.getInet6AddressRecord().getInet6Address());
- assertEquals(InetAddresses.parseNumericAddress("2605:a601:a846:5700:3e61:5ff:fe0c:89f8"),
- response2.getInet6AddressRecord().getInet6Address());
+ assertTrue(response1.getInet6AddressRecords().stream().anyMatch(
+ record -> record.getInet6Address().equals(
+ parseNumericAddress("2605:a601:a846:5700:3e61:5ff:fe0c:89f8"))));
+ assertTrue(response2.getInet6AddressRecords().stream().anyMatch(
+ record -> record.getInet6Address().equals(
+ parseNumericAddress("2605:a601:a846:5700:3e61:5ff:fe0c:89f8"))));
}
@Test
@Ignore("MdnsConfigs is not configurable currently.")
- public void decode_singleHostname_multipleSrvRecords_flagDisabled_singleCompleteResponse() {
+ public void decode_singleHostname_multipleSrvRecords_flagDisabled_singleCompleteResponse()
+ throws Exception {
//MdnsScannerConfigsFlagsImpl.allowMultipleSrvRecordsPerHost.override(false);
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, MATTER_SERVICE_TYPE);
assertNotNull(matterDuplicateHostname);
- DatagramPacket packet =
- new DatagramPacket(matterDuplicateHostname, matterDuplicateHostname.length);
-
- packet.setSocketAddress(
- new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT));
-
- responses.clear();
- int errorCode = decoder.decode(
- packet, responses, /* interfaceIndex= */ 0, mock(Network.class));
- assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
+ responses = decode(decoder, matterDuplicateHostname);
// This should emit only two records:
assertEquals(2, responses.size());
// But only the first is complete:
- assertTrue(responses.get(0).isComplete());
- assertFalse(responses.get(1).isComplete());
+ assertTrue(responses.valueAt(0).isComplete());
+ assertFalse(responses.valueAt(1).isComplete());
+ }
+
+ @Test
+ public void testDecodeWithIpv4AddressChange() throws IOException {
+ MdnsResponse response = makeMdnsResponse(0, DATAIN_SERVICE_NAME_1, List.of(
+ new PacketAndRecordClass(DATAIN_PTR_1,
+ MdnsPointerRecord.class),
+ new PacketAndRecordClass(DATAIN_SERVICE_1,
+ MdnsServiceRecord.class),
+ new PacketAndRecordClass(DATAIN_IPV4_1,
+ MdnsInet4AddressRecord.class)));
+ // Now update the response with another address
+ final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
+ final ArraySet<MdnsResponse> updatedResponses = decode(
+ decoder, makeResponsePacket(DATAIN_IPV4_2), List.of(response));
+ assertEquals(1, updatedResponses.size());
+ assertEquals(parseNumericAddress("10.1.2.4"),
+ updatedResponses.valueAt(0).getInet4AddressRecord().getInet4Address());
+ assertEquals(parseNumericAddress("10.1.2.3"),
+ response.getInet4AddressRecord().getInet4Address());
+ }
+
+ @Test
+ public void testDecodeWithIpv6AddressChange() throws IOException {
+ MdnsResponse response = makeMdnsResponse(0, DATAIN_SERVICE_NAME_1, List.of(
+ new PacketAndRecordClass(DATAIN_PTR_1,
+ MdnsPointerRecord.class),
+ new PacketAndRecordClass(DATAIN_SERVICE_1,
+ MdnsServiceRecord.class),
+ new PacketAndRecordClass(DATAIN_IPV6_1,
+ MdnsInet6AddressRecord.class)));
+ // Now update the response with another address
+ final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
+ final ArraySet<MdnsResponse> updatedResponses = decode(
+ decoder, makeResponsePacket(DATAIN_IPV6_2), List.of(response));
+ assertEquals(1, updatedResponses.size());
+ assertEquals(parseNumericAddress("aabb:ccdd:1122:3344:a0b0:c0d0:1020:3030"),
+ updatedResponses.valueAt(0).getInet6AddressRecord().getInet6Address());
+ assertEquals(parseNumericAddress("aabb:ccdd:1122:3344:a0b0:c0d0:1020:3040"),
+ response.getInet6AddressRecord().getInet6Address());
+ }
+
+ @Test
+ public void testDecodeWithChangeOnText() throws IOException {
+ MdnsResponse response = makeMdnsResponse(0, DATAIN_SERVICE_NAME_1, List.of(
+ new PacketAndRecordClass(DATAIN_PTR_1,
+ MdnsPointerRecord.class),
+ new PacketAndRecordClass(DATAIN_SERVICE_1,
+ MdnsServiceRecord.class),
+ new PacketAndRecordClass(DATAIN_TEXT_1,
+ MdnsTextRecord.class)));
+ // Now update the response with another address
+ final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
+ final ArraySet<MdnsResponse> updatedResponses = decode(
+ decoder, makeResponsePacket(DATAIN_TEXT_2), List.of(response));
+ assertEquals(1, updatedResponses.size());
+ assertEquals(List.of(
+ new MdnsServiceInfo.TextEntry("a", "hello there"),
+ new MdnsServiceInfo.TextEntry("b", "1234567890"),
+ new MdnsServiceInfo.TextEntry("xyz", "!@#$")),
+ updatedResponses.valueAt(0).getTextRecord().getEntries());
+ }
+
+ @Test
+ public void testDecodeWithChangeOnService() throws IOException {
+ MdnsResponse response = makeMdnsResponse(0, DATAIN_SERVICE_NAME_1, List.of(
+ new PacketAndRecordClass(DATAIN_PTR_1,
+ MdnsPointerRecord.class),
+ new PacketAndRecordClass(DATAIN_SERVICE_1,
+ MdnsServiceRecord.class),
+ new PacketAndRecordClass(DATAIN_IPV4_1,
+ MdnsInet4AddressRecord.class)));
+ assertArrayEquals(new String[] { "testhost1" },
+ response.getServiceRecord().getServiceHost());
+ assertNotNull(response.getInet4AddressRecord());
+ // Now update the response with another hostname
+ final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
+ final ArraySet<MdnsResponse> updatedResponses = decode(
+ decoder, makeResponsePacket(DATAIN_SERVICE_2), List.of(response));
+ assertEquals(1, updatedResponses.size());
+ assertArrayEquals(new String[] { "testhost2" },
+ updatedResponses.valueAt(0).getServiceRecord().getServiceHost());
+ // Hostname changed, so address records are dropped
+ assertNull(updatedResponses.valueAt(0).getInet4AddressRecord());
+ }
+
+ @Test
+ public void testDecodeWithChangeOnPtr() throws IOException {
+ MdnsResponse response = makeMdnsResponse(0, DATAIN_SERVICE_NAME_1, List.of(
+ new PacketAndRecordClass(DATAIN_PTR_1,
+ MdnsPointerRecord.class),
+ new PacketAndRecordClass(DATAIN_SERVICE_1,
+ MdnsServiceRecord.class)));
+ // Now update the response with another address
+ final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
+ final ArraySet<MdnsResponse> updatedResponses = decode(
+ decoder, makeResponsePacket(DATAIN_PTR_2), List.of(response));
+ assertEquals(1, updatedResponses.size());
+ assertArrayEquals(new String[] { "foo", "bar", "quxy" },
+ updatedResponses.valueAt(0).getPointerRecords().get(0).getPointer());
+ }
+
+ @Test
+ public void testDecodeWithNoChange() throws IOException {
+ List<PacketAndRecordClass> recordList =
+ Arrays.asList(
+ new PacketAndRecordClass(DATAIN_IPV4_1, MdnsInet4AddressRecord.class),
+ new PacketAndRecordClass(DATAIN_IPV6_1, MdnsInet6AddressRecord.class),
+ new PacketAndRecordClass(DATAIN_PTR_1, MdnsPointerRecord.class),
+ new PacketAndRecordClass(DATAIN_SERVICE_2, MdnsServiceRecord.class),
+ new PacketAndRecordClass(DATAIN_TEXT_1, MdnsTextRecord.class));
+ // Create a two identical responses.
+ MdnsResponse response = makeMdnsResponse(0, DATAIN_SERVICE_NAME_1, recordList);
+
+ final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
+ final byte[] identicalResponse = makeResponsePacket(
+ recordList.stream().map(p -> p.packetData).collect(Collectors.toList()));
+ final ArraySet<MdnsResponse> changes = decode(
+ decoder, identicalResponse, List.of(response));
+
+ // Decoding should not indicate any change.
+ assertEquals(0, changes.size());
+ }
+
+ private static MdnsResponse makeMdnsResponse(long time, String[] serviceName,
+ List<PacketAndRecordClass> responseList) throws IOException {
+ final MdnsResponse response = new MdnsResponse(
+ time, serviceName, 999 /* interfaceIndex */, mock(Network.class));
+ for (PacketAndRecordClass responseData : responseList) {
+ DatagramPacket packet =
+ new DatagramPacket(responseData.packetData, responseData.packetData.length);
+ MdnsPacketReader reader = new MdnsPacketReader(packet);
+ String[] name = reader.readLabels();
+ reader.skip(2); // skip record type indication.
+ // Apply the right kind of record to the response.
+ if (responseData.recordClass == MdnsInet4AddressRecord.class) {
+ response.addInet4AddressRecord(new MdnsInet4AddressRecord(name, reader));
+ } else if (responseData.recordClass == MdnsInet6AddressRecord.class) {
+ response.addInet6AddressRecord(new MdnsInet6AddressRecord(name, reader));
+ } else if (responseData.recordClass == MdnsPointerRecord.class) {
+ response.addPointerRecord(new MdnsPointerRecord(name, reader));
+ } else if (responseData.recordClass == MdnsServiceRecord.class) {
+ response.setServiceRecord(new MdnsServiceRecord(name, reader));
+ } else if (responseData.recordClass == MdnsTextRecord.class) {
+ response.setTextRecord(new MdnsTextRecord(name, reader));
+ } else {
+ fail("Unsupported/unexpected MdnsRecord subtype used in test - invalid test!");
+ }
+ }
+ return response;
+ }
+
+ private static byte[] makeResponsePacket(byte[] responseRecord) throws IOException {
+ return makeResponsePacket(List.of(responseRecord));
+ }
+
+ private static byte[] makeResponsePacket(List<byte[]> responseRecords) throws IOException {
+ final MdnsPacketWriter writer = new MdnsPacketWriter(1500);
+ writer.writeUInt16(0); // Transaction ID (advertisement: 0)
+ writer.writeUInt16(0x8400); // Flags: response, authoritative
+ writer.writeUInt16(0); // questions count
+ writer.writeUInt16(responseRecords.size()); // answers count
+ writer.writeUInt16(0); // authority entries count
+ writer.writeUInt16(0); // additional records count
+
+ for (byte[] record : responseRecords) {
+ writer.writeBytes(record);
+ }
+ final DatagramPacket packet = writer.getPacket(new InetSocketAddress(0 /* port */));
+ return Arrays.copyOf(packet.getData(), packet.getLength());
+ }
+
+
+ // This helper class just wraps the data bytes of a response packet with the contained record
+ // type.
+ // Its only purpose is to make the test code a bit more readable.
+ private static class PacketAndRecordClass {
+ public final byte[] packetData;
+ public final Class<?> recordClass;
+
+ PacketAndRecordClass(byte[] data, Class<?> c) {
+ packetData = data;
+ recordClass = c;
+ }
+ }
+
+ private ArraySet<MdnsResponse> decode(MdnsResponseDecoder decoder, byte[] data)
+ throws MdnsPacket.ParseException {
+ return decode(decoder, data, Collections.emptyList());
+ }
+
+ private ArraySet<MdnsResponse> decode(MdnsResponseDecoder decoder, byte[] data,
+ Collection<MdnsResponse> existingResponses) throws MdnsPacket.ParseException {
+ final MdnsPacket parsedPacket = MdnsResponseDecoder.parseResponse(data, data.length);
+ assertNotNull(parsedPacket);
+
+ return decoder.augmentResponses(parsedPacket,
+ existingResponses,
+ MdnsSocket.INTERFACE_INDEX_UNSPECIFIED, mock(Network.class));
}
}
\ No newline at end of file
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsResponseTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsResponseTests.java
index ec57dc8..3f5e7a1 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsResponseTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsResponseTests.java
@@ -16,6 +16,8 @@
package com.android.server.connectivity.mdns;
+import static android.net.InetAddresses.parseNumericAddress;
+
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static org.junit.Assert.assertEquals;
@@ -23,22 +25,21 @@
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.mockito.Mockito.mock;
+import static java.util.Collections.emptyList;
+
import android.net.Network;
import com.android.net.module.util.HexDump;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.net.DatagramPacket;
-import java.util.Arrays;
import java.util.List;
// The record test data does not use compressed names (label pointers), since that would require
@@ -48,36 +49,24 @@
public class MdnsResponseTests {
private static final String TAG = "MdnsResponseTests";
// MDNS response packet for name "test" with an IPv4 address of 10.1.2.3
- private static final byte[] dataIn_ipv4_1 = HexDump.hexStringToByteArray(
+ private static final byte[] DATAIN_IPV4 = HexDump.hexStringToByteArray(
"0474657374000001" + "0001000011940004" + "0A010203");
- // MDNS response packet for name "tess" with an IPv4 address of 10.1.2.4
- private static final byte[] dataIn_ipv4_2 = HexDump.hexStringToByteArray(
- "0474657373000001" + "0001000011940004" + "0A010204");
// MDNS response w/name "test" & IPv6 address of aabb:ccdd:1122:3344:a0b0:c0d0:1020:3040
- private static final byte[] dataIn_ipv6_1 = HexDump.hexStringToByteArray(
+ private static final byte[] DATAIN_IPV6 = HexDump.hexStringToByteArray(
"047465737400001C" + "0001000011940010" + "AABBCCDD11223344" + "A0B0C0D010203040");
- // MDNS response w/name "test" & IPv6 address of aabb:ccdd:1122:3344:a0b0:c0d0:1020:3030
- private static final byte[] dataIn_ipv6_2 = HexDump.hexStringToByteArray(
- "047465737400001C" + "0001000011940010" + "AABBCCDD11223344" + "A0B0C0D010203030");
// MDNS response w/name "test" & PTR to foo.bar.quxx
- private static final byte[] dataIn_ptr_1 = HexDump.hexStringToByteArray(
+ private static final byte[] DATAIN_PTR = HexDump.hexStringToByteArray(
"047465737400000C" + "000100001194000E" + "03666F6F03626172" + "047175787800");
- // MDNS response w/name "test" & PTR to foo.bar.quxy
- private static final byte[] dataIn_ptr_2 = HexDump.hexStringToByteArray(
- "047465737400000C" + "000100001194000E" + "03666F6F03626172" + "047175787900");
// MDNS response w/name "test" & Service for host foo.bar.quxx
- private static final byte[] dataIn_service_1 = HexDump.hexStringToByteArray(
+ private static final byte[] DATAIN_SERVICE = HexDump.hexStringToByteArray(
"0474657374000021"
+ "0001000011940014"
+ "000100FF1F480366"
+ "6F6F036261720471"
+ "75787800");
- // MDNS response w/name "test" & Service for host test
- private static final byte[] dataIn_service_2 = HexDump.hexStringToByteArray(
- "0474657374000021" + "000100001194000B" + "000100FF1F480474" + "657374");
// MDNS response w/name "test" & the following text strings:
// "a=hello there", "b=1234567890", and "xyz=!$$$"
- private static final byte[] dataIn_text_1 = HexDump.hexStringToByteArray(
+ private static final byte[] DATAIN_TEXT = HexDump.hexStringToByteArray(
"0474657374000010"
+ "0001000011940024"
+ "0D613D68656C6C6F"
@@ -85,18 +74,11 @@
+ "3D31323334353637"
+ "3839300878797A3D"
+ "21242424");
- // MDNS response w/name "test" & the following text strings:
- // "a=hello there", "b=1234567890", and "xyz=!@#$"
- private static final byte[] dataIn_text_2 = HexDump.hexStringToByteArray(
- "0474657374000010"
- + "0001000011940024"
- + "0D613D68656C6C6F"
- + "2074686572650C62"
- + "3D31323334353637"
- + "3839300878797A3D"
- + "21402324");
+ private static final String[] TEST_SERVICE_NAME =
+ new String[] { "test", "_type", "_tcp", "local" };
private static final int INTERFACE_INDEX = 999;
+ private static final int TEST_TTL_MS = 120_000;
private final Network mNetwork = mock(Network.class);
// The following helper classes act as wrappers so that IPv4 and IPv6 address records can
@@ -113,87 +95,63 @@
}
}
- // This helper class just wraps the data bytes of a response packet with the contained record
- // type.
- // Its only purpose is to make the test code a bit more readable.
- static class PacketAndRecordClass {
- public final byte[] packetData;
- public final Class<?> recordClass;
-
- public PacketAndRecordClass() {
- packetData = null;
- recordClass = null;
- }
-
- public PacketAndRecordClass(byte[] data, Class<?> c) {
- packetData = data;
- recordClass = c;
- }
- }
-
- // Construct an MdnsResponse with the specified data packets applied.
- private MdnsResponse makeMdnsResponse(long time, List<PacketAndRecordClass> responseList)
- throws IOException {
- MdnsResponse response = new MdnsResponse(time, INTERFACE_INDEX, mNetwork);
- for (PacketAndRecordClass responseData : responseList) {
- DatagramPacket packet =
- new DatagramPacket(responseData.packetData, responseData.packetData.length);
- MdnsPacketReader reader = new MdnsPacketReader(packet);
- String[] name = reader.readLabels();
- reader.skip(2); // skip record type indication.
- // Apply the right kind of record to the response.
- if (responseData.recordClass == MdnsInet4AddressRecord.class) {
- response.setInet4AddressRecord(new MdnsInet4AddressRecord(name, reader));
- } else if (responseData.recordClass == MdnsInet6AddressRecord.class) {
- response.setInet6AddressRecord(new MdnsInet6AddressRecord(name, reader));
- } else if (responseData.recordClass == MdnsPointerRecord.class) {
- response.addPointerRecord(new MdnsPointerRecord(name, reader));
- } else if (responseData.recordClass == MdnsServiceRecord.class) {
- response.setServiceRecord(new MdnsServiceRecord(name, reader));
- } else if (responseData.recordClass == MdnsTextRecord.class) {
- response.setTextRecord(new MdnsTextRecord(name, reader));
- } else {
- fail("Unsupported/unexpected MdnsRecord subtype used in test - invalid test!");
- }
- }
+ private MdnsResponse makeCompleteResponse(int recordsTtlMillis) {
+ final String[] hostname = new String[] { "MyHostname" };
+ final String[] serviceName = new String[] { "MyService", "_type", "_tcp", "local" };
+ final String[] serviceType = new String[] { "_type", "_tcp", "local" };
+ final MdnsResponse response = new MdnsResponse(/* now= */ 0, serviceName, INTERFACE_INDEX,
+ mNetwork);
+ response.addPointerRecord(new MdnsPointerRecord(serviceType, 0L /* receiptTimeMillis */,
+ false /* cacheFlush */, recordsTtlMillis, serviceName));
+ response.setServiceRecord(new MdnsServiceRecord(serviceName, 0L /* receiptTimeMillis */,
+ true /* cacheFlush */, recordsTtlMillis, 0 /* servicePriority */,
+ 0 /* serviceWeight */, 0 /* servicePort */, hostname));
+ response.setTextRecord(new MdnsTextRecord(serviceName, 0L /* receiptTimeMillis */,
+ true /* cacheFlush */, recordsTtlMillis, emptyList() /* entries */));
+ response.addInet4AddressRecord(new MdnsInetAddressRecord(
+ hostname, 0L /* receiptTimeMillis */, true /* cacheFlush */,
+ recordsTtlMillis, parseNumericAddress("192.0.2.123")));
+ response.addInet6AddressRecord(new MdnsInetAddressRecord(
+ hostname, 0L /* receiptTimeMillis */, true /* cacheFlush */,
+ recordsTtlMillis, parseNumericAddress("2001:db8::123")));
return response;
}
@Test
public void getInet4AddressRecord_returnsAddedRecord() throws IOException {
- DatagramPacket packet = new DatagramPacket(dataIn_ipv4_1, dataIn_ipv4_1.length);
+ DatagramPacket packet = new DatagramPacket(DATAIN_IPV4, DATAIN_IPV4.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
MdnsInetAddressRecord record = new MdnsInetAddressRecord(name, MdnsRecord.TYPE_A, reader);
- MdnsResponse response = new MdnsResponse(0, INTERFACE_INDEX, mNetwork);
+ MdnsResponse response = new MdnsResponse(0, TEST_SERVICE_NAME, INTERFACE_INDEX, mNetwork);
assertFalse(response.hasInet4AddressRecord());
- assertTrue(response.setInet4AddressRecord(record));
+ assertTrue(response.addInet4AddressRecord(record));
assertEquals(response.getInet4AddressRecord(), record);
}
@Test
public void getInet6AddressRecord_returnsAddedRecord() throws IOException {
- DatagramPacket packet = new DatagramPacket(dataIn_ipv6_1, dataIn_ipv6_1.length);
+ DatagramPacket packet = new DatagramPacket(DATAIN_IPV6, DATAIN_IPV6.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
MdnsInetAddressRecord record =
new MdnsInetAddressRecord(name, MdnsRecord.TYPE_AAAA, reader);
- MdnsResponse response = new MdnsResponse(0, INTERFACE_INDEX, mNetwork);
+ MdnsResponse response = new MdnsResponse(0, TEST_SERVICE_NAME, INTERFACE_INDEX, mNetwork);
assertFalse(response.hasInet6AddressRecord());
- assertTrue(response.setInet6AddressRecord(record));
+ assertTrue(response.addInet6AddressRecord(record));
assertEquals(response.getInet6AddressRecord(), record);
}
@Test
public void getPointerRecords_returnsAddedRecord() throws IOException {
- DatagramPacket packet = new DatagramPacket(dataIn_ptr_1, dataIn_ptr_1.length);
+ DatagramPacket packet = new DatagramPacket(DATAIN_PTR, DATAIN_PTR.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
MdnsPointerRecord record = new MdnsPointerRecord(name, reader);
- MdnsResponse response = new MdnsResponse(0, INTERFACE_INDEX, mNetwork);
+ MdnsResponse response = new MdnsResponse(0, record.getPointer(), INTERFACE_INDEX, mNetwork);
assertFalse(response.hasPointerRecords());
assertTrue(response.addPointerRecord(record));
List<MdnsPointerRecord> recordList = response.getPointerRecords();
@@ -204,12 +162,12 @@
@Test
public void getServiceRecord_returnsAddedRecord() throws IOException {
- DatagramPacket packet = new DatagramPacket(dataIn_service_1, dataIn_service_1.length);
+ DatagramPacket packet = new DatagramPacket(DATAIN_SERVICE, DATAIN_SERVICE.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
MdnsServiceRecord record = new MdnsServiceRecord(name, reader);
- MdnsResponse response = new MdnsResponse(0, INTERFACE_INDEX, mNetwork);
+ MdnsResponse response = new MdnsResponse(0, name, INTERFACE_INDEX, mNetwork);
assertFalse(response.hasServiceRecord());
assertTrue(response.setServiceRecord(record));
assertEquals(response.getServiceRecord(), record);
@@ -217,12 +175,12 @@
@Test
public void getTextRecord_returnsAddedRecord() throws IOException {
- DatagramPacket packet = new DatagramPacket(dataIn_text_1, dataIn_text_1.length);
+ DatagramPacket packet = new DatagramPacket(DATAIN_TEXT, DATAIN_TEXT.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
MdnsTextRecord record = new MdnsTextRecord(name, reader);
- MdnsResponse response = new MdnsResponse(0, INTERFACE_INDEX, mNetwork);
+ MdnsResponse response = new MdnsResponse(0, name, INTERFACE_INDEX, mNetwork);
assertFalse(response.hasTextRecord());
assertTrue(response.setTextRecord(record));
assertEquals(response.getTextRecord(), record);
@@ -230,104 +188,86 @@
@Test
public void getInterfaceIndex() {
- final MdnsResponse response1 = new MdnsResponse(/* now= */ 0, INTERFACE_INDEX, mNetwork);
+ final MdnsResponse response1 = new MdnsResponse(/* now= */ 0, TEST_SERVICE_NAME,
+ INTERFACE_INDEX, mNetwork);
assertEquals(INTERFACE_INDEX, response1.getInterfaceIndex());
- final MdnsResponse response2 =
- new MdnsResponse(/* now= */ 0, 1234 /* interfaceIndex */, mNetwork);
+ final MdnsResponse response2 = new MdnsResponse(/* now= */ 0, TEST_SERVICE_NAME,
+ 1234 /* interfaceIndex */, mNetwork);
assertEquals(1234, response2.getInterfaceIndex());
}
@Test
public void testGetNetwork() {
- final MdnsResponse response1 =
- new MdnsResponse(/* now= */ 0, INTERFACE_INDEX, null /* network */);
+ final MdnsResponse response1 = new MdnsResponse(/* now= */ 0, TEST_SERVICE_NAME,
+ INTERFACE_INDEX, null /* network */);
assertNull(response1.getNetwork());
- final MdnsResponse response2 =
- new MdnsResponse(/* now= */ 0, 1234 /* interfaceIndex */, mNetwork);
+ final MdnsResponse response2 = new MdnsResponse(/* now= */ 0, TEST_SERVICE_NAME,
+ 1234 /* interfaceIndex */, mNetwork);
assertEquals(mNetwork, response2.getNetwork());
}
@Test
- public void mergeRecordsFrom_indicates_change_on_ipv4_address() throws IOException {
- MdnsResponse response = makeMdnsResponse(
- 0,
- Arrays.asList(
- new PacketAndRecordClass(dataIn_ipv4_1, MdnsInet4AddressRecord.class)));
- // Now create a new response that updates the address.
- MdnsResponse response2 = makeMdnsResponse(
- 100,
- Arrays.asList(
- new PacketAndRecordClass(dataIn_ipv4_2, MdnsInet4AddressRecord.class)));
- assertTrue(response.mergeRecordsFrom(response2));
+ public void copyConstructor() {
+ final MdnsResponse response = makeCompleteResponse(TEST_TTL_MS);
+ final MdnsResponse copy = new MdnsResponse(response);
+
+ assertEquals(response.getInet6AddressRecord(), copy.getInet6AddressRecord());
+ assertEquals(response.getInet4AddressRecord(), copy.getInet4AddressRecord());
+ assertEquals(response.getPointerRecords(), copy.getPointerRecords());
+ assertEquals(response.getServiceRecord(), copy.getServiceRecord());
+ assertEquals(response.getTextRecord(), copy.getTextRecord());
+ assertEquals(response.getRecords(), copy.getRecords());
+ assertEquals(response.getNetwork(), copy.getNetwork());
+ assertEquals(response.getInterfaceIndex(), copy.getInterfaceIndex());
}
@Test
- public void mergeRecordsFrom_indicates_change_on_ipv6_address() throws IOException {
- MdnsResponse response = makeMdnsResponse(
- 0,
- Arrays.asList(
- new PacketAndRecordClass(dataIn_ipv6_1, MdnsInet6AddressRecord.class)));
- // Now create a new response that updates the address.
- MdnsResponse response2 = makeMdnsResponse(
- 100,
- Arrays.asList(
- new PacketAndRecordClass(dataIn_ipv6_2, MdnsInet6AddressRecord.class)));
- assertTrue(response.mergeRecordsFrom(response2));
+ public void addRecords_noChange() {
+ final MdnsResponse response = makeCompleteResponse(TEST_TTL_MS);
+
+ assertFalse(response.addPointerRecord(response.getPointerRecords().get(0)));
+ assertFalse(response.addInet6AddressRecord(response.getInet6AddressRecord()));
+ assertFalse(response.addInet4AddressRecord(response.getInet4AddressRecord()));
+ assertFalse(response.setServiceRecord(response.getServiceRecord()));
+ assertFalse(response.setTextRecord(response.getTextRecord()));
}
@Test
- public void mergeRecordsFrom_indicates_change_on_text() throws IOException {
- MdnsResponse response = makeMdnsResponse(
- 0,
- Arrays.asList(new PacketAndRecordClass(dataIn_text_1, MdnsTextRecord.class)));
- // Now create a new response that updates the address.
- MdnsResponse response2 = makeMdnsResponse(
- 100,
- Arrays.asList(new PacketAndRecordClass(dataIn_text_2, MdnsTextRecord.class)));
- assertTrue(response.mergeRecordsFrom(response2));
- }
+ public void addRecords_ttlChange() {
+ final MdnsResponse response = makeCompleteResponse(TEST_TTL_MS);
+ final MdnsResponse ttlZeroResponse = makeCompleteResponse(0);
- @Test
- public void mergeRecordsFrom_indicates_change_on_service() throws IOException {
- MdnsResponse response = makeMdnsResponse(
- 0,
- Arrays.asList(new PacketAndRecordClass(dataIn_service_1, MdnsServiceRecord.class)));
- // Now create a new response that updates the address.
- MdnsResponse response2 = makeMdnsResponse(
- 100,
- Arrays.asList(new PacketAndRecordClass(dataIn_service_2, MdnsServiceRecord.class)));
- assertTrue(response.mergeRecordsFrom(response2));
- }
+ assertTrue(response.addPointerRecord(ttlZeroResponse.getPointerRecords().get(0)));
+ assertEquals(1, response.getPointerRecords().size());
+ assertEquals(0, response.getPointerRecords().get(0).getTtl());
+ assertTrue(response.getRecords().stream().anyMatch(r ->
+ r == response.getPointerRecords().get(0)));
- @Test
- public void mergeRecordsFrom_indicates_change_on_pointer() throws IOException {
- MdnsResponse response = makeMdnsResponse(
- 0,
- Arrays.asList(new PacketAndRecordClass(dataIn_ptr_1, MdnsPointerRecord.class)));
- // Now create a new response that updates the address.
- MdnsResponse response2 = makeMdnsResponse(
- 100,
- Arrays.asList(new PacketAndRecordClass(dataIn_ptr_2, MdnsPointerRecord.class)));
- assertTrue(response.mergeRecordsFrom(response2));
- }
+ assertTrue(response.addInet6AddressRecord(ttlZeroResponse.getInet6AddressRecord()));
+ assertEquals(1, response.getInet6AddressRecords().size());
+ assertEquals(0, response.getInet6AddressRecord().getTtl());
+ assertTrue(response.getRecords().stream().anyMatch(r ->
+ r == response.getInet6AddressRecord()));
- @Test
- @Ignore("MdnsConfigs is not configurable currently.")
- public void mergeRecordsFrom_indicates_noChange() throws IOException {
- //MdnsConfigsFlagsImpl.useReducedMergeRecordUpdateEvents.override(true);
- List<PacketAndRecordClass> recordList =
- Arrays.asList(
- new PacketAndRecordClass(dataIn_ipv4_1, MdnsInet4AddressRecord.class),
- new PacketAndRecordClass(dataIn_ipv6_1, MdnsInet6AddressRecord.class),
- new PacketAndRecordClass(dataIn_ptr_1, MdnsPointerRecord.class),
- new PacketAndRecordClass(dataIn_service_2, MdnsServiceRecord.class),
- new PacketAndRecordClass(dataIn_text_1, MdnsTextRecord.class));
- // Create a two identical responses.
- MdnsResponse response = makeMdnsResponse(0, recordList);
- MdnsResponse response2 = makeMdnsResponse(100, recordList);
- // Merging should not indicate any change.
- assertFalse(response.mergeRecordsFrom(response2));
+ assertTrue(response.addInet4AddressRecord(ttlZeroResponse.getInet4AddressRecord()));
+ assertEquals(1, response.getInet4AddressRecords().size());
+ assertEquals(0, response.getInet4AddressRecord().getTtl());
+ assertTrue(response.getRecords().stream().anyMatch(r ->
+ r == response.getInet4AddressRecord()));
+
+ assertTrue(response.setServiceRecord(ttlZeroResponse.getServiceRecord()));
+ assertEquals(0, response.getServiceRecord().getTtl());
+ assertTrue(response.getRecords().stream().anyMatch(r ->
+ r == response.getServiceRecord()));
+
+ assertTrue(response.setTextRecord(ttlZeroResponse.getTextRecord()));
+ assertEquals(0, response.getTextRecord().getTtl());
+ assertTrue(response.getRecords().stream().anyMatch(r ->
+ r == response.getTextRecord()));
+
+ // All records were replaced, not added
+ assertEquals(ttlZeroResponse.getRecords().size(), response.getRecords().size());
}
}
\ No newline at end of file
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java
index 76728cf..e7d7a98 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java
@@ -119,6 +119,26 @@
}
@Test
+ public void constructor_createWithUppercaseKeys_correctAttributes() {
+ MdnsServiceInfo info =
+ new MdnsServiceInfo(
+ "my-mdns-service",
+ new String[] {"_testtype", "_tcp"},
+ List.of(),
+ new String[] {"my-host", "local"},
+ 12345,
+ "192.168.1.1",
+ "2001::1",
+ List.of("KEY=Value"),
+ /* textEntries= */ null);
+
+ assertEquals("Value", info.getAttributeByKey("key"));
+ assertEquals("Value", info.getAttributeByKey("KEY"));
+ assertEquals(1, info.getAttributes().size());
+ assertEquals("KEY", info.getAttributes().keySet().iterator().next());
+ }
+
+ @Test
public void getInterfaceIndex_constructorWithDefaultValues_returnsMinusOne() {
MdnsServiceInfo info =
new MdnsServiceInfo(
@@ -177,8 +197,8 @@
List.of(),
new String[] {"my-host", "local"},
12345,
- "192.168.1.1",
- "2001::1",
+ List.of("192.168.1.1"),
+ List.of("2001::1"),
List.of(),
/* textEntries= */ null,
/* interfaceIndex= */ 20,
@@ -197,8 +217,8 @@
List.of(),
new String[] {"my-host", "local"},
12345,
- "192.168.1.1",
- "2001::1",
+ List.of("192.168.1.1", "192.168.1.2"),
+ List.of("2001::1", "2001::2"),
List.of("vn=Alphabet Inc.", "mn=Google Nest Hub Max", "id=12345"),
List.of(
MdnsServiceInfo.TextEntry.fromString("vn=Google Inc."),
@@ -217,7 +237,9 @@
assertArrayEquals(beforeParcel.getHostName(), afterParcel.getHostName());
assertEquals(beforeParcel.getPort(), afterParcel.getPort());
assertEquals(beforeParcel.getIpv4Address(), afterParcel.getIpv4Address());
+ assertEquals(beforeParcel.getIpv4Addresses(), afterParcel.getIpv4Addresses());
assertEquals(beforeParcel.getIpv6Address(), afterParcel.getIpv6Address());
+ assertEquals(beforeParcel.getIpv6Addresses(), afterParcel.getIpv6Addresses());
assertEquals(beforeParcel.getAttributes(), afterParcel.getAttributes());
assertEquals(beforeParcel.getInterfaceIndex(), afterParcel.getInterfaceIndex());
assertEquals(beforeParcel.getNetwork(), afterParcel.getNetwork());
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
index a45ca68..746994f 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
@@ -24,13 +24,12 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -60,8 +59,7 @@
import java.io.IOException;
import java.net.DatagramPacket;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
@@ -72,6 +70,7 @@
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
/** Tests for {@link MdnsServiceTypeClient}. */
@RunWith(DevSdkIgnoreRunner.class)
@@ -85,6 +84,9 @@
private static final InetSocketAddress IPV6_ADDRESS = new InetSocketAddress(
MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT);
+ private static final long TEST_TTL = 120000L;
+ private static final long TEST_ELAPSED_REALTIME = 123L;
+
@Mock
private MdnsServiceBrowserListener mockListenerOne;
@Mock
@@ -95,6 +97,8 @@
private MdnsMultinetworkSocketClient mockSocketClient;
@Mock
private Network mockNetwork;
+ @Mock
+ private MdnsResponseDecoder.Clock mockDecoderClock;
@Captor
private ArgumentCaptor<MdnsServiceInfo> serviceInfoCaptor;
@@ -111,6 +115,7 @@
@SuppressWarnings("DoNotMock")
public void setUp() throws IOException {
MockitoAnnotations.initMocks(this);
+ doReturn(TEST_ELAPSED_REALTIME).when(mockDecoderClock).elapsedRealtime();
expectedIPv4Packets = new DatagramPacket[16];
expectedIPv6Packets = new DatagramPacket[16];
@@ -160,7 +165,8 @@
.thenReturn(expectedIPv6Packets[15]);
client =
- new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor) {
+ new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
+ mockDecoderClock, mockNetwork) {
@Override
MdnsPacketWriter createMdnsPacketWriter() {
return mockPacketWriter;
@@ -414,16 +420,17 @@
}
private static void verifyServiceInfo(MdnsServiceInfo serviceInfo, String serviceName,
- String[] serviceType, String ipv4Address, String ipv6Address, int port,
+ String[] serviceType, List<String> ipv4Addresses, List<String> ipv6Addresses, int port,
List<String> subTypes, Map<String, String> attributes, int interfaceIndex,
Network network) {
assertEquals(serviceName, serviceInfo.getServiceInstanceName());
assertArrayEquals(serviceType, serviceInfo.getServiceType());
- assertEquals(ipv4Address, serviceInfo.getIpv4Address());
- assertEquals(ipv6Address, serviceInfo.getIpv6Address());
+ assertEquals(ipv4Addresses, serviceInfo.getIpv4Addresses());
+ assertEquals(ipv6Addresses, serviceInfo.getIpv6Addresses());
assertEquals(port, serviceInfo.getPort());
assertEquals(subTypes, serviceInfo.getSubtypes());
for (String key : attributes.keySet()) {
+ assertTrue(attributes.containsKey(key));
assertEquals(attributes.get(key), serviceInfo.getAttributeByKey(key));
}
assertEquals(interfaceIndex, serviceInfo.getInterfaceIndex());
@@ -434,22 +441,19 @@
public void processResponse_incompleteResponse() {
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
- MdnsResponse response = mock(MdnsResponse.class);
- when(response.getServiceInstanceName()).thenReturn("service-instance-1");
- doReturn(INTERFACE_INDEX).when(response).getInterfaceIndex();
- doReturn(mockNetwork).when(response).getNetwork();
- when(response.isComplete()).thenReturn(false);
-
- client.processResponse(response);
+ client.processResponse(createResponse(
+ "service-instance-1", null /* host */, 0 /* port */,
+ SERVICE_TYPE_LABELS,
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture());
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
"service-instance-1",
SERVICE_TYPE_LABELS,
- null /* ipv4Address */,
- null /* ipv6Address */,
- 0 /* port */,
- List.of() /* subTypes */,
- Collections.singletonMap("key", null) /* attributes */,
+ /* ipv4Addresses= */ List.of(),
+ /* ipv6Addresses= */ List.of(),
+ /* port= */ 0,
+ /* subTypes= */ List.of(),
+ Collections.emptyMap(),
INTERFACE_INDEX,
mockNetwork);
@@ -463,36 +467,25 @@
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
// Process the initial response.
- MdnsResponse initialResponse =
- createResponse(
- "service-instance-1",
- ipV4Address,
- 5353,
- /* subtype= */ "ABCDE",
- Collections.emptyMap(),
- /* interfaceIndex= */ 20,
- mockNetwork);
- client.processResponse(initialResponse);
+ client.processResponse(createResponse(
+ "service-instance-1", ipV4Address, 5353,
+ /* subtype= */ "ABCDE",
+ Collections.emptyMap(), TEST_TTL), /* interfaceIndex= */ 20, mockNetwork);
// Process a second response with a different port and updated text attributes.
- MdnsResponse secondResponse =
- createResponse(
- "service-instance-1",
- ipV4Address,
- 5354,
- /* subtype= */ "ABCDE",
- Collections.singletonMap("key", "value"),
- /* interfaceIndex= */ 20,
- mockNetwork);
- client.processResponse(secondResponse);
+ client.processResponse(createResponse(
+ "service-instance-1", ipV4Address, 5354,
+ /* subtype= */ "ABCDE",
+ Collections.singletonMap("key", "value"), TEST_TTL),
+ /* interfaceIndex= */ 20, mockNetwork);
// Verify onServiceNameDiscovered was called once for the initial response.
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture());
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
"service-instance-1",
SERVICE_TYPE_LABELS,
- ipV4Address /* ipv4Address */,
- null /* ipv6Address */,
+ List.of(ipV4Address) /* ipv4Address */,
+ List.of() /* ipv6Address */,
5353 /* port */,
Collections.singletonList("ABCDE") /* subTypes */,
Collections.singletonMap("key", null) /* attributes */,
@@ -529,39 +522,25 @@
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
// Process the initial response.
- MdnsResponse initialResponse =
- createResponse(
- "service-instance-1",
- ipV6Address,
- 5353,
- /* subtype= */ "ABCDE",
- Collections.emptyMap(),
- /* interfaceIndex= */ 20,
- mockNetwork);
- client.processResponse(initialResponse);
+ client.processResponse(createResponse(
+ "service-instance-1", ipV6Address, 5353,
+ /* subtype= */ "ABCDE",
+ Collections.emptyMap(), TEST_TTL), /* interfaceIndex= */ 20, mockNetwork);
// Process a second response with a different port and updated text attributes.
- MdnsResponse secondResponse =
- createResponse(
- "service-instance-1",
- ipV6Address,
- 5354,
- /* subtype= */ "ABCDE",
- Collections.singletonMap("key", "value"),
- /* interfaceIndex= */ 20,
- mockNetwork);
- client.processResponse(secondResponse);
-
- System.out.println("secondResponses ip"
- + secondResponse.getInet6AddressRecord().getInet6Address().getHostAddress());
+ client.processResponse(createResponse(
+ "service-instance-1", ipV6Address, 5354,
+ /* subtype= */ "ABCDE",
+ Collections.singletonMap("key", "value"), TEST_TTL),
+ /* interfaceIndex= */ 20, mockNetwork);
// Verify onServiceNameDiscovered was called once for the initial response.
verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture());
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
"service-instance-1",
SERVICE_TYPE_LABELS,
- null /* ipv4Address */,
- ipV6Address /* ipv6Address */,
+ List.of() /* ipv4Address */,
+ List.of(ipV6Address) /* ipv6Address */,
5353 /* port */,
Collections.singletonList("ABCDE") /* subTypes */,
Collections.singletonMap("key", null) /* attributes */,
@@ -619,29 +598,25 @@
final String serviceName = "service-instance-1";
final String ipV6Address = "2000:3333::da6c:63ff:fe7c:7483";
// Process the initial response.
- final MdnsResponse initialResponse =
- createResponse(
- serviceName,
- ipV6Address,
- 5353 /* port */,
- /* subtype= */ "ABCDE",
- Collections.emptyMap(),
- INTERFACE_INDEX,
- mockNetwork);
- client.processResponse(initialResponse);
- MdnsResponse response = mock(MdnsResponse.class);
- doReturn("goodbye-service").when(response).getServiceInstanceName();
- doReturn(INTERFACE_INDEX).when(response).getInterfaceIndex();
- doReturn(mockNetwork).when(response).getNetwork();
- doReturn(true).when(response).isGoodbye();
- client.processResponse(response);
+ client.processResponse(createResponse(
+ serviceName, ipV6Address, 5353,
+ SERVICE_TYPE_LABELS,
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
+
+ client.processResponse(createResponse(
+ "goodbye-service", ipV6Address, 5353,
+ SERVICE_TYPE_LABELS,
+ Collections.emptyMap(), /* ptrTtlMillis= */ 0L), INTERFACE_INDEX, mockNetwork);
+
// Verify removed callback won't be called if the service is not existed.
verifyServiceRemovedNoCallback(mockListenerOne);
verifyServiceRemovedNoCallback(mockListenerTwo);
// Verify removed callback would be called.
- doReturn(serviceName).when(response).getServiceInstanceName();
- client.processResponse(response);
+ client.processResponse(createResponse(
+ serviceName, ipV6Address, 5353,
+ SERVICE_TYPE_LABELS,
+ Collections.emptyMap(), 0L), INTERFACE_INDEX, mockNetwork);
verifyServiceRemovedCallback(
mockListenerOne, serviceName, SERVICE_TYPE_LABELS, INTERFACE_INDEX, mockNetwork);
verifyServiceRemovedCallback(
@@ -651,16 +626,10 @@
@Test
public void reportExistingServiceToNewlyRegisteredListeners() throws Exception {
// Process the initial response.
- MdnsResponse initialResponse =
- createResponse(
- "service-instance-1",
- "192.168.1.1",
- 5353,
- /* subtype= */ "ABCDE",
- Collections.emptyMap(),
- INTERFACE_INDEX,
- mockNetwork);
- client.processResponse(initialResponse);
+ client.processResponse(createResponse(
+ "service-instance-1", "192.168.1.1", 5353,
+ /* subtype= */ "ABCDE",
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
client.startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
@@ -669,8 +638,8 @@
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
"service-instance-1",
SERVICE_TYPE_LABELS,
- "192.168.1.1" /* ipv4Address */,
- null /* ipv6Address */,
+ List.of("192.168.1.1") /* ipv4Address */,
+ List.of() /* ipv6Address */,
5353 /* port */,
Collections.singletonList("ABCDE") /* subTypes */,
Collections.singletonMap("key", null) /* attributes */,
@@ -687,10 +656,10 @@
assertNull(existingServiceInfo.getAttributeByKey("key"));
// Process a goodbye message for the existing response.
- MdnsResponse goodByeResponse = mock(MdnsResponse.class);
- when(goodByeResponse.getServiceInstanceName()).thenReturn("service-instance-1");
- when(goodByeResponse.isGoodbye()).thenReturn(true);
- client.processResponse(goodByeResponse);
+ client.processResponse(createResponse(
+ "service-instance-1", "192.168.1.1", 5353,
+ SERVICE_TYPE_LABELS,
+ Collections.emptyMap(), /* ptrTtlMillis= */ 0L), INTERFACE_INDEX, mockNetwork);
client.startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
@@ -709,17 +678,15 @@
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
// Process the initial response.
- MdnsResponse initialResponse =
- createMockResponse(
- serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
- Map.of(), INTERFACE_INDEX, mockNetwork);
- client.processResponse(initialResponse);
+ client.processResponse(createResponse(
+ serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE",
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
// Clear the scheduled runnable.
currentThreadExecutor.getAndClearLastScheduledRunnable();
// Simulate the case where the response is after TTL.
- when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 0);
+ doReturn(TEST_ELAPSED_REALTIME + TEST_TTL + 1L).when(mockDecoderClock).elapsedRealtime();
firstMdnsTask.run();
// Verify removed callback was not called.
@@ -733,7 +700,8 @@
//MdnsConfigsFlagsImpl.allowSearchOptionsToRemoveExpiredService.override(true);
final String serviceInstanceName = "service-instance-1";
client =
- new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor) {
+ new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
+ mockDecoderClock, mockNetwork) {
@Override
MdnsPacketWriter createMdnsPacketWriter() {
return mockPacketWriter;
@@ -743,24 +711,22 @@
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
// Process the initial response.
- MdnsResponse initialResponse =
- createMockResponse(
- serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
- Map.of(), INTERFACE_INDEX, mockNetwork);
- client.processResponse(initialResponse);
+ client.processResponse(createResponse(
+ serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE",
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
// Clear the scheduled runnable.
currentThreadExecutor.getAndClearLastScheduledRunnable();
// Simulate the case where the response is under TTL.
- when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 1000);
+ doReturn(TEST_ELAPSED_REALTIME + TEST_TTL - 1L).when(mockDecoderClock).elapsedRealtime();
firstMdnsTask.run();
// Verify removed callback was not called.
verifyServiceRemovedNoCallback(mockListenerOne);
// Simulate the case where the response is after TTL.
- when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 0);
+ doReturn(TEST_ELAPSED_REALTIME + TEST_TTL + 1L).when(mockDecoderClock).elapsedRealtime();
firstMdnsTask.run();
// Verify removed callback was called.
@@ -773,7 +739,8 @@
throws Exception {
final String serviceInstanceName = "service-instance-1";
client =
- new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor) {
+ new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
+ mockDecoderClock, mockNetwork) {
@Override
MdnsPacketWriter createMdnsPacketWriter() {
return mockPacketWriter;
@@ -783,17 +750,15 @@
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
// Process the initial response.
- MdnsResponse initialResponse =
- createMockResponse(
- serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
- Map.of(), INTERFACE_INDEX, mockNetwork);
- client.processResponse(initialResponse);
+ client.processResponse(createResponse(
+ serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE",
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
// Clear the scheduled runnable.
currentThreadExecutor.getAndClearLastScheduledRunnable();
// Simulate the case where the response is after TTL.
- when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 0);
+ doReturn(TEST_ELAPSED_REALTIME + TEST_TTL + 1L).when(mockDecoderClock).elapsedRealtime();
firstMdnsTask.run();
// Verify removed callback was not called.
@@ -807,7 +772,8 @@
//MdnsConfigsFlagsImpl.removeServiceAfterTtlExpires.override(true);
final String serviceInstanceName = "service-instance-1";
client =
- new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor) {
+ new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
+ mockDecoderClock, mockNetwork) {
@Override
MdnsPacketWriter createMdnsPacketWriter() {
return mockPacketWriter;
@@ -817,17 +783,15 @@
Runnable firstMdnsTask = currentThreadExecutor.getAndClearSubmittedRunnable();
// Process the initial response.
- MdnsResponse initialResponse =
- createMockResponse(
- serviceInstanceName, "192.168.1.1", 5353, List.of("ABCDE"),
- Map.of(), INTERFACE_INDEX, mockNetwork);
- client.processResponse(initialResponse);
+ client.processResponse(createResponse(
+ serviceInstanceName, "192.168.1.1", 5353, /* subtype= */ "ABCDE",
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
// Clear the scheduled runnable.
currentThreadExecutor.getAndClearLastScheduledRunnable();
// Simulate the case where the response is after TTL.
- when(initialResponse.getServiceRecord().getRemainingTTL(anyLong())).thenReturn((long) 0);
+ doReturn(TEST_ELAPSED_REALTIME + TEST_TTL + 1L).when(mockDecoderClock).elapsedRealtime();
firstMdnsTask.run();
// Verify removed callback was called.
@@ -844,56 +808,36 @@
InOrder inOrder = inOrder(mockListenerOne);
// Process the initial response which is incomplete.
- final MdnsResponse initialResponse =
- createResponse(
- serviceName,
- null,
- 5353,
- "ABCDE" /* subtype */,
- Collections.emptyMap(),
- INTERFACE_INDEX,
- mockNetwork);
- client.processResponse(initialResponse);
+ final String subtype = "ABCDE";
+ client.processResponse(createResponse(
+ serviceName, null, 5353, subtype,
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
// Process a second response which has ip address to make response become complete.
- final MdnsResponse secondResponse =
- createResponse(
- serviceName,
- ipV4Address,
- 5353,
- "ABCDE" /* subtype */,
- Collections.emptyMap(),
- INTERFACE_INDEX,
- mockNetwork);
- client.processResponse(secondResponse);
+ client.processResponse(createResponse(
+ serviceName, ipV4Address, 5353, subtype,
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
// Process a third response with a different ip address, port and updated text attributes.
- final MdnsResponse thirdResponse =
- createResponse(
- serviceName,
- ipV6Address,
- 5354,
- "ABCDE" /* subtype */,
- Collections.singletonMap("key", "value"),
- INTERFACE_INDEX,
- mockNetwork);
- client.processResponse(thirdResponse);
+ client.processResponse(createResponse(
+ serviceName, ipV6Address, 5354, subtype,
+ Collections.singletonMap("key", "value"), TEST_TTL), INTERFACE_INDEX, mockNetwork);
- // Process the last response which is goodbye message.
- final MdnsResponse lastResponse = mock(MdnsResponse.class);
- doReturn(serviceName).when(lastResponse).getServiceInstanceName();
- doReturn(true).when(lastResponse).isGoodbye();
- client.processResponse(lastResponse);
+ // Process the last response which is goodbye message (with the main type, not subtype).
+ client.processResponse(createResponse(
+ serviceName, ipV6Address, 5354, SERVICE_TYPE_LABELS,
+ Collections.singletonMap("key", "value"), /* ptrTtlMillis= */ 0L),
+ INTERFACE_INDEX, mockNetwork);
// Verify onServiceNameDiscovered was first called for the initial response.
inOrder.verify(mockListenerOne).onServiceNameDiscovered(serviceInfoCaptor.capture());
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(0),
serviceName,
SERVICE_TYPE_LABELS,
- null /* ipv4Address */,
- null /* ipv6Address */,
+ List.of() /* ipv4Address */,
+ List.of() /* ipv6Address */,
5353 /* port */,
- Collections.singletonList("ABCDE") /* subTypes */,
+ Collections.singletonList(subtype) /* subTypes */,
Collections.singletonMap("key", null) /* attributes */,
INTERFACE_INDEX,
mockNetwork);
@@ -903,10 +847,10 @@
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(1),
serviceName,
SERVICE_TYPE_LABELS,
- ipV4Address /* ipv4Address */,
- null /* ipv6Address */,
+ List.of(ipV4Address) /* ipv4Address */,
+ List.of() /* ipv6Address */,
5353 /* port */,
- Collections.singletonList("ABCDE") /* subTypes */,
+ Collections.singletonList(subtype) /* subTypes */,
Collections.singletonMap("key", null) /* attributes */,
INTERFACE_INDEX,
mockNetwork);
@@ -916,10 +860,10 @@
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(2),
serviceName,
SERVICE_TYPE_LABELS,
- ipV4Address /* ipv4Address */,
- ipV6Address /* ipv6Address */,
+ List.of(ipV4Address) /* ipv4Address */,
+ List.of(ipV6Address) /* ipv6Address */,
5354 /* port */,
- Collections.singletonList("ABCDE") /* subTypes */,
+ Collections.singletonList(subtype) /* subTypes */,
Collections.singletonMap("key", "value") /* attributes */,
INTERFACE_INDEX,
mockNetwork);
@@ -929,8 +873,8 @@
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(3),
serviceName,
SERVICE_TYPE_LABELS,
- ipV4Address /* ipv4Address */,
- ipV6Address /* ipv6Address */,
+ List.of(ipV4Address) /* ipv4Address */,
+ List.of(ipV6Address) /* ipv6Address */,
5354 /* port */,
Collections.singletonList("ABCDE") /* subTypes */,
Collections.singletonMap("key", "value") /* attributes */,
@@ -942,8 +886,8 @@
verifyServiceInfo(serviceInfoCaptor.getAllValues().get(4),
serviceName,
SERVICE_TYPE_LABELS,
- ipV4Address /* ipv4Address */,
- ipV6Address /* ipv6Address */,
+ List.of(ipV4Address) /* ipv4Address */,
+ List.of(ipV6Address) /* ipv6Address */,
5354 /* port */,
Collections.singletonList("ABCDE") /* subTypes */,
Collections.singletonMap("key", "value") /* attributes */,
@@ -951,6 +895,168 @@
mockNetwork);
}
+ @Test
+ public void testProcessResponse_Resolve() throws Exception {
+ client = new MdnsServiceTypeClient(
+ SERVICE_TYPE, mockSocketClient, currentThreadExecutor, mockNetwork);
+
+ final String instanceName = "service-instance";
+ final String[] hostname = new String[] { "testhost "};
+ final String ipV4Address = "192.0.2.0";
+ final String ipV6Address = "2001:db8::";
+
+ final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
+ .setResolveInstanceName(instanceName).build();
+
+ client.startSendAndReceive(mockListenerOne, resolveOptions);
+ InOrder inOrder = inOrder(mockListenerOne, mockSocketClient);
+
+ // Verify a query for SRV/TXT was sent, but no PTR query
+ final ArgumentCaptor<DatagramPacket> srvTxtQueryCaptor =
+ ArgumentCaptor.forClass(DatagramPacket.class);
+ currentThreadExecutor.getAndClearLastScheduledRunnable().run();
+ // Send twice for IPv4 and IPv6
+ inOrder.verify(mockSocketClient, times(2)).sendUnicastPacket(srvTxtQueryCaptor.capture(),
+ eq(null) /* network */);
+
+ final MdnsPacket srvTxtQueryPacket = MdnsPacket.parse(
+ new MdnsPacketReader(srvTxtQueryCaptor.getValue()));
+ final List<MdnsRecord> srvTxtQuestions = srvTxtQueryPacket.questions;
+
+ final String[] serviceName = Stream.concat(Stream.of(instanceName),
+ Arrays.stream(SERVICE_TYPE_LABELS)).toArray(String[]::new);
+ assertFalse(srvTxtQuestions.stream().anyMatch(q -> q.getType() == MdnsRecord.TYPE_PTR));
+ assertTrue(srvTxtQuestions.stream().anyMatch(q ->
+ q.getType() == MdnsRecord.TYPE_SRV && Arrays.equals(q.name, serviceName)));
+ assertTrue(srvTxtQuestions.stream().anyMatch(q ->
+ q.getType() == MdnsRecord.TYPE_TXT && Arrays.equals(q.name, serviceName)));
+
+ // Process a response with SRV+TXT
+ final MdnsPacket srvTxtResponse = new MdnsPacket(
+ 0 /* flags */,
+ Collections.emptyList() /* questions */,
+ List.of(
+ new MdnsServiceRecord(serviceName, 0L /* receiptTimeMillis */,
+ true /* cacheFlush */, TEST_TTL, 0 /* servicePriority */,
+ 0 /* serviceWeight */, 1234 /* servicePort */, hostname),
+ new MdnsTextRecord(serviceName, 0L /* receiptTimeMillis */,
+ true /* cacheFlush */, TEST_TTL,
+ Collections.emptyList() /* entries */)),
+ Collections.emptyList() /* authorityRecords */,
+ Collections.emptyList() /* additionalRecords */);
+
+ client.processResponse(srvTxtResponse, INTERFACE_INDEX, mockNetwork);
+
+ // Expect a query for A/AAAA
+ final ArgumentCaptor<DatagramPacket> addressQueryCaptor =
+ ArgumentCaptor.forClass(DatagramPacket.class);
+ currentThreadExecutor.getAndClearLastScheduledRunnable().run();
+ inOrder.verify(mockSocketClient, times(2)).sendMulticastPacket(addressQueryCaptor.capture(),
+ eq(null) /* network */);
+
+ final MdnsPacket addressQueryPacket = MdnsPacket.parse(
+ new MdnsPacketReader(addressQueryCaptor.getValue()));
+ final List<MdnsRecord> addressQueryQuestions = addressQueryPacket.questions;
+ assertTrue(addressQueryQuestions.stream().anyMatch(q ->
+ q.getType() == MdnsRecord.TYPE_A && Arrays.equals(q.name, hostname)));
+ assertTrue(addressQueryQuestions.stream().anyMatch(q ->
+ q.getType() == MdnsRecord.TYPE_AAAA && Arrays.equals(q.name, hostname)));
+
+ // Process a response with address records
+ final MdnsPacket addressResponse = new MdnsPacket(
+ 0 /* flags */,
+ Collections.emptyList() /* questions */,
+ List.of(
+ new MdnsInetAddressRecord(hostname, 0L /* receiptTimeMillis */,
+ true /* cacheFlush */, TEST_TTL,
+ InetAddresses.parseNumericAddress(ipV4Address)),
+ new MdnsInetAddressRecord(hostname, 0L /* receiptTimeMillis */,
+ true /* cacheFlush */, TEST_TTL,
+ InetAddresses.parseNumericAddress(ipV6Address))),
+ Collections.emptyList() /* authorityRecords */,
+ Collections.emptyList() /* additionalRecords */);
+
+ inOrder.verify(mockListenerOne, never()).onServiceNameDiscovered(any());
+ client.processResponse(addressResponse, INTERFACE_INDEX, mockNetwork);
+
+ inOrder.verify(mockListenerOne).onServiceFound(serviceInfoCaptor.capture());
+ verifyServiceInfo(serviceInfoCaptor.getValue(),
+ instanceName,
+ SERVICE_TYPE_LABELS,
+ List.of(ipV4Address),
+ List.of(ipV6Address),
+ 1234 /* port */,
+ Collections.emptyList() /* subTypes */,
+ Collections.emptyMap() /* attributes */,
+ INTERFACE_INDEX,
+ mockNetwork);
+ }
+
+ @Test
+ public void testProcessResponse_ResolveExcludesOtherServices() {
+ client = new MdnsServiceTypeClient(
+ SERVICE_TYPE, mockSocketClient, currentThreadExecutor, mockNetwork);
+
+ final String requestedInstance = "instance1";
+ final String otherInstance = "instance2";
+ final String ipV4Address = "192.0.2.0";
+ final String ipV6Address = "2001:db8::";
+
+ final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
+ // Use different case in the options
+ .setResolveInstanceName("Instance1").build();
+
+ client.startSendAndReceive(mockListenerOne, resolveOptions);
+ client.startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
+
+ // Complete response from instanceName
+ client.processResponse(createResponse(
+ requestedInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS,
+ Collections.emptyMap() /* textAttributes */, TEST_TTL),
+ INTERFACE_INDEX, mockNetwork);
+
+ // Complete response from otherInstanceName
+ client.processResponse(createResponse(
+ otherInstance, ipV4Address, 5353, SERVICE_TYPE_LABELS,
+ Collections.emptyMap() /* textAttributes */, TEST_TTL),
+ INTERFACE_INDEX, mockNetwork);
+
+ // Address update from otherInstanceName
+ client.processResponse(createResponse(
+ otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS,
+ Collections.emptyMap(), TEST_TTL), INTERFACE_INDEX, mockNetwork);
+
+ // Goodbye from otherInstanceName
+ client.processResponse(createResponse(
+ otherInstance, ipV6Address, 5353, SERVICE_TYPE_LABELS,
+ Collections.emptyMap(), 0L /* ttl */), INTERFACE_INDEX, mockNetwork);
+
+ // mockListenerOne gets notified for the requested instance
+ verify(mockListenerOne).onServiceNameDiscovered(matchServiceName(requestedInstance));
+ verify(mockListenerOne).onServiceFound(matchServiceName(requestedInstance));
+
+ // ...but does not get any callback for the other instance
+ verify(mockListenerOne, never()).onServiceFound(matchServiceName(otherInstance));
+ verify(mockListenerOne, never()).onServiceNameDiscovered(matchServiceName(otherInstance));
+ verify(mockListenerOne, never()).onServiceUpdated(matchServiceName(otherInstance));
+ verify(mockListenerOne, never()).onServiceRemoved(matchServiceName(otherInstance));
+
+ // mockListenerTwo gets notified for both though
+ final InOrder inOrder = inOrder(mockListenerTwo);
+ inOrder.verify(mockListenerTwo).onServiceNameDiscovered(
+ matchServiceName(requestedInstance));
+ inOrder.verify(mockListenerTwo).onServiceFound(matchServiceName(requestedInstance));
+
+ inOrder.verify(mockListenerTwo).onServiceNameDiscovered(matchServiceName(otherInstance));
+ inOrder.verify(mockListenerTwo).onServiceFound(matchServiceName(otherInstance));
+ inOrder.verify(mockListenerTwo).onServiceUpdated(matchServiceName(otherInstance));
+ inOrder.verify(mockListenerTwo).onServiceRemoved(matchServiceName(otherInstance));
+ }
+
+ private static MdnsServiceInfo matchServiceName(String name) {
+ return argThat(info -> info.getServiceInstanceName().equals(name));
+ }
+
// verifies that the right query was enqueued with the right delay, and send query by executing
// the runnable.
private void verifyAndSendQuery(int index, long timeInMs, boolean expectsUnicastResponse) {
@@ -1029,106 +1135,68 @@
}
}
- // Creates a mock mDNS response.
- private MdnsResponse createMockResponse(
- @NonNull String serviceInstanceName,
- @NonNull String host,
- int port,
- @NonNull List<String> subtypes,
- @NonNull Map<String, String> textAttributes,
- int interfaceIndex,
- Network network)
- throws Exception {
- String[] hostName = new String[]{"hostname"};
- MdnsServiceRecord serviceRecord = mock(MdnsServiceRecord.class);
- when(serviceRecord.getServiceHost()).thenReturn(hostName);
- when(serviceRecord.getServicePort()).thenReturn(port);
-
- MdnsResponse response = spy(new MdnsResponse(0, interfaceIndex, network));
-
- MdnsInetAddressRecord inetAddressRecord = mock(MdnsInetAddressRecord.class);
- if (host.contains(":")) {
- when(inetAddressRecord.getInet6Address())
- .thenReturn((Inet6Address) Inet6Address.getByName(host));
- response.setInet6AddressRecord(inetAddressRecord);
- } else {
- when(inetAddressRecord.getInet4Address())
- .thenReturn((Inet4Address) Inet4Address.getByName(host));
- response.setInet4AddressRecord(inetAddressRecord);
- }
-
- MdnsTextRecord textRecord = mock(MdnsTextRecord.class);
- List<String> textStrings = new ArrayList<>();
- List<TextEntry> textEntries = new ArrayList<>();
- for (Map.Entry<String, String> kv : textAttributes.entrySet()) {
- textStrings.add(kv.getKey() + "=" + kv.getValue());
- textEntries.add(new TextEntry(kv.getKey(), kv.getValue().getBytes(UTF_8)));
- }
- when(textRecord.getStrings()).thenReturn(textStrings);
- when(textRecord.getEntries()).thenReturn(textEntries);
-
- response.setServiceRecord(serviceRecord);
- response.setTextRecord(textRecord);
-
- doReturn(false).when(response).isGoodbye();
- doReturn(true).when(response).isComplete();
- doReturn(serviceInstanceName).when(response).getServiceInstanceName();
- doReturn(new ArrayList<>(subtypes)).when(response).getSubtypes();
- return response;
- }
-
- // Creates a mDNS response.
- private MdnsResponse createResponse(
+ private MdnsPacket createResponse(
@NonNull String serviceInstanceName,
@Nullable String host,
int port,
@NonNull String subtype,
@NonNull Map<String, String> textAttributes,
- int interfaceIndex,
- Network network)
+ long ptrTtlMillis)
throws Exception {
- MdnsResponse response = new MdnsResponse(0, interfaceIndex, network);
+ final ArrayList<String> type = new ArrayList<>();
+ type.add(subtype);
+ type.add(MdnsConstants.SUBTYPE_LABEL);
+ type.addAll(Arrays.asList(SERVICE_TYPE_LABELS));
+ return createResponse(serviceInstanceName, host, port, type.toArray(new String[0]),
+ textAttributes, ptrTtlMillis);
+ }
+
+ // Creates a mDNS response.
+ private MdnsPacket createResponse(
+ @NonNull String serviceInstanceName,
+ @Nullable String host,
+ int port,
+ @NonNull String[] type,
+ @NonNull Map<String, String> textAttributes,
+ long ptrTtlMillis) {
+
+ final ArrayList<MdnsRecord> answerRecords = new ArrayList<>();
// Set PTR record
+ final ArrayList<String> serviceNameList = new ArrayList<>();
+ serviceNameList.add(serviceInstanceName);
+ serviceNameList.addAll(Arrays.asList(type));
+ final String[] serviceName = serviceNameList.toArray(new String[0]);
final MdnsPointerRecord pointerRecord = new MdnsPointerRecord(
- new String[]{subtype, MdnsConstants.SUBTYPE_LABEL, "test"} /* name */,
- 0L /* receiptTimeMillis */,
+ type,
+ TEST_ELAPSED_REALTIME /* receiptTimeMillis */,
false /* cacheFlush */,
- 120000L /* ttlMillis */,
- new String[]{serviceInstanceName});
- response.addPointerRecord(pointerRecord);
+ ptrTtlMillis,
+ serviceName);
+ answerRecords.add(pointerRecord);
// Set SRV record.
final MdnsServiceRecord serviceRecord = new MdnsServiceRecord(
- new String[] {"service"} /* name */,
- 0L /* receiptTimeMillis */,
+ serviceName,
+ TEST_ELAPSED_REALTIME /* receiptTimeMillis */,
false /* cacheFlush */,
- 120000L /* ttlMillis */,
+ TEST_TTL,
0 /* servicePriority */,
0 /* serviceWeight */,
port,
new String[]{"hostname"});
- response.setServiceRecord(serviceRecord);
+ answerRecords.add(serviceRecord);
// Set A/AAAA record.
if (host != null) {
- if (InetAddresses.parseNumericAddress(host) instanceof Inet6Address) {
- final MdnsInetAddressRecord inetAddressRecord = new MdnsInetAddressRecord(
- new String[] {"address"} /* name */,
- 0L /* receiptTimeMillis */,
- false /* cacheFlush */,
- 120000L /* ttlMillis */,
- Inet6Address.getByName(host));
- response.setInet6AddressRecord(inetAddressRecord);
- } else {
- final MdnsInetAddressRecord inetAddressRecord = new MdnsInetAddressRecord(
- new String[] {"address"} /* name */,
- 0L /* receiptTimeMillis */,
- false /* cacheFlush */,
- 120000L /* ttlMillis */,
- Inet4Address.getByName(host));
- response.setInet4AddressRecord(inetAddressRecord);
- }
+ final InetAddress addr = InetAddresses.parseNumericAddress(host);
+ final MdnsInetAddressRecord inetAddressRecord = new MdnsInetAddressRecord(
+ new String[] {"hostname"} /* name */,
+ TEST_ELAPSED_REALTIME /* receiptTimeMillis */,
+ false /* cacheFlush */,
+ TEST_TTL,
+ addr);
+ answerRecords.add(inetAddressRecord);
}
// Set TXT record.
@@ -1137,12 +1205,18 @@
textEntries.add(new TextEntry(kv.getKey(), kv.getValue().getBytes(UTF_8)));
}
final MdnsTextRecord textRecord = new MdnsTextRecord(
- new String[] {"text"} /* name */,
- 0L /* receiptTimeMillis */,
+ serviceName,
+ TEST_ELAPSED_REALTIME /* receiptTimeMillis */,
false /* cacheFlush */,
- 120000L /* ttlMillis */,
+ TEST_TTL,
textEntries);
- response.setTextRecord(textRecord);
- return response;
+ answerRecords.add(textRecord);
+ return new MdnsPacket(
+ 0 /* flags */,
+ Collections.emptyList() /* questions */,
+ answerRecords,
+ Collections.emptyList() /* authorityRecords */,
+ Collections.emptyList() /* additionalRecords */
+ );
}
}
\ No newline at end of file
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketClientTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketClientTests.java
index 1d61cd3..abb1747 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketClientTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketClientTests.java
@@ -18,13 +18,11 @@
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
-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.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
@@ -48,7 +46,6 @@
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -373,7 +370,7 @@
mdnsClient.startDiscovery();
verify(mockCallback, timeout(TIMEOUT).atLeast(1))
- .onResponseReceived(any(MdnsResponse.class));
+ .onResponseReceived(any(MdnsPacket.class), anyInt(), any());
}
@Test
@@ -382,7 +379,7 @@
mdnsClient.startDiscovery();
verify(mockCallback, timeout(TIMEOUT).atLeastOnce())
- .onResponseReceived(any(MdnsResponse.class));
+ .onResponseReceived(any(MdnsPacket.class), anyInt(), any());
mdnsClient.stopDiscovery();
}
@@ -415,7 +412,8 @@
mdnsClient.startDiscovery();
verify(mockCallback, timeout(TIMEOUT).atLeast(1))
- .onFailedToParseMdnsResponse(anyInt(), eq(MdnsResponseErrorCode.ERROR_END_OF_FILE));
+ .onFailedToParseMdnsResponse(
+ anyInt(), eq(MdnsResponseErrorCode.ERROR_END_OF_FILE), any());
mdnsClient.stopDiscovery();
}
@@ -436,7 +434,8 @@
mdnsClient.startDiscovery();
verify(mockCallback, timeout(TIMEOUT).atLeast(1))
- .onFailedToParseMdnsResponse(1, MdnsResponseErrorCode.ERROR_END_OF_FILE);
+ .onFailedToParseMdnsResponse(
+ eq(1), eq(MdnsResponseErrorCode.ERROR_END_OF_FILE), any());
mdnsClient.stopDiscovery();
}
@@ -514,7 +513,7 @@
mdnsClient.startDiscovery();
verify(mockCallback, timeout(TIMEOUT).atLeastOnce())
- .onResponseReceived(argThat(response -> response.getInterfaceIndex() == 21));
+ .onResponseReceived(any(), eq(21), any());
}
@Test
@@ -536,11 +535,7 @@
mdnsClient.setCallback(mockCallback);
mdnsClient.startDiscovery();
- ArgumentCaptor<MdnsResponse> mdnsResponseCaptor =
- ArgumentCaptor.forClass(MdnsResponse.class);
verify(mockMulticastSocket, never()).getInterfaceIndex();
- verify(mockCallback, timeout(TIMEOUT).atLeast(1))
- .onResponseReceived(mdnsResponseCaptor.capture());
- assertEquals(-1, mdnsResponseCaptor.getValue().getInterfaceIndex());
+ verify(mockCallback, timeout(TIMEOUT).atLeast(1)).onResponseReceived(any(), eq(-1), any());
}
}
\ No newline at end of file
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
index 635b296..2d73c98 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
@@ -16,6 +16,13 @@
package com.android.server.connectivity.mdns;
+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 com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK;
+import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static com.android.testutils.ContextUtils.mockService;
import static org.junit.Assert.assertEquals;
@@ -23,28 +30,41 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
-import android.net.INetd;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.TetheringManager;
import android.net.TetheringManager.TetheringEventCallback;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
+import android.system.OsConstants;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.net.module.util.ArrayTrackRecord;
+import com.android.net.module.util.SharedLog;
+import com.android.net.module.util.netlink.NetlinkConstants;
+import com.android.net.module.util.netlink.RtNetlinkAddressMessage;
+import com.android.net.module.util.netlink.StructIfaddrMsg;
+import com.android.net.module.util.netlink.StructNlMsgHdr;
import com.android.server.connectivity.mdns.MdnsSocketProvider.Dependencies;
+import com.android.server.connectivity.mdns.internal.SocketNetlinkMonitor;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
@@ -57,23 +77,29 @@
import org.mockito.MockitoAnnotations;
import java.io.IOException;
+import java.net.Inet6Address;
+import java.net.InetAddress;
import java.util.Collections;
import java.util.List;
@RunWith(DevSdkIgnoreRunner.class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class MdnsSocketProviderTest {
+ private static final String TAG = MdnsSocketProviderTest.class.getSimpleName();
private static final String TEST_IFACE_NAME = "test";
private static final String LOCAL_ONLY_IFACE_NAME = "local_only";
private static final String TETHERED_IFACE_NAME = "tethered";
+ private static final int TETHERED_IFACE_IDX = 32;
private static final long DEFAULT_TIMEOUT = 2000L;
private static final long NO_CALLBACK_TIMEOUT = 200L;
private static final LinkAddress LINKADDRV4 = new LinkAddress("192.0.2.0/24");
private static final LinkAddress LINKADDRV6 =
new LinkAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334/64");
- private static final Network TEST_NETWORK = new Network(123);
- private static final Network LOCAL_NETWORK = new Network(INetd.LOCAL_NET_ID);
+ private static final LinkAddress LINKADDRV6_FLAG_CHANGE =
+ new LinkAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334/64", 1 /* flags */,
+ 0 /* scope */);
+ private static final Network TEST_NETWORK = new Network(123);
@Mock private Context mContext;
@Mock private Dependencies mDeps;
@Mock private ConnectivityManager mCm;
@@ -86,6 +112,7 @@
private NetworkCallback mNetworkCallback;
private TetheringEventCallback mTetheringEventCallback;
+ private TestNetLinkMonitor mTestSocketNetLinkMonitor;
@Before
public void setUp() throws IOException {
MockitoAnnotations.initMocks(this);
@@ -99,22 +126,42 @@
// Test is using mockito-extended
doCallRealMethod().when(mContext).getSystemService(TetheringManager.class);
}
- doReturn(true).when(mDeps).canScanOnInterface(any());
- doReturn(mTestNetworkIfaceWrapper).when(mDeps).getNetworkInterfaceByName(TEST_IFACE_NAME);
+ doReturn(mTestNetworkIfaceWrapper).when(mDeps).getNetworkInterfaceByName(anyString());
+ doReturn(true).when(mTestNetworkIfaceWrapper).isUp();
+ doReturn(true).when(mLocalOnlyIfaceWrapper).isUp();
+ doReturn(true).when(mTetheredIfaceWrapper).isUp();
+ doReturn(true).when(mTestNetworkIfaceWrapper).supportsMulticast();
+ doReturn(true).when(mLocalOnlyIfaceWrapper).supportsMulticast();
+ doReturn(true).when(mTetheredIfaceWrapper).supportsMulticast();
doReturn(mLocalOnlyIfaceWrapper).when(mDeps)
.getNetworkInterfaceByName(LOCAL_ONLY_IFACE_NAME);
doReturn(mTetheredIfaceWrapper).when(mDeps).getNetworkInterfaceByName(TETHERED_IFACE_NAME);
doReturn(mock(MdnsInterfaceSocket.class))
.when(mDeps).createMdnsInterfaceSocket(any(), anyInt(), any(), any());
+ doReturn(TETHERED_IFACE_IDX).when(mDeps).getNetworkInterfaceIndexByName(
+ TETHERED_IFACE_NAME);
final HandlerThread thread = new HandlerThread("MdnsSocketProviderTest");
thread.start();
mHandler = new Handler(thread.getLooper());
+ doReturn(mTestSocketNetLinkMonitor).when(mDeps).createSocketNetlinkMonitor(any(), any(),
+ any());
+ doAnswer(inv -> {
+ mTestSocketNetLinkMonitor = new TestNetLinkMonitor(inv.getArgument(0),
+ inv.getArgument(1),
+ inv.getArgument(2));
+ return mTestSocketNetLinkMonitor;
+ }).when(mDeps).createSocketNetlinkMonitor(any(), any(),
+ any());
+ mSocketProvider = new MdnsSocketProvider(mContext, thread.getLooper(), mDeps);
+ }
+
+ private void startMonitoringSockets() {
final ArgumentCaptor<NetworkCallback> nwCallbackCaptor =
ArgumentCaptor.forClass(NetworkCallback.class);
final ArgumentCaptor<TetheringEventCallback> teCallbackCaptor =
ArgumentCaptor.forClass(TetheringEventCallback.class);
- mSocketProvider = new MdnsSocketProvider(mContext, thread.getLooper(), mDeps);
+
mHandler.post(mSocketProvider::startMonitoringSockets);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
verify(mCm).registerNetworkCallback(any(), nwCallbackCaptor.capture(), any());
@@ -122,6 +169,23 @@
mNetworkCallback = nwCallbackCaptor.getValue();
mTetheringEventCallback = teCallbackCaptor.getValue();
+
+ mHandler.post(mSocketProvider::startNetLinkMonitor);
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ }
+
+ private static class TestNetLinkMonitor extends SocketNetlinkMonitor {
+ TestNetLinkMonitor(@NonNull Handler handler,
+ @NonNull SharedLog log,
+ @Nullable MdnsSocketProvider.NetLinkMonitorCallBack cb) {
+ super(handler, log, cb);
+ }
+
+ @Override
+ public void startMonitoring() { }
+
+ @Override
+ public void stopMonitoring() { }
}
private class TestSocketCallback implements MdnsSocketProvider.SocketCallback {
@@ -203,19 +267,34 @@
}
}
+ private static NetworkCapabilities makeCapabilities(int... transports) {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+ for (int transport : transports) {
+ nc.addTransportType(transport);
+ }
+ return nc;
+ }
+
+ private void postNetworkAvailable(int... transports) {
+ final LinkProperties testLp = new LinkProperties();
+ testLp.setInterfaceName(TEST_IFACE_NAME);
+ testLp.setLinkAddresses(List.of(LINKADDRV4));
+ final NetworkCapabilities testNc = makeCapabilities(transports);
+ mHandler.post(() -> mNetworkCallback.onCapabilitiesChanged(TEST_NETWORK, testNc));
+ mHandler.post(() -> mNetworkCallback.onLinkPropertiesChanged(TEST_NETWORK, testLp));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ }
+
@Test
public void testSocketRequestAndUnrequestSocket() {
+ startMonitoringSockets();
+
final TestSocketCallback testCallback1 = new TestSocketCallback();
mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback1));
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
testCallback1.expectedNoCallback();
- final LinkProperties testLp = new LinkProperties();
- testLp.setInterfaceName(TEST_IFACE_NAME);
- testLp.setLinkAddresses(List.of(LINKADDRV4));
- mHandler.post(() -> mNetworkCallback.onLinkPropertiesChanged(TEST_NETWORK, testLp));
- HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
- verify(mTestNetworkIfaceWrapper).getNetworkInterface();
+ postNetworkAvailable(TRANSPORT_WIFI);
testCallback1.expectedSocketCreatedForNetwork(TEST_NETWORK, List.of(LINKADDRV4));
final TestSocketCallback testCallback2 = new TestSocketCallback();
@@ -237,7 +316,7 @@
verify(mLocalOnlyIfaceWrapper).getNetworkInterface();
testCallback1.expectedNoCallback();
testCallback2.expectedNoCallback();
- testCallback3.expectedSocketCreatedForNetwork(LOCAL_NETWORK, List.of());
+ testCallback3.expectedSocketCreatedForNetwork(null /* network */, List.of());
mHandler.post(() -> mTetheringEventCallback.onTetheredInterfacesChanged(
List.of(TETHERED_IFACE_NAME)));
@@ -245,7 +324,7 @@
verify(mTetheredIfaceWrapper).getNetworkInterface();
testCallback1.expectedNoCallback();
testCallback2.expectedNoCallback();
- testCallback3.expectedSocketCreatedForNetwork(LOCAL_NETWORK, List.of());
+ testCallback3.expectedSocketCreatedForNetwork(null /* network */, List.of());
mHandler.post(() -> mSocketProvider.unrequestSocket(testCallback1));
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
@@ -263,23 +342,178 @@
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
testCallback1.expectedNoCallback();
testCallback2.expectedNoCallback();
- testCallback3.expectedInterfaceDestroyedForNetwork(LOCAL_NETWORK);
+ testCallback3.expectedInterfaceDestroyedForNetwork(null /* network */);
mHandler.post(() -> mSocketProvider.unrequestSocket(testCallback3));
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
testCallback1.expectedNoCallback();
testCallback2.expectedNoCallback();
// Expect the socket destroy for tethered interface.
- testCallback3.expectedInterfaceDestroyedForNetwork(LOCAL_NETWORK);
+ testCallback3.expectedInterfaceDestroyedForNetwork(null /* network */);
+ }
+
+ private RtNetlinkAddressMessage createNetworkAddressUpdateNetLink(
+ short msgType, LinkAddress linkAddress, int ifIndex, int flags) {
+ final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
+ nlmsghdr.nlmsg_type = msgType;
+ nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ nlmsghdr.nlmsg_seq = 1;
+
+ InetAddress ip = linkAddress.getAddress();
+
+ final byte family =
+ (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET);
+ StructIfaddrMsg structIfaddrMsg = new StructIfaddrMsg(family,
+ (short) linkAddress.getPrefixLength(),
+ (short) linkAddress.getFlags(), (short) linkAddress.getScope(), ifIndex);
+
+ return new RtNetlinkAddressMessage(nlmsghdr, structIfaddrMsg, ip,
+ null /* structIfacacheInfo */, flags);
+ }
+
+ @Test
+ public void testDownstreamNetworkAddressUpdateFromNetlink() {
+ startMonitoringSockets();
+ final TestSocketCallback testCallbackAll = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(null /* network */, testCallbackAll));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+
+ // Address add message arrived before the interface is created.
+ RtNetlinkAddressMessage addIpv4AddrMsg = createNetworkAddressUpdateNetLink(
+ NetlinkConstants.RTM_NEWADDR,
+ LINKADDRV4,
+ TETHERED_IFACE_IDX,
+ 0 /* flags */);
+ mHandler.post(
+ () -> mTestSocketNetLinkMonitor.processNetlinkMessage(addIpv4AddrMsg,
+ 0 /* whenMs */));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+
+ // Interface is created.
+ mHandler.post(() -> mTetheringEventCallback.onTetheredInterfacesChanged(
+ List.of(TETHERED_IFACE_NAME)));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ verify(mTetheredIfaceWrapper).getNetworkInterface();
+ testCallbackAll.expectedSocketCreatedForNetwork(null /* network */, List.of(LINKADDRV4));
+
+ // Old Address removed.
+ RtNetlinkAddressMessage removeIpv4AddrMsg = createNetworkAddressUpdateNetLink(
+ NetlinkConstants.RTM_DELADDR,
+ LINKADDRV4,
+ TETHERED_IFACE_IDX,
+ 0 /* flags */);
+ mHandler.post(
+ () -> mTestSocketNetLinkMonitor.processNetlinkMessage(removeIpv4AddrMsg,
+ 0 /* whenMs */));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ testCallbackAll.expectedAddressesChangedForNetwork(null /* network */, List.of());
+
+ // New address added.
+ RtNetlinkAddressMessage addIpv6AddrMsg = createNetworkAddressUpdateNetLink(
+ NetlinkConstants.RTM_NEWADDR,
+ LINKADDRV6,
+ TETHERED_IFACE_IDX,
+ 0 /* flags */);
+ mHandler.post(() -> mTestSocketNetLinkMonitor.processNetlinkMessage(addIpv6AddrMsg,
+ 0 /* whenMs */));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ testCallbackAll.expectedAddressesChangedForNetwork(null /* network */, List.of(LINKADDRV6));
+
+ // Address updated
+ RtNetlinkAddressMessage updateIpv6AddrMsg = createNetworkAddressUpdateNetLink(
+ NetlinkConstants.RTM_NEWADDR,
+ LINKADDRV6,
+ TETHERED_IFACE_IDX,
+ 1 /* flags */);
+ mHandler.post(
+ () -> mTestSocketNetLinkMonitor.processNetlinkMessage(updateIpv6AddrMsg,
+ 0 /* whenMs */));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ testCallbackAll.expectedAddressesChangedForNetwork(null /* network */,
+ List.of(LINKADDRV6_FLAG_CHANGE));
}
@Test
public void testAddressesChanged() throws Exception {
+ startMonitoringSockets();
+
final TestSocketCallback testCallback = new TestSocketCallback();
mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback));
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
testCallback.expectedNoCallback();
+ postNetworkAvailable(TRANSPORT_WIFI);
+ testCallback.expectedSocketCreatedForNetwork(TEST_NETWORK, List.of(LINKADDRV4));
+
+ final LinkProperties newTestLp = new LinkProperties();
+ newTestLp.setInterfaceName(TEST_IFACE_NAME);
+ newTestLp.setLinkAddresses(List.of(LINKADDRV4, LINKADDRV6));
+ mHandler.post(() -> mNetworkCallback.onLinkPropertiesChanged(TEST_NETWORK, newTestLp));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ testCallback.expectedAddressesChangedForNetwork(
+ TEST_NETWORK, List.of(LINKADDRV4, LINKADDRV6));
+ }
+
+ @Test
+ public void testStartAndStopMonitoringSockets() {
+ // Stop monitoring sockets before start. Should not unregister any network callback.
+ mHandler.post(mSocketProvider::requestStopWhenInactive);
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ verify(mCm, never()).unregisterNetworkCallback(any(NetworkCallback.class));
+ verify(mTm, never()).unregisterTetheringEventCallback(any(TetheringEventCallback.class));
+
+ // Start sockets monitoring.
+ startMonitoringSockets();
+ // Request a socket then unrequest it. Expect no network callback unregistration.
+ final TestSocketCallback testCallback = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ testCallback.expectedNoCallback();
+ mHandler.post(()-> mSocketProvider.unrequestSocket(testCallback));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ verify(mCm, never()).unregisterNetworkCallback(any(NetworkCallback.class));
+ verify(mTm, never()).unregisterTetheringEventCallback(any(TetheringEventCallback.class));
+ // Request stop and it should unregister network callback immediately because there is no
+ // socket request.
+ mHandler.post(mSocketProvider::requestStopWhenInactive);
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ verify(mCm, times(1)).unregisterNetworkCallback(any(NetworkCallback.class));
+ verify(mTm, times(1)).unregisterTetheringEventCallback(any(TetheringEventCallback.class));
+
+ // Start sockets monitoring and request a socket again.
+ mHandler.post(mSocketProvider::startMonitoringSockets);
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ verify(mCm, times(2)).registerNetworkCallback(any(), any(NetworkCallback.class), any());
+ verify(mTm, times(2)).registerTetheringEventCallback(
+ any(), any(TetheringEventCallback.class));
+ final TestSocketCallback testCallback2 = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback2));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ testCallback2.expectedNoCallback();
+ // Try to stop monitoring sockets but should be ignored and wait until all socket are
+ // unrequested.
+ mHandler.post(mSocketProvider::requestStopWhenInactive);
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ verify(mCm, times(1)).unregisterNetworkCallback(any(NetworkCallback.class));
+ verify(mTm, times(1)).unregisterTetheringEventCallback(any());
+ // Unrequest the socket then network callbacks should be unregistered.
+ mHandler.post(()-> mSocketProvider.unrequestSocket(testCallback2));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ verify(mCm, times(2)).unregisterNetworkCallback(any(NetworkCallback.class));
+ verify(mTm, times(2)).unregisterTetheringEventCallback(any(TetheringEventCallback.class));
+ }
+
+ @Test
+ public void testLinkPropertiesAreClearedAfterStopMonitoringSockets() {
+ startMonitoringSockets();
+
+ // Request a socket with null network.
+ final TestSocketCallback testCallback = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(null, testCallback));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ testCallback.expectedNoCallback();
+
+ // Notify a LinkPropertiesChanged with TEST_NETWORK.
final LinkProperties testLp = new LinkProperties();
testLp.setInterfaceName(TEST_IFACE_NAME);
testLp.setLinkAddresses(List.of(LINKADDRV4));
@@ -288,13 +522,108 @@
verify(mTestNetworkIfaceWrapper, times(1)).getNetworkInterface();
testCallback.expectedSocketCreatedForNetwork(TEST_NETWORK, List.of(LINKADDRV4));
- final LinkProperties newTestLp = new LinkProperties();
- newTestLp.setInterfaceName(TEST_IFACE_NAME);
- newTestLp.setLinkAddresses(List.of(LINKADDRV4, LINKADDRV6));
- mHandler.post(() -> mNetworkCallback.onLinkPropertiesChanged(TEST_NETWORK, newTestLp));
+ // Try to stop monitoring and unrequest the socket.
+ mHandler.post(mSocketProvider::requestStopWhenInactive);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
- verify(mTestNetworkIfaceWrapper, times(1)).getNetworkInterface();
- testCallback.expectedAddressesChangedForNetwork(
- TEST_NETWORK, List.of(LINKADDRV4, LINKADDRV6));
+ mHandler.post(()-> mSocketProvider.unrequestSocket(testCallback));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ testCallback.expectedInterfaceDestroyedForNetwork(TEST_NETWORK);
+ verify(mCm, times(1)).unregisterNetworkCallback(any(NetworkCallback.class));
+ verify(mTm, times(1)).unregisterTetheringEventCallback(any());
+
+ // Start sockets monitoring and request a socket again. Expected no socket created callback
+ // because all saved LinkProperties has been cleared.
+ mHandler.post(mSocketProvider::startMonitoringSockets);
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ verify(mCm, times(2)).registerNetworkCallback(any(), any(NetworkCallback.class), any());
+ verify(mTm, times(2)).registerTetheringEventCallback(
+ any(), any(TetheringEventCallback.class));
+ mHandler.post(() -> mSocketProvider.requestSocket(null, testCallback));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ testCallback.expectedNoCallback();
+
+ // Notify a LinkPropertiesChanged with another network.
+ final LinkProperties otherLp = new LinkProperties();
+ final LinkAddress otherAddress = new LinkAddress("192.0.2.1/24");
+ final Network otherNetwork = new Network(456);
+ otherLp.setInterfaceName("test2");
+ otherLp.setLinkAddresses(List.of(otherAddress));
+ mHandler.post(() -> mNetworkCallback.onLinkPropertiesChanged(otherNetwork, otherLp));
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ verify(mTestNetworkIfaceWrapper, times(2)).getNetworkInterface();
+ testCallback.expectedSocketCreatedForNetwork(otherNetwork, List.of(otherAddress));
+ }
+
+ @Test
+ public void testNoSocketCreatedForCellular() {
+ startMonitoringSockets();
+
+ final TestSocketCallback testCallback = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback));
+
+ postNetworkAvailable(TRANSPORT_CELLULAR);
+ testCallback.expectedNoCallback();
+ }
+
+ @Test
+ public void testNoSocketCreatedForNonMulticastInterface() throws Exception {
+ doReturn(false).when(mTestNetworkIfaceWrapper).supportsMulticast();
+ startMonitoringSockets();
+
+ final TestSocketCallback testCallback = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback));
+
+ postNetworkAvailable(TRANSPORT_BLUETOOTH);
+ testCallback.expectedNoCallback();
+ }
+
+ @Test
+ public void testSocketCreatedForMulticastInterface() throws Exception {
+ doReturn(true).when(mTestNetworkIfaceWrapper).supportsMulticast();
+ startMonitoringSockets();
+
+ final TestSocketCallback testCallback = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback));
+
+ postNetworkAvailable(TRANSPORT_BLUETOOTH);
+ testCallback.expectedSocketCreatedForNetwork(TEST_NETWORK, List.of(LINKADDRV4));
+ }
+
+ @Test
+ public void testNoSocketCreatedForPTPInterface() throws Exception {
+ doReturn(true).when(mTestNetworkIfaceWrapper).isPointToPoint();
+ startMonitoringSockets();
+
+ final TestSocketCallback testCallback = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback));
+
+ postNetworkAvailable(TRANSPORT_BLUETOOTH);
+ testCallback.expectedNoCallback();
+ }
+
+ @Test
+ public void testNoSocketCreatedForVPNInterface() throws Exception {
+ // VPN interfaces generally also have IFF_POINTOPOINT, but even if they don't, they should
+ // not be included even with TRANSPORT_WIFI.
+ doReturn(false).when(mTestNetworkIfaceWrapper).supportsMulticast();
+ startMonitoringSockets();
+
+ final TestSocketCallback testCallback = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback));
+
+ postNetworkAvailable(TRANSPORT_VPN, TRANSPORT_WIFI);
+ testCallback.expectedNoCallback();
+ }
+
+ @Test
+ public void testSocketCreatedForWifiWithoutMulticastFlag() throws Exception {
+ doReturn(false).when(mTestNetworkIfaceWrapper).supportsMulticast();
+ startMonitoringSockets();
+
+ final TestSocketCallback testCallback = new TestSocketCallback();
+ mHandler.post(() -> mSocketProvider.requestSocket(TEST_NETWORK, testCallback));
+
+ postNetworkAvailable(TRANSPORT_WIFI);
+ testCallback.expectedSocketCreatedForNetwork(TEST_NETWORK, List.of(LINKADDRV4));
}
}
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
index 5e7f0ff..e6aba22 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
@@ -86,8 +86,9 @@
}
@After
- public void cleanUp() {
+ public void cleanUp() throws InterruptedException {
mHandlerThread.quitSafely();
+ mHandlerThread.join();
}
private void initMockResources() {
diff --git a/tests/unit/java/com/android/server/net/IpConfigStoreTest.java b/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
index 4adc999..dcf0f75 100644
--- a/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
+++ b/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
@@ -36,7 +36,6 @@
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
-import com.android.testutils.HandlerUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -58,7 +57,7 @@
@RunWith(DevSdkIgnoreRunner.class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class IpConfigStoreTest {
- private static final int TIMEOUT_MS = 2_000;
+ private static final int TIMEOUT_MS = 5_000;
private static final int KEY_CONFIG = 17;
private static final String IFACE_1 = "eth0";
private static final String IFACE_2 = "eth1";
@@ -139,6 +138,8 @@
}
@Override
public void quitHandlerThread(HandlerThread handlerThread) {
+ // Don't join in here, quitHandlerThread runs on the
+ // handler thread itself.
testHandlerThread.quitSafely();
}
};
@@ -155,7 +156,7 @@
final DelayedDiskWrite writer = new DelayedDiskWrite(dependencies);
final IpConfigStore store = new IpConfigStore(writer);
store.writeIpConfigurations(configFile.getPath(), expectedNetworks);
- HandlerUtils.waitForIdle(testHandlerThread, TIMEOUT_MS);
+ testHandlerThread.join();
// Read IP config from the file path.
final ArrayMap<String, IpConfiguration> actualNetworks =
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
index 04db6d3..63daebc 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -472,8 +472,7 @@
256L, 16L, 512L, 32L, 0L)
.insertEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 64L, 3L, 1024L, 8L, 0L);
- doReturn(stats).when(mDeps).getNetworkStatsDetail(anyInt(), any(),
- anyInt());
+ doReturn(stats).when(mDeps).getNetworkStatsDetail();
final String[] ifaces = new String[]{TEST_IFACE};
final NetworkStats res = mFactory.readNetworkStatsDetail(UID_ALL, ifaces, TAG_ALL);
@@ -488,8 +487,7 @@
mFactory.removeUidsLocked(removedUids);
// Return empty stats for reading the result of removing uids stats later.
- doReturn(buildEmptyStats()).when(mDeps).getNetworkStatsDetail(anyInt(), any(),
- anyInt());
+ doReturn(buildEmptyStats()).when(mDeps).getNetworkStatsDetail();
final NetworkStats removedUidsStats =
mFactory.readNetworkStatsDetail(UID_ALL, ifaces, TAG_ALL);
@@ -574,8 +572,7 @@
final NetworkStats statsFromResource = parseNetworkStatsFromGoldenSample(resourceId,
24 /* initialSize */, true /* consumeHeader */, false /* checkActive */,
true /* isUidData */);
- doReturn(statsFromResource).when(mDeps).getNetworkStatsDetail(anyInt(), any(),
- anyInt());
+ doReturn(statsFromResource).when(mDeps).getNetworkStatsDetail();
return mFactory.readNetworkStatsDetail();
}
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 13a6a6f..04163fd 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -82,7 +82,6 @@
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -395,10 +394,6 @@
verify(mNetd).registerUnsolicitedEventListener(alertObserver.capture());
mAlertObserver = alertObserver.getValue();
- // Make augmentWithStackedInterfaces returns the interfaces that was passed to it.
- doAnswer(inv -> ((String[]) inv.getArgument(0)).clone())
- .when(mStatsFactory).augmentWithStackedInterfaces(any());
-
// Catch TetheringEventCallback during systemReady().
ArgumentCaptor<TetheringManager.TetheringEventCallback> tetheringEventCbCaptor =
ArgumentCaptor.forClass(TetheringManager.TetheringEventCallback.class);
@@ -544,6 +539,7 @@
mService = null;
mHandlerThread.quitSafely();
+ mHandlerThread.join();
}
private void initWifiStats(NetworkStateSnapshot snapshot) throws Exception {
diff --git a/tests/unit/res/xml/self_certified_capabilities_bandwidth.xml b/tests/unit/res/xml/self_certified_capabilities_bandwidth.xml
new file mode 100644
index 0000000..01fdca1
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_bandwidth.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+</network-capabilities-declaration>
diff --git a/tests/unit/res/xml/self_certified_capabilities_both.xml b/tests/unit/res/xml/self_certified_capabilities_both.xml
new file mode 100644
index 0000000..4066be2
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_both.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+</network-capabilities-declaration>
diff --git a/tests/unit/res/xml/self_certified_capabilities_latency.xml b/tests/unit/res/xml/self_certified_capabilities_latency.xml
new file mode 100644
index 0000000..1c4a0e0
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_latency.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+</network-capabilities-declaration>
diff --git a/tests/unit/res/xml/self_certified_capabilities_other.xml b/tests/unit/res/xml/self_certified_capabilities_other.xml
new file mode 100644
index 0000000..5b6649c
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_other.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="other"/>
+</network-capabilities-declaration>
diff --git a/tests/unit/res/xml/self_certified_capabilities_wrong_declaration.xml b/tests/unit/res/xml/self_certified_capabilities_wrong_declaration.xml
new file mode 100644
index 0000000..6082356
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_wrong_declaration.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration1 xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+</network-capabilities-declaration1>
diff --git a/tests/unit/res/xml/self_certified_capabilities_wrong_tag.xml b/tests/unit/res/xml/self_certified_capabilities_wrong_tag.xml
new file mode 100644
index 0000000..c9ecc0b
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_wrong_tag.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability1 android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+</network-capabilities-declaration>
diff --git a/tools/gen_jarjar.py b/tools/gen_jarjar.py
index eb686ce..5129128 100755
--- a/tools/gen_jarjar.py
+++ b/tools/gen_jarjar.py
@@ -120,9 +120,11 @@
_get_toplevel_class(clazz) not in excluded_classes and
not any(r.fullmatch(clazz) for r in exclude_regexes)):
outfile.write(f'rule {clazz} {args.prefix}.@0\n')
- # Also include jarjar rules for unit tests of the class, so the package matches
- outfile.write(f'rule {clazz}Test {args.prefix}.@0\n')
- outfile.write(f'rule {clazz}Test$* {args.prefix}.@0\n')
+ # Also include jarjar rules for unit tests of the class if it's not explicitly
+ # excluded, so the package matches
+ if not any(r.fullmatch(clazz + 'Test') for r in exclude_regexes):
+ outfile.write(f'rule {clazz}Test {args.prefix}.@0\n')
+ outfile.write(f'rule {clazz}Test$* {args.prefix}.@0\n')
def _main():
diff --git a/tools/gn2bp/Android.bp.swp b/tools/gn2bp/Android.bp.swp
deleted file mode 100644
index 9f34b06..0000000
--- a/tools/gn2bp/Android.bp.swp
+++ /dev/null
@@ -1,10867 +0,0 @@
-// Copyright (C) 2022 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.
-//
-// This file is automatically generated by gen_android_bp. Do not edit.
-
-// GN: PACKAGE
-package {
- default_applicable_licenses: [
- "external_cronet_license",
- ],
-}
-
-// GN: //components/cronet/android:cronet_api_java
-java_library {
- name: "cronet_aml_api_java",
- srcs: [
- ":cronet_aml_api_sources",
- ],
- libs: [
- "androidx.annotation_annotation",
- "framework-annotations-lib",
- ],
- sdk_version: "module_current",
-}
-
-// GN: //components/cronet/android:cronet_api_java
-// TODO(danstahr): add the API helpers separately after the main API is checked in and thoroughly reviewed
-filegroup {
- name: "cronet_aml_api_sources",
- srcs: [
- ":cronet_aml_components_cronet_android_interface_api_version",
- "components/cronet/android/api/src/android/net/http/BidirectionalStream.java",
- "components/cronet/android/api/src/android/net/http/CallbackException.java",
- "components/cronet/android/api/src/android/net/http/ConnectionMigrationOptions.java",
- "components/cronet/android/api/src/android/net/http/DnsOptions.java",
- "components/cronet/android/api/src/android/net/http/ExperimentalBidirectionalStream.java",
- "components/cronet/android/api/src/android/net/http/ExperimentalHttpEngine.java",
- "components/cronet/android/api/src/android/net/http/ExperimentalUrlRequest.java",
- "components/cronet/android/api/src/android/net/http/HttpEngine.java",
- "components/cronet/android/api/src/android/net/http/HttpException.java",
- "components/cronet/android/api/src/android/net/http/IHttpEngineBuilder.java",
- "components/cronet/android/api/src/android/net/http/InlineExecutionProhibitedException.java",
- "components/cronet/android/api/src/android/net/http/NetworkException.java",
- "components/cronet/android/api/src/android/net/http/NetworkQualityRttListener.java",
- "components/cronet/android/api/src/android/net/http/NetworkQualityThroughputListener.java",
- "components/cronet/android/api/src/android/net/http/QuicException.java",
- "components/cronet/android/api/src/android/net/http/QuicOptions.java",
- "components/cronet/android/api/src/android/net/http/RequestFinishedInfo.java",
- "components/cronet/android/api/src/android/net/http/UploadDataProvider.java",
- "components/cronet/android/api/src/android/net/http/UploadDataSink.java",
- "components/cronet/android/api/src/android/net/http/UrlRequest.java",
- "components/cronet/android/api/src/android/net/http/UrlResponseInfo.java",
- ],
-}
-
-// GN: //base/allocator:buildflags
-cc_genrule {
- name: "cronet_aml_base_allocator_buildflags",
- cmd: "echo '--flags USE_ALLOCATOR_SHIM=\"true\" USE_PARTITION_ALLOC=\"false\" USE_PARTITION_ALLOC_AS_MALLOC=\"false\" USE_BACKUP_REF_PTR=\"false\" USE_ASAN_BACKUP_REF_PTR=\"false\" USE_PARTITION_ALLOC_AS_GWP_ASAN_STORE=\"false\" USE_MTE_CHECKED_PTR=\"false\" FORCE_ENABLE_RAW_PTR_EXCLUSION=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base/allocator:buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/allocator/buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base/allocator/partition_allocator:chromecast_buildflags
-cc_genrule {
- name: "cronet_aml_base_allocator_partition_allocator_chromecast_buildflags",
- cmd: "echo '--flags PA_IS_CAST_ANDROID=\"false\" PA_IS_CASTOS=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base/allocator/partition_allocator:chromecast_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/allocator/partition_allocator/chromecast_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base/allocator/partition_allocator:chromeos_buildflags
-cc_genrule {
- name: "cronet_aml_base_allocator_partition_allocator_chromeos_buildflags",
- cmd: "echo '--flags PA_IS_CHROMEOS_ASH=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base/allocator/partition_allocator:chromeos_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/allocator/partition_allocator/chromeos_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base/allocator/partition_allocator:debugging_buildflags
-cc_genrule {
- name: "cronet_aml_base_allocator_partition_allocator_debugging_buildflags",
- cmd: "echo '--flags PA_DCHECK_IS_ON=\"false\" PA_EXPENSIVE_DCHECKS_ARE_ON=\"false\" PA_DCHECK_IS_CONFIGURABLE=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base/allocator/partition_allocator:debugging_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base/allocator/partition_allocator:logging_buildflags
-cc_genrule {
- name: "cronet_aml_base_allocator_partition_allocator_logging_buildflags",
- cmd: "echo '--flags PA_ENABLE_LOG_ERROR_NOT_REACHED=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base/allocator/partition_allocator:logging_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/allocator/partition_allocator/logging_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base/allocator/partition_allocator:partition_alloc
-cc_library_static {
- name: "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- srcs: [
- ":cronet_aml_third_party_android_ndk_cpu_features",
- "base/allocator/partition_allocator/address_pool_manager.cc",
- "base/allocator/partition_allocator/address_pool_manager_bitmap.cc",
- "base/allocator/partition_allocator/address_space_randomization.cc",
- "base/allocator/partition_allocator/allocation_guard.cc",
- "base/allocator/partition_allocator/dangling_raw_ptr_checks.cc",
- "base/allocator/partition_allocator/gwp_asan_support.cc",
- "base/allocator/partition_allocator/memory_reclaimer.cc",
- "base/allocator/partition_allocator/oom.cc",
- "base/allocator/partition_allocator/oom_callback.cc",
- "base/allocator/partition_allocator/page_allocator.cc",
- "base/allocator/partition_allocator/page_allocator_internals_posix.cc",
- "base/allocator/partition_allocator/partition_address_space.cc",
- "base/allocator/partition_allocator/partition_alloc.cc",
- "base/allocator/partition_allocator/partition_alloc_base/check.cc",
- "base/allocator/partition_allocator/partition_alloc_base/cpu.cc",
- "base/allocator/partition_allocator/partition_alloc_base/debug/alias.cc",
- "base/allocator/partition_allocator/partition_alloc_base/files/file_path.cc",
- "base/allocator/partition_allocator/partition_alloc_base/files/file_util_posix.cc",
- "base/allocator/partition_allocator/partition_alloc_base/logging.cc",
- "base/allocator/partition_allocator/partition_alloc_base/memory/ref_counted.cc",
- "base/allocator/partition_allocator/partition_alloc_base/native_library.cc",
- "base/allocator/partition_allocator/partition_alloc_base/native_library_posix.cc",
- "base/allocator/partition_allocator/partition_alloc_base/posix/safe_strerror.cc",
- "base/allocator/partition_allocator/partition_alloc_base/rand_util.cc",
- "base/allocator/partition_allocator/partition_alloc_base/rand_util_posix.cc",
- "base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.cc",
- "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread.cc",
- "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread_posix.cc",
- "base/allocator/partition_allocator/partition_alloc_base/time/time.cc",
- "base/allocator/partition_allocator/partition_alloc_base/time/time_android.cc",
- "base/allocator/partition_allocator/partition_alloc_base/time/time_conversion_posix.cc",
- "base/allocator/partition_allocator/partition_alloc_base/time/time_now_posix.cc",
- "base/allocator/partition_allocator/partition_alloc_base/time/time_override.cc",
- "base/allocator/partition_allocator/partition_alloc_hooks.cc",
- "base/allocator/partition_allocator/partition_bucket.cc",
- "base/allocator/partition_allocator/partition_oom.cc",
- "base/allocator/partition_allocator/partition_page.cc",
- "base/allocator/partition_allocator/partition_root.cc",
- "base/allocator/partition_allocator/partition_stats.cc",
- "base/allocator/partition_allocator/random.cc",
- "base/allocator/partition_allocator/reservation_offset_table.cc",
- "base/allocator/partition_allocator/spinning_mutex.cc",
- "base/allocator/partition_allocator/starscan/metadata_allocator.cc",
- "base/allocator/partition_allocator/starscan/pcscan.cc",
- "base/allocator/partition_allocator/starscan/pcscan_internal.cc",
- "base/allocator/partition_allocator/starscan/pcscan_scheduling.cc",
- "base/allocator/partition_allocator/starscan/snapshot.cc",
- "base/allocator/partition_allocator/starscan/stack/stack.cc",
- "base/allocator/partition_allocator/starscan/stats_collector.cc",
- "base/allocator/partition_allocator/starscan/write_protector.cc",
- "base/allocator/partition_allocator/tagging.cc",
- "base/allocator/partition_allocator/thread_cache.cc",
- ],
- generated_headers: [
- "cronet_aml_base_allocator_partition_allocator_chromecast_buildflags",
- "cronet_aml_base_allocator_partition_allocator_chromeos_buildflags",
- "cronet_aml_base_allocator_partition_allocator_debugging_buildflags",
- "cronet_aml_base_allocator_partition_allocator_logging_buildflags",
- "cronet_aml_base_allocator_partition_allocator_partition_alloc_buildflags",
- ],
- export_generated_headers: [
- "cronet_aml_base_allocator_partition_allocator_chromecast_buildflags",
- "cronet_aml_base_allocator_partition_allocator_chromeos_buildflags",
- "cronet_aml_base_allocator_partition_allocator_debugging_buildflags",
- "cronet_aml_base_allocator_partition_allocator_logging_buildflags",
- "cronet_aml_base_allocator_partition_allocator_partition_alloc_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DIS_PARTITION_ALLOC_IMPL",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-DPA_PCSCAN_STACK_SUPPORTED",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/android_ndk/sources/android/cpufeatures/",
- ],
- header_libs: [
- "libgtest_prod_headers",
- ],
- cpp_std: "c++17",
- target: {
- android_arm: {
- srcs: [
- "base/allocator/partition_allocator/starscan/stack/asm/arm/push_registers_asm.cc",
- ],
- },
- android_arm64: {
- srcs: [
- "base/allocator/partition_allocator/starscan/stack/asm/arm64/push_registers_asm.cc",
- ],
- cflags: [
- "-march=armv8-a+memtag",
- ],
- },
- android_x86: {
- srcs: [
- "base/allocator/partition_allocator/starscan/stack/asm/x86/push_registers_asm.cc",
- ],
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- srcs: [
- "base/allocator/partition_allocator/starscan/stack/asm/x64/push_registers_asm.cc",
- ],
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //base/allocator/partition_allocator:partition_alloc_buildflags
-cc_genrule {
- name: "cronet_aml_base_allocator_partition_allocator_partition_alloc_buildflags",
- cmd: "echo '--flags ENABLE_PARTITION_ALLOC_AS_MALLOC_SUPPORT=\"true\" ENABLE_BACKUP_REF_PTR_SUPPORT=\"true\" ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=\"false\" ENABLE_DANGLING_RAW_PTR_CHECKS=\"false\" PUT_REF_COUNT_IN_PREVIOUS_SLOT=\"true\" ENABLE_GWP_ASAN_SUPPORT=\"true\" ENABLE_MTE_CHECKED_PTR_SUPPORT=\"false\" RECORD_ALLOC_INFO=\"false\" USE_FREESLOT_BITMAP=\"false\" ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS=\"false\" STARSCAN=\"true\" PA_USE_BASE_TRACING=\"true\" ENABLE_PKEYS=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base/allocator/partition_allocator:partition_alloc_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/allocator/partition_allocator/partition_alloc_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:anchor_functions_buildflags
-cc_genrule {
- name: "cronet_aml_base_anchor_functions_buildflags",
- cmd: "echo '--flags USE_LLD=\"true\" SUPPORTS_CODE_ORDERING=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:anchor_functions_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/android/library_loader/anchor_functions_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:android_runtime_jni_headers
-cc_genrule {
- name: "cronet_aml_base_android_runtime_jni_headers",
- cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
- "long " +
- "--output_dir " +
- "$(genDir)/base/android_runtime_jni_headers " +
- "--includes " +
- "base/android/jni_generator/jni_generator_helper.h " +
- "--jar_file " +
- "$(location :current_android_jar) " +
- "--output_name " +
- "Runnable_jni.h " +
- "--output_name " +
- "Runtime_jni.h " +
- "--input_file " +
- "java/lang/Runnable.class " +
- "--input_file " +
- "java/lang/Runtime.class " +
- "--javap " +
- "$$(find $${OUT_DIR:-out}/.path -name javap) " +
- "--package_prefix " +
- "android.net.http.internal",
- out: [
- "base/android_runtime_jni_headers/Runnable_jni.h",
- "base/android_runtime_jni_headers/Runtime_jni.h",
- ],
- tool_files: [
- ":current_android_jar",
- "base/android/jni_generator/android_jar.classes",
- "base/android/jni_generator/jni_generator.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/gn_helpers.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:base
-cc_library_static {
- name: "cronet_aml_base_base",
- srcs: [
- ":cronet_aml_base_nodebug_assertion",
- ":cronet_aml_third_party_abseil_cpp_absl_base_base",
- ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity",
- ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait",
- ":cronet_aml_third_party_abseil_cpp_absl_base_strerror",
- ":cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate",
- ":cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler",
- ":cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize",
- ":cronet_aml_third_party_abseil_cpp_absl_hash_city",
- ":cronet_aml_third_party_abseil_cpp_absl_hash_hash",
- ":cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash",
- ":cronet_aml_third_party_abseil_cpp_absl_numeric_int128",
- ":cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased",
- ":cronet_aml_third_party_abseil_cpp_absl_random_distributions",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_platform",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material",
- ":cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception",
- ":cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences",
- ":cronet_aml_third_party_abseil_cpp_absl_status_status",
- ":cronet_aml_third_party_abseil_cpp_absl_status_statusor",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cord",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_strings",
- ":cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization",
- ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time",
- ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone",
- ":cronet_aml_third_party_abseil_cpp_absl_time_time",
- ":cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access",
- ":cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access",
- ":cronet_aml_third_party_android_ndk_cpu_features",
- ":cronet_aml_third_party_ashmem_ashmem",
- "base/allocator/allocator_check.cc",
- "base/allocator/allocator_extension.cc",
- "base/allocator/dispatcher/dispatcher.cc",
- "base/allocator/dispatcher/internal/dispatch_data.cc",
- "base/allocator/dispatcher/reentry_guard.cc",
- "base/allocator/partition_allocator/shim/allocator_shim.cc",
- "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc",
- "base/android/android_hardware_buffer_compat.cc",
- "base/android/android_image_reader_compat.cc",
- "base/android/apk_assets.cc",
- "base/android/application_status_listener.cc",
- "base/android/base_feature_list.cc",
- "base/android/base_features.cc",
- "base/android/base_jni_onload.cc",
- "base/android/build_info.cc",
- "base/android/bundle_utils.cc",
- "base/android/callback_android.cc",
- "base/android/child_process_service.cc",
- "base/android/command_line_android.cc",
- "base/android/content_uri_utils.cc",
- "base/android/cpu_features.cc",
- "base/android/early_trace_event_binding.cc",
- "base/android/event_log.cc",
- "base/android/feature_list_jni.cc",
- "base/android/features_jni.cc",
- "base/android/field_trial_list.cc",
- "base/android/important_file_writer_android.cc",
- "base/android/int_string_callback.cc",
- "base/android/jank_metric_uma_recorder.cc",
- "base/android/java_exception_reporter.cc",
- "base/android/java_handler_thread.cc",
- "base/android/java_heap_dump_generator.cc",
- "base/android/java_runtime.cc",
- "base/android/jni_android.cc",
- "base/android/jni_array.cc",
- "base/android/jni_registrar.cc",
- "base/android/jni_string.cc",
- "base/android/jni_utils.cc",
- "base/android/jni_weak_ref.cc",
- "base/android/library_loader/anchor_functions.cc",
- "base/android/library_loader/library_loader_hooks.cc",
- "base/android/library_loader/library_prefetcher.cc",
- "base/android/library_loader/library_prefetcher_hooks.cc",
- "base/android/locale_utils.cc",
- "base/android/memory_pressure_listener_android.cc",
- "base/android/native_uma_recorder.cc",
- "base/android/path_service_android.cc",
- "base/android/path_utils.cc",
- "base/android/radio_utils.cc",
- "base/android/reached_addresses_bitset.cc",
- "base/android/remove_stale_data.cc",
- "base/android/scoped_hardware_buffer_fence_sync.cc",
- "base/android/scoped_hardware_buffer_handle.cc",
- "base/android/scoped_java_ref.cc",
- "base/android/statistics_recorder_android.cc",
- "base/android/sys_utils.cc",
- "base/android/task_scheduler/post_task_android.cc",
- "base/android/task_scheduler/task_runner_android.cc",
- "base/android/thread_instruction_count.cc",
- "base/android/timezone_utils.cc",
- "base/android/trace_event_binding.cc",
- "base/android/unguessable_token_android.cc",
- "base/at_exit.cc",
- "base/barrier_closure.cc",
- "base/base64.cc",
- "base/base64url.cc",
- "base/base_paths.cc",
- "base/base_paths_android.cc",
- "base/big_endian.cc",
- "base/build_time.cc",
- "base/callback_list.cc",
- "base/check.cc",
- "base/check_is_test.cc",
- "base/check_op.cc",
- "base/command_line.cc",
- "base/containers/flat_tree.cc",
- "base/containers/intrusive_heap.cc",
- "base/containers/linked_list.cc",
- "base/cpu.cc",
- "base/cpu_reduction_experiment.cc",
- "base/debug/activity_analyzer.cc",
- "base/debug/activity_tracker.cc",
- "base/debug/alias.cc",
- "base/debug/asan_invalid_access.cc",
- "base/debug/buffered_dwarf_reader.cc",
- "base/debug/crash_logging.cc",
- "base/debug/debugger.cc",
- "base/debug/debugger_posix.cc",
- "base/debug/dump_without_crashing.cc",
- "base/debug/dwarf_line_no.cc",
- "base/debug/elf_reader.cc",
- "base/debug/proc_maps_linux.cc",
- "base/debug/profiler.cc",
- "base/debug/stack_trace.cc",
- "base/debug/stack_trace_android.cc",
- "base/debug/task_trace.cc",
- "base/environment.cc",
- "base/feature_list.cc",
- "base/features.cc",
- "base/file_descriptor_posix.cc",
- "base/file_descriptor_store.cc",
- "base/files/file.cc",
- "base/files/file_descriptor_watcher_posix.cc",
- "base/files/file_enumerator.cc",
- "base/files/file_enumerator_posix.cc",
- "base/files/file_path.cc",
- "base/files/file_path_watcher.cc",
- "base/files/file_path_watcher_inotify.cc",
- "base/files/file_posix.cc",
- "base/files/file_proxy.cc",
- "base/files/file_tracing.cc",
- "base/files/file_util.cc",
- "base/files/file_util_android.cc",
- "base/files/file_util_posix.cc",
- "base/files/important_file_writer.cc",
- "base/files/important_file_writer_cleaner.cc",
- "base/files/memory_mapped_file.cc",
- "base/files/memory_mapped_file_posix.cc",
- "base/files/safe_base_name.cc",
- "base/files/scoped_file.cc",
- "base/files/scoped_file_android.cc",
- "base/files/scoped_temp_dir.cc",
- "base/functional/callback_helpers.cc",
- "base/functional/callback_internal.cc",
- "base/guid.cc",
- "base/hash/hash.cc",
- "base/hash/legacy_hash.cc",
- "base/hash/md5_boringssl.cc",
- "base/hash/sha1_boringssl.cc",
- "base/json/json_file_value_serializer.cc",
- "base/json/json_parser.cc",
- "base/json/json_reader.cc",
- "base/json/json_string_value_serializer.cc",
- "base/json/json_value_converter.cc",
- "base/json/json_writer.cc",
- "base/json/string_escape.cc",
- "base/json/values_util.cc",
- "base/lazy_instance_helpers.cc",
- "base/linux_util.cc",
- "base/location.cc",
- "base/logging.cc",
- "base/memory/aligned_memory.cc",
- "base/memory/discardable_memory.cc",
- "base/memory/discardable_memory_allocator.cc",
- "base/memory/discardable_shared_memory.cc",
- "base/memory/madv_free_discardable_memory_allocator_posix.cc",
- "base/memory/madv_free_discardable_memory_posix.cc",
- "base/memory/memory_pressure_listener.cc",
- "base/memory/memory_pressure_monitor.cc",
- "base/memory/nonscannable_memory.cc",
- "base/memory/page_size_posix.cc",
- "base/memory/platform_shared_memory_handle.cc",
- "base/memory/platform_shared_memory_mapper_android.cc",
- "base/memory/platform_shared_memory_region.cc",
- "base/memory/platform_shared_memory_region_android.cc",
- "base/memory/raw_ptr.cc",
- "base/memory/raw_ptr_asan_bound_arg_tracker.cc",
- "base/memory/raw_ptr_asan_service.cc",
- "base/memory/read_only_shared_memory_region.cc",
- "base/memory/ref_counted.cc",
- "base/memory/ref_counted_memory.cc",
- "base/memory/shared_memory_mapper.cc",
- "base/memory/shared_memory_mapping.cc",
- "base/memory/shared_memory_security_policy.cc",
- "base/memory/shared_memory_tracker.cc",
- "base/memory/unsafe_shared_memory_pool.cc",
- "base/memory/unsafe_shared_memory_region.cc",
- "base/memory/weak_ptr.cc",
- "base/memory/writable_shared_memory_region.cc",
- "base/message_loop/message_pump.cc",
- "base/message_loop/message_pump_android.cc",
- "base/message_loop/message_pump_default.cc",
- "base/message_loop/message_pump_epoll.cc",
- "base/message_loop/message_pump_libevent.cc",
- "base/message_loop/watchable_io_message_pump_posix.cc",
- "base/message_loop/work_id_provider.cc",
- "base/metrics/bucket_ranges.cc",
- "base/metrics/crc32.cc",
- "base/metrics/dummy_histogram.cc",
- "base/metrics/field_trial.cc",
- "base/metrics/field_trial_param_associator.cc",
- "base/metrics/field_trial_params.cc",
- "base/metrics/histogram.cc",
- "base/metrics/histogram_base.cc",
- "base/metrics/histogram_delta_serialization.cc",
- "base/metrics/histogram_functions.cc",
- "base/metrics/histogram_samples.cc",
- "base/metrics/histogram_snapshot_manager.cc",
- "base/metrics/metrics_hashes.cc",
- "base/metrics/persistent_histogram_allocator.cc",
- "base/metrics/persistent_histogram_storage.cc",
- "base/metrics/persistent_memory_allocator.cc",
- "base/metrics/persistent_sample_map.cc",
- "base/metrics/ranges_manager.cc",
- "base/metrics/sample_map.cc",
- "base/metrics/sample_vector.cc",
- "base/metrics/single_sample_metrics.cc",
- "base/metrics/sparse_histogram.cc",
- "base/metrics/statistics_recorder.cc",
- "base/metrics/user_metrics.cc",
- "base/native_library.cc",
- "base/native_library_posix.cc",
- "base/observer_list_internal.cc",
- "base/observer_list_threadsafe.cc",
- "base/observer_list_types.cc",
- "base/one_shot_event.cc",
- "base/os_compat_android.cc",
- "base/path_service.cc",
- "base/pending_task.cc",
- "base/pickle.cc",
- "base/posix/can_lower_nice_to.cc",
- "base/posix/file_descriptor_shuffle.cc",
- "base/posix/global_descriptors.cc",
- "base/posix/safe_strerror.cc",
- "base/posix/unix_domain_socket.cc",
- "base/power_monitor/battery_level_provider.cc",
- "base/power_monitor/battery_state_sampler.cc",
- "base/power_monitor/moving_average.cc",
- "base/power_monitor/power_monitor.cc",
- "base/power_monitor/power_monitor_device_source.cc",
- "base/power_monitor/power_monitor_device_source_android.cc",
- "base/power_monitor/power_monitor_features.cc",
- "base/power_monitor/power_monitor_source.cc",
- "base/power_monitor/sampling_event_source.cc",
- "base/power_monitor/timer_sampling_event_source.cc",
- "base/process/environment_internal.cc",
- "base/process/internal_linux.cc",
- "base/process/kill.cc",
- "base/process/kill_posix.cc",
- "base/process/launch.cc",
- "base/process/launch_posix.cc",
- "base/process/memory.cc",
- "base/process/memory_linux.cc",
- "base/process/process_android.cc",
- "base/process/process_handle.cc",
- "base/process/process_handle_linux.cc",
- "base/process/process_handle_posix.cc",
- "base/process/process_iterator.cc",
- "base/process/process_iterator_linux.cc",
- "base/process/process_metrics.cc",
- "base/process/process_metrics_linux.cc",
- "base/process/process_metrics_posix.cc",
- "base/process/process_posix.cc",
- "base/profiler/arm_cfi_table.cc",
- "base/profiler/frame.cc",
- "base/profiler/metadata_recorder.cc",
- "base/profiler/module_cache.cc",
- "base/profiler/module_cache_posix.cc",
- "base/profiler/sample_metadata.cc",
- "base/profiler/sampling_profiler_thread_token.cc",
- "base/profiler/stack_base_address_posix.cc",
- "base/profiler/stack_buffer.cc",
- "base/profiler/stack_copier.cc",
- "base/profiler/stack_copier_signal.cc",
- "base/profiler/stack_copier_suspend.cc",
- "base/profiler/stack_sampler.cc",
- "base/profiler/stack_sampler_android.cc",
- "base/profiler/stack_sampler_impl.cc",
- "base/profiler/stack_sampling_profiler.cc",
- "base/profiler/thread_delegate_posix.cc",
- "base/profiler/unwinder.cc",
- "base/rand_util.cc",
- "base/rand_util_posix.cc",
- "base/run_loop.cc",
- "base/sampling_heap_profiler/lock_free_address_hash_set.cc",
- "base/sampling_heap_profiler/poisson_allocation_sampler.cc",
- "base/sampling_heap_profiler/sampling_heap_profiler.cc",
- "base/scoped_add_feature_flags.cc",
- "base/scoped_environment_variable_override.cc",
- "base/scoped_native_library.cc",
- "base/sequence_checker.cc",
- "base/sequence_checker_impl.cc",
- "base/sequence_token.cc",
- "base/strings/abseil_string_conversions.cc",
- "base/strings/abseil_string_number_conversions.cc",
- "base/strings/escape.cc",
- "base/strings/latin1_string_conversions.cc",
- "base/strings/pattern.cc",
- "base/strings/safe_sprintf.cc",
- "base/strings/strcat.cc",
- "base/strings/string_number_conversions.cc",
- "base/strings/string_piece.cc",
- "base/strings/string_split.cc",
- "base/strings/string_util.cc",
- "base/strings/string_util_constants.cc",
- "base/strings/stringprintf.cc",
- "base/strings/sys_string_conversions_posix.cc",
- "base/strings/utf_offset_string_conversions.cc",
- "base/strings/utf_string_conversion_utils.cc",
- "base/strings/utf_string_conversions.cc",
- "base/substring_set_matcher/matcher_string_pattern.cc",
- "base/substring_set_matcher/substring_set_matcher.cc",
- "base/supports_user_data.cc",
- "base/sync_socket.cc",
- "base/sync_socket_posix.cc",
- "base/synchronization/atomic_flag.cc",
- "base/synchronization/condition_variable_posix.cc",
- "base/synchronization/lock.cc",
- "base/synchronization/lock_impl_posix.cc",
- "base/synchronization/waitable_event_posix.cc",
- "base/synchronization/waitable_event_watcher_posix.cc",
- "base/syslog_logging.cc",
- "base/system/sys_info.cc",
- "base/system/sys_info_android.cc",
- "base/system/sys_info_linux.cc",
- "base/system/sys_info_posix.cc",
- "base/system/system_monitor.cc",
- "base/task/cancelable_task_tracker.cc",
- "base/task/common/checked_lock_impl.cc",
- "base/task/common/lazy_now.cc",
- "base/task/common/operations_controller.cc",
- "base/task/common/scoped_defer_task_posting.cc",
- "base/task/common/task_annotator.cc",
- "base/task/current_thread.cc",
- "base/task/default_delayed_task_handle_delegate.cc",
- "base/task/deferred_sequenced_task_runner.cc",
- "base/task/delayed_task_handle.cc",
- "base/task/lazy_thread_pool_task_runner.cc",
- "base/task/post_job.cc",
- "base/task/scoped_set_task_priority_for_current_thread.cc",
- "base/task/sequence_manager/associated_thread_id.cc",
- "base/task/sequence_manager/atomic_flag_set.cc",
- "base/task/sequence_manager/delayed_task_handle_delegate.cc",
- "base/task/sequence_manager/enqueue_order_generator.cc",
- "base/task/sequence_manager/fence.cc",
- "base/task/sequence_manager/hierarchical_timing_wheel.cc",
- "base/task/sequence_manager/sequence_manager.cc",
- "base/task/sequence_manager/sequence_manager_impl.cc",
- "base/task/sequence_manager/sequenced_task_source.cc",
- "base/task/sequence_manager/task_order.cc",
- "base/task/sequence_manager/task_queue.cc",
- "base/task/sequence_manager/task_queue_impl.cc",
- "base/task/sequence_manager/task_queue_selector.cc",
- "base/task/sequence_manager/tasks.cc",
- "base/task/sequence_manager/thread_controller.cc",
- "base/task/sequence_manager/thread_controller_impl.cc",
- "base/task/sequence_manager/thread_controller_power_monitor.cc",
- "base/task/sequence_manager/thread_controller_with_message_pump_impl.cc",
- "base/task/sequence_manager/time_domain.cc",
- "base/task/sequence_manager/timing_wheel.cc",
- "base/task/sequence_manager/wake_up_queue.cc",
- "base/task/sequence_manager/work_deduplicator.cc",
- "base/task/sequence_manager/work_queue.cc",
- "base/task/sequence_manager/work_queue_sets.cc",
- "base/task/sequenced_task_runner.cc",
- "base/task/simple_task_executor.cc",
- "base/task/single_thread_task_executor.cc",
- "base/task/single_thread_task_runner.cc",
- "base/task/task_executor.cc",
- "base/task/task_features.cc",
- "base/task/task_runner.cc",
- "base/task/task_traits.cc",
- "base/task/thread_pool.cc",
- "base/task/thread_pool/delayed_priority_queue.cc",
- "base/task/thread_pool/delayed_task_manager.cc",
- "base/task/thread_pool/environment_config.cc",
- "base/task/thread_pool/initialization_util.cc",
- "base/task/thread_pool/job_task_source.cc",
- "base/task/thread_pool/pooled_parallel_task_runner.cc",
- "base/task/thread_pool/pooled_sequenced_task_runner.cc",
- "base/task/thread_pool/pooled_single_thread_task_runner_manager.cc",
- "base/task/thread_pool/pooled_task_runner_delegate.cc",
- "base/task/thread_pool/priority_queue.cc",
- "base/task/thread_pool/sequence.cc",
- "base/task/thread_pool/service_thread.cc",
- "base/task/thread_pool/task.cc",
- "base/task/thread_pool/task_source.cc",
- "base/task/thread_pool/task_source_sort_key.cc",
- "base/task/thread_pool/task_tracker.cc",
- "base/task/thread_pool/thread_group.cc",
- "base/task/thread_pool/thread_group_impl.cc",
- "base/task/thread_pool/thread_group_native.cc",
- "base/task/thread_pool/thread_pool_impl.cc",
- "base/task/thread_pool/thread_pool_instance.cc",
- "base/task/thread_pool/worker_thread.cc",
- "base/task/thread_pool/worker_thread_stack.cc",
- "base/third_party/cityhash/city.cc",
- "base/third_party/cityhash_v103/src/city_v103.cc",
- "base/third_party/nspr/prtime.cc",
- "base/third_party/superfasthash/superfasthash.c",
- "base/threading/hang_watcher.cc",
- "base/threading/platform_thread.cc",
- "base/threading/platform_thread_android.cc",
- "base/threading/platform_thread_internal_posix.cc",
- "base/threading/platform_thread_posix.cc",
- "base/threading/platform_thread_ref.cc",
- "base/threading/post_task_and_reply_impl.cc",
- "base/threading/scoped_blocking_call.cc",
- "base/threading/scoped_blocking_call_internal.cc",
- "base/threading/scoped_thread_priority.cc",
- "base/threading/sequence_local_storage_map.cc",
- "base/threading/sequence_local_storage_slot.cc",
- "base/threading/sequenced_task_runner_handle.cc",
- "base/threading/simple_thread.cc",
- "base/threading/thread.cc",
- "base/threading/thread_checker.cc",
- "base/threading/thread_checker_impl.cc",
- "base/threading/thread_collision_warner.cc",
- "base/threading/thread_id_name_manager.cc",
- "base/threading/thread_local_storage.cc",
- "base/threading/thread_local_storage_posix.cc",
- "base/threading/thread_restrictions.cc",
- "base/threading/thread_task_runner_handle.cc",
- "base/threading/watchdog.cc",
- "base/time/clock.cc",
- "base/time/default_clock.cc",
- "base/time/default_tick_clock.cc",
- "base/time/tick_clock.cc",
- "base/time/time.cc",
- "base/time/time_android.cc",
- "base/time/time_conversion_posix.cc",
- "base/time/time_delta_from_string.cc",
- "base/time/time_exploded_icu.cc",
- "base/time/time_exploded_posix.cc",
- "base/time/time_now_posix.cc",
- "base/time/time_override.cc",
- "base/time/time_to_iso8601.cc",
- "base/timer/elapsed_timer.cc",
- "base/timer/hi_res_timer_manager_posix.cc",
- "base/timer/lap_timer.cc",
- "base/timer/timer.cc",
- "base/timer/wall_clock_timer.cc",
- "base/token.cc",
- "base/trace_event/heap_profiler_allocation_context.cc",
- "base/trace_event/heap_profiler_allocation_context_tracker.cc",
- "base/trace_event/memory_allocator_dump_guid.cc",
- "base/trace_event/trace_event_stub.cc",
- "base/trace_event/trace_id_helper.cc",
- "base/unguessable_token.cc",
- "base/value_iterators.cc",
- "base/values.cc",
- "base/version.cc",
- "base/vlog.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- ],
- generated_headers: [
- "cronet_aml_base_allocator_buildflags",
- "cronet_aml_base_anchor_functions_buildflags",
- "cronet_aml_base_android_runtime_jni_headers",
- "cronet_aml_base_base_jni_headers",
- "cronet_aml_base_build_date",
- "cronet_aml_base_cfi_buildflags",
- "cronet_aml_base_clang_profiling_buildflags",
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_feature_list_buildflags",
- "cronet_aml_base_ios_cronet_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_base_message_pump_buildflags",
- "cronet_aml_base_orderfile_buildflags",
- "cronet_aml_base_parsing_buildflags",
- "cronet_aml_base_power_monitor_buildflags",
- "cronet_aml_base_profiler_buildflags",
- "cronet_aml_base_sanitizer_buildflags",
- "cronet_aml_base_synchronization_buildflags",
- "cronet_aml_base_tracing_buildflags",
- "cronet_aml_build_branding_buildflags",
- "cronet_aml_build_chromecast_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_build_config_compiler_compiler_buildflags",
- ],
- export_generated_headers: [
- "cronet_aml_base_allocator_buildflags",
- "cronet_aml_base_anchor_functions_buildflags",
- "cronet_aml_base_android_runtime_jni_headers",
- "cronet_aml_base_base_jni_headers",
- "cronet_aml_base_build_date",
- "cronet_aml_base_cfi_buildflags",
- "cronet_aml_base_clang_profiling_buildflags",
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_feature_list_buildflags",
- "cronet_aml_base_ios_cronet_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_base_message_pump_buildflags",
- "cronet_aml_base_orderfile_buildflags",
- "cronet_aml_base_parsing_buildflags",
- "cronet_aml_base_power_monitor_buildflags",
- "cronet_aml_base_profiler_buildflags",
- "cronet_aml_base_sanitizer_buildflags",
- "cronet_aml_base_synchronization_buildflags",
- "cronet_aml_base_tracing_buildflags",
- "cronet_aml_build_branding_buildflags",
- "cronet_aml_build_chromecast_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_build_config_compiler_compiler_buildflags",
- ],
- export_header_lib_headers: [
- "libgtest_prod_headers",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DBASE_IMPLEMENTATION",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-DUSE_CHROMIUM_ICU=1",
- "-DU_ENABLE_DYLOAD=0",
- "-DU_ENABLE_RESOURCE_TRACING=0",
- "-DU_ENABLE_TRACING=1",
- "-DU_STATIC_IMPLEMENTATION",
- "-DU_USING_ICU_NAMESPACE=0",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/android_ndk/sources/android/cpufeatures/",
- "third_party/boringssl/src/include/",
- "third_party/icu/source/common/",
- "third_party/icu/source/i18n/",
- ],
- header_libs: [
- "libgtest_prod_headers",
- ],
- cpp_std: "c++17",
- target: {
- android_arm: {
- srcs: [
- "base/android/reached_code_profiler.cc",
- "base/profiler/chrome_unwind_info_android.cc",
- "base/profiler/chrome_unwinder_android.cc",
- "base/profiler/chrome_unwinder_android_v2.cc",
- "base/trace_event/cfi_backtrace_android.cc",
- ],
- },
- android_arm64: {
- srcs: [
- "base/android/reached_code_profiler.cc",
- ],
- },
- android_x86: {
- srcs: [
- "base/android/reached_code_profiler_stub.cc",
- ],
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- srcs: [
- "base/android/reached_code_profiler_stub.cc",
- ],
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //base:base_android_java_enums_srcjar
-java_genrule {
- name: "cronet_aml_base_base_android_java_enums_srcjar",
- cmd: "$(location build/android/gyp/java_cpp_enum.py) --srcjar " +
- "$(out) " +
- "$(location base/android/application_status_listener.h) " +
- "$(location base/android/child_process_binding_types.h) " +
- "$(location base/android/library_loader/library_loader_hooks.h) " +
- "$(location base/android/linker/modern_linker_jni.h) " +
- "$(location base/android/task_scheduler/task_runner_android.h) " +
- "$(location base/memory/memory_pressure_listener.h) " +
- "$(location base/metrics/histogram_base.h) " +
- "$(location base/task/task_traits.h)",
- out: [
- "base/base_android_java_enums_srcjar.srcjar",
- ],
- tool_files: [
- "base/android/application_status_listener.h",
- "base/android/child_process_binding_types.h",
- "base/android/library_loader/library_loader_hooks.h",
- "base/android/linker/modern_linker_jni.h",
- "base/android/task_scheduler/task_runner_android.h",
- "base/memory/memory_pressure_listener.h",
- "base/metrics/histogram_base.h",
- "base/task/task_traits.h",
- "build/android/gyp/java_cpp_enum.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- ],
-}
-
-// GN: //base:base_jni_headers
-cc_genrule {
- name: "cronet_aml_base_base_jni_headers",
- srcs: [
- "base/android/java/src/org/chromium/base/ApkAssets.java",
- "base/android/java/src/org/chromium/base/ApplicationStatus.java",
- "base/android/java/src/org/chromium/base/BaseFeatureList.java",
- "base/android/java/src/org/chromium/base/BuildInfo.java",
- "base/android/java/src/org/chromium/base/BundleUtils.java",
- "base/android/java/src/org/chromium/base/Callback.java",
- "base/android/java/src/org/chromium/base/CommandLine.java",
- "base/android/java/src/org/chromium/base/ContentUriUtils.java",
- "base/android/java/src/org/chromium/base/CpuFeatures.java",
- "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
- "base/android/java/src/org/chromium/base/EventLog.java",
- "base/android/java/src/org/chromium/base/FeatureList.java",
- "base/android/java/src/org/chromium/base/Features.java",
- "base/android/java/src/org/chromium/base/FieldTrialList.java",
- "base/android/java/src/org/chromium/base/FileUtils.java",
- "base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
- "base/android/java/src/org/chromium/base/IntStringCallback.java",
- "base/android/java/src/org/chromium/base/JNIUtils.java",
- "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
- "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
- "base/android/java/src/org/chromium/base/LocaleUtils.java",
- "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
- "base/android/java/src/org/chromium/base/PathService.java",
- "base/android/java/src/org/chromium/base/PathUtils.java",
- "base/android/java/src/org/chromium/base/PiiElider.java",
- "base/android/java/src/org/chromium/base/PowerMonitor.java",
- "base/android/java/src/org/chromium/base/RadioUtils.java",
- "base/android/java/src/org/chromium/base/SysUtils.java",
- "base/android/java/src/org/chromium/base/ThreadUtils.java",
- "base/android/java/src/org/chromium/base/TimezoneUtils.java",
- "base/android/java/src/org/chromium/base/TraceEvent.java",
- "base/android/java/src/org/chromium/base/UnguessableToken.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
- "base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
- "base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java",
- "base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
- "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
- "base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java",
- "base/android/java/src/org/chromium/base/task/PostTask.java",
- "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
- ],
- cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
- "long " +
- "--output_dir " +
- "$(genDir)/base/base_jni_headers " +
- "--includes " +
- "base/android/jni_generator/jni_generator_helper.h " +
- "--use_proxy_hash " +
- "--output_name " +
- "ApkAssets_jni.h " +
- "--output_name " +
- "ApplicationStatus_jni.h " +
- "--output_name " +
- "BaseFeatureList_jni.h " +
- "--output_name " +
- "BuildInfo_jni.h " +
- "--output_name " +
- "BundleUtils_jni.h " +
- "--output_name " +
- "Callback_jni.h " +
- "--output_name " +
- "CommandLine_jni.h " +
- "--output_name " +
- "ContentUriUtils_jni.h " +
- "--output_name " +
- "CpuFeatures_jni.h " +
- "--output_name " +
- "EarlyTraceEvent_jni.h " +
- "--output_name " +
- "EventLog_jni.h " +
- "--output_name " +
- "FeatureList_jni.h " +
- "--output_name " +
- "Features_jni.h " +
- "--output_name " +
- "FieldTrialList_jni.h " +
- "--output_name " +
- "FileUtils_jni.h " +
- "--output_name " +
- "ImportantFileWriterAndroid_jni.h " +
- "--output_name " +
- "IntStringCallback_jni.h " +
- "--output_name " +
- "JNIUtils_jni.h " +
- "--output_name " +
- "JavaExceptionReporter_jni.h " +
- "--output_name " +
- "JavaHandlerThread_jni.h " +
- "--output_name " +
- "LocaleUtils_jni.h " +
- "--output_name " +
- "MemoryPressureListener_jni.h " +
- "--output_name " +
- "PathService_jni.h " +
- "--output_name " +
- "PathUtils_jni.h " +
- "--output_name " +
- "PiiElider_jni.h " +
- "--output_name " +
- "PowerMonitor_jni.h " +
- "--output_name " +
- "RadioUtils_jni.h " +
- "--output_name " +
- "SysUtils_jni.h " +
- "--output_name " +
- "ThreadUtils_jni.h " +
- "--output_name " +
- "TimezoneUtils_jni.h " +
- "--output_name " +
- "TraceEvent_jni.h " +
- "--output_name " +
- "UnguessableToken_jni.h " +
- "--output_name " +
- "JankMetricUMARecorder_jni.h " +
- "--output_name " +
- "LibraryLoader_jni.h " +
- "--output_name " +
- "LibraryPrefetcher_jni.h " +
- "--output_name " +
- "JavaHeapDumpGenerator_jni.h " +
- "--output_name " +
- "NativeUmaRecorder_jni.h " +
- "--output_name " +
- "StatisticsRecorderAndroid_jni.h " +
- "--output_name " +
- "ChildProcessService_jni.h " +
- "--output_name " +
- "PostTask_jni.h " +
- "--output_name " +
- "TaskRunnerImpl_jni.h " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/ApkAssets.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/ApplicationStatus.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/BaseFeatureList.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/BuildInfo.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/BundleUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/Callback.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/CommandLine.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/ContentUriUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/CpuFeatures.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/EarlyTraceEvent.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/EventLog.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/FeatureList.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/Features.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/FieldTrialList.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/FileUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/IntStringCallback.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/JNIUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/JavaExceptionReporter.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/JavaHandlerThread.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/LocaleUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/MemoryPressureListener.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/PathService.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/PathUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/PiiElider.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/PowerMonitor.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/RadioUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/SysUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/ThreadUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/TimezoneUtils.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/TraceEvent.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/UnguessableToken.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/task/PostTask.java) " +
- "--input_file " +
- "$(location base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java) " +
- "--package_prefix " +
- "android.net.http.internal",
- out: [
- "base/base_jni_headers/ApkAssets_jni.h",
- "base/base_jni_headers/ApplicationStatus_jni.h",
- "base/base_jni_headers/BaseFeatureList_jni.h",
- "base/base_jni_headers/BuildInfo_jni.h",
- "base/base_jni_headers/BundleUtils_jni.h",
- "base/base_jni_headers/Callback_jni.h",
- "base/base_jni_headers/ChildProcessService_jni.h",
- "base/base_jni_headers/CommandLine_jni.h",
- "base/base_jni_headers/ContentUriUtils_jni.h",
- "base/base_jni_headers/CpuFeatures_jni.h",
- "base/base_jni_headers/EarlyTraceEvent_jni.h",
- "base/base_jni_headers/EventLog_jni.h",
- "base/base_jni_headers/FeatureList_jni.h",
- "base/base_jni_headers/Features_jni.h",
- "base/base_jni_headers/FieldTrialList_jni.h",
- "base/base_jni_headers/FileUtils_jni.h",
- "base/base_jni_headers/ImportantFileWriterAndroid_jni.h",
- "base/base_jni_headers/IntStringCallback_jni.h",
- "base/base_jni_headers/JNIUtils_jni.h",
- "base/base_jni_headers/JankMetricUMARecorder_jni.h",
- "base/base_jni_headers/JavaExceptionReporter_jni.h",
- "base/base_jni_headers/JavaHandlerThread_jni.h",
- "base/base_jni_headers/JavaHeapDumpGenerator_jni.h",
- "base/base_jni_headers/LibraryLoader_jni.h",
- "base/base_jni_headers/LibraryPrefetcher_jni.h",
- "base/base_jni_headers/LocaleUtils_jni.h",
- "base/base_jni_headers/MemoryPressureListener_jni.h",
- "base/base_jni_headers/NativeUmaRecorder_jni.h",
- "base/base_jni_headers/PathService_jni.h",
- "base/base_jni_headers/PathUtils_jni.h",
- "base/base_jni_headers/PiiElider_jni.h",
- "base/base_jni_headers/PostTask_jni.h",
- "base/base_jni_headers/PowerMonitor_jni.h",
- "base/base_jni_headers/RadioUtils_jni.h",
- "base/base_jni_headers/StatisticsRecorderAndroid_jni.h",
- "base/base_jni_headers/SysUtils_jni.h",
- "base/base_jni_headers/TaskRunnerImpl_jni.h",
- "base/base_jni_headers/ThreadUtils_jni.h",
- "base/base_jni_headers/TimezoneUtils_jni.h",
- "base/base_jni_headers/TraceEvent_jni.h",
- "base/base_jni_headers/UnguessableToken_jni.h",
- ],
- tool_files: [
- "base/android/jni_generator/android_jar.classes",
- "base/android/jni_generator/jni_generator.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/gn_helpers.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:base_static
-cc_library_static {
- name: "cronet_aml_base_base_static",
- srcs: [
- "base/base_switches.cc",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- export_generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //base:build_date
-cc_genrule {
- name: "cronet_aml_base_build_date",
- cmd: "$(location build/write_build_date_header.py) $(out) " +
- "1674804594",
- out: [
- "base/generated_build_date.h",
- ],
- tool_files: [
- "build/write_build_date_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:cfi_buildflags
-cc_genrule {
- name: "cronet_aml_base_cfi_buildflags",
- cmd: "echo '--flags CFI_CAST_CHECK=\"false && false\" CFI_ICALL_CHECK=\"false && false\" CFI_ENFORCEMENT_TRAP=\"false && !false\" CFI_ENFORCEMENT_DIAGNOSTIC=\"false && false && !false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:cfi_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/cfi_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:clang_profiling_buildflags
-cc_genrule {
- name: "cronet_aml_base_clang_profiling_buildflags",
- cmd: "echo '--flags CLANG_PROFILING=\"false\" CLANG_PROFILING_INSIDE_SANDBOX=\"false\" USE_CLANG_COVERAGE=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:clang_profiling_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/clang_profiling_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:debugging_buildflags
-cc_genrule {
- name: "cronet_aml_base_debugging_buildflags",
- cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" FROM_HERE_USES_LOCATION_BUILTINS=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"false\" UNSAFE_DEVELOPER_BUILD=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:debugging_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi; " +
- "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" FROM_HERE_USES_LOCATION_BUILTINS=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"true\" UNSAFE_DEVELOPER_BUILD=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:debugging_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi; " +
- "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" FROM_HERE_USES_LOCATION_BUILTINS=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"false\" UNSAFE_DEVELOPER_BUILD=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"true\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:debugging_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi; " +
- "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags DCHECK_IS_CONFIGURABLE=\"false\" ENABLE_LOCATION_SOURCE=\"true\" FROM_HERE_USES_LOCATION_BUILTINS=\"true\" ENABLE_PROFILING=\"false\" CAN_UNWIND_WITH_FRAME_POINTERS=\"true\" UNSAFE_DEVELOPER_BUILD=\"false\" CAN_UNWIND_WITH_CFI_TABLE=\"false\" EXCLUDE_UNWIND_TABLES=\"false\" ENABLE_GDBINIT_WARNING=\"false\" ENABLE_LLDBINIT_WARNING=\"false\" EXPENSIVE_DCHECKS_ARE_ON=\"false\" ENABLE_STACK_TRACE_LINE_NUMBERS=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:debugging_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi;",
- out: [
- "base/debug/debugging_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:feature_list_buildflags
-cc_genrule {
- name: "cronet_aml_base_feature_list_buildflags",
- cmd: "echo '--flags ENABLE_BANNED_BASE_FEATURE_PREFIX=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:feature_list_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/feature_list_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:ios_cronet_buildflags
-cc_genrule {
- name: "cronet_aml_base_ios_cronet_buildflags",
- cmd: "echo '--flags CRONET_BUILD=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:ios_cronet_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/message_loop/ios_cronet_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:java_features_srcjar
-java_genrule {
- name: "cronet_aml_base_java_features_srcjar",
- srcs: [
- "base/android/base_features.cc",
- "base/features.cc",
- "base/task/task_features.cc",
- ],
- cmd: "$(location build/android/gyp/java_cpp_features.py) --srcjar " +
- "$(out) " +
- "--template " +
- "$(location base/android/java/src/org/chromium/base/BaseFeatures.java.tmpl) " +
- "$(location base/android/base_features.cc) " +
- "$(location base/features.cc) " +
- "$(location base/task/task_features.cc)",
- out: [
- "base/java_features_srcjar.srcjar",
- ],
- tool_files: [
- "base/android/java/src/org/chromium/base/BaseFeatures.java.tmpl",
- "build/android/gyp/java_cpp_features.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- ],
-}
-
-// GN: //base:java_switches_srcjar
-java_genrule {
- name: "cronet_aml_base_java_switches_srcjar",
- srcs: [
- "base/base_switches.cc",
- ],
- cmd: "$(location build/android/gyp/java_cpp_strings.py) --srcjar " +
- "$(out) " +
- "--template " +
- "$(location base/android/java/src/org/chromium/base/BaseSwitches.java.tmpl) " +
- "$(location base/base_switches.cc)",
- out: [
- "base/java_switches_srcjar.srcjar",
- ],
- tool_files: [
- "base/android/java/src/org/chromium/base/BaseSwitches.java.tmpl",
- "build/android/gyp/java_cpp_strings.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- ],
-}
-
-// GN: //base:logging_buildflags
-cc_genrule {
- name: "cronet_aml_base_logging_buildflags",
- cmd: "echo '--flags ENABLE_LOG_ERROR_NOT_REACHED=\"false\" USE_RUNTIME_VLOG=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:logging_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/logging_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:message_pump_buildflags
-cc_genrule {
- name: "cronet_aml_base_message_pump_buildflags",
- cmd: "echo '--flags ENABLE_MESSAGE_PUMP_EPOLL=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:message_pump_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/message_loop/message_pump_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:nodebug_assertion
-cc_object {
- name: "cronet_aml_base_nodebug_assertion",
- srcs: [
- "base/nodebug_assertion.cc",
- ],
- static_libs: [
- "cronet_aml_base_base_static",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DBASE_IMPLEMENTATION",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //base:orderfile_buildflags
-cc_genrule {
- name: "cronet_aml_base_orderfile_buildflags",
- cmd: "echo '--flags DEVTOOLS_INSTRUMENTATION_DUMPING=\"false\" ORDERFILE_INSTRUMENTATION=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:orderfile_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/android/orderfile/orderfile_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:parsing_buildflags
-cc_genrule {
- name: "cronet_aml_base_parsing_buildflags",
- cmd: "echo '--flags BUILD_RUST_JSON_PARSER=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:parsing_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/parsing_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:power_monitor_buildflags
-cc_genrule {
- name: "cronet_aml_base_power_monitor_buildflags",
- cmd: "echo '--flags HAS_BATTERY_LEVEL_PROVIDER_IMPL=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:power_monitor_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/power_monitor/power_monitor_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:profiler_buildflags
-cc_genrule {
- name: "cronet_aml_base_profiler_buildflags",
- cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags ENABLE_ARM_CFI_TABLE=\"false\" IOS_STACK_PROFILER_ENABLED=\"true\" USE_ANDROID_UNWINDER_V2=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:profiler_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi; " +
- "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags ENABLE_ARM_CFI_TABLE=\"false\" IOS_STACK_PROFILER_ENABLED=\"true\" USE_ANDROID_UNWINDER_V2=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:profiler_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi; " +
- "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags ENABLE_ARM_CFI_TABLE=\"true\" IOS_STACK_PROFILER_ENABLED=\"true\" USE_ANDROID_UNWINDER_V2=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:profiler_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi; " +
- "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags ENABLE_ARM_CFI_TABLE=\"false\" IOS_STACK_PROFILER_ENABLED=\"true\" USE_ANDROID_UNWINDER_V2=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:profiler_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi;",
- out: [
- "base/profiler/profiler_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:sanitizer_buildflags
-cc_genrule {
- name: "cronet_aml_base_sanitizer_buildflags",
- cmd: "echo '--flags IS_HWASAN=\"false\" USING_SANITIZER=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:sanitizer_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/sanitizer_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base:synchronization_buildflags
-cc_genrule {
- name: "cronet_aml_base_synchronization_buildflags",
- cmd: "echo '--flags ENABLE_MUTEX_PRIORITY_INHERITANCE=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:synchronization_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/synchronization/synchronization_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //base/third_party/double_conversion:double_conversion
-cc_library_static {
- name: "cronet_aml_base_third_party_double_conversion_double_conversion",
- srcs: [
- "base/third_party/double_conversion/double-conversion/bignum-dtoa.cc",
- "base/third_party/double_conversion/double-conversion/bignum.cc",
- "base/third_party/double_conversion/double-conversion/cached-powers.cc",
- "base/third_party/double_conversion/double-conversion/double-to-string.cc",
- "base/third_party/double_conversion/double-conversion/fast-dtoa.cc",
- "base/third_party/double_conversion/double-conversion/fixed-dtoa.cc",
- "base/third_party/double_conversion/double-conversion/string-to-double.cc",
- "base/third_party/double_conversion/double-conversion/strtod.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //base/third_party/dynamic_annotations:dynamic_annotations
-cc_library_static {
- name: "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- srcs: [
- "base/third_party/dynamic_annotations/dynamic_annotations.c",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //base:tracing_buildflags
-cc_genrule {
- name: "cronet_aml_base_tracing_buildflags",
- cmd: "echo '--flags ENABLE_BASE_TRACING=\"false\" USE_PERFETTO_CLIENT_LIBRARY=\"false\" OPTIONAL_TRACE_EVENTS_ENABLED=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//base:tracing_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "base/tracing_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //build/android:build_config_gen
-genrule {
- name: "cronet_aml_build_android_build_config_gen",
- srcs: [
- ":cronet_aml_build_android_build_config_gen_preprocess",
- ],
- tools: [
- "soong_zip",
- ],
- cmd: "cp $(in) $(genDir)/BuildConfig.java && " +
- "$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/BuildConfig.java",
- out: [
- "BuildConfig.srcjar",
- ],
-}
-
-// GN: //build/android:build_config_gen
-cc_object {
- name: "cronet_aml_build_android_build_config_gen_preprocess",
- srcs: [
- ":cronet_aml_build_android_build_config_gen_rename",
- ],
- cflags: [
- "-DANDROID",
- "-E",
- "-P",
- ],
- compile_multilib: "first",
-}
-
-// GN: //build/android:build_config_gen
-genrule {
- name: "cronet_aml_build_android_build_config_gen_rename",
- srcs: [
- "build/android/java/templates/BuildConfig.template",
- ],
- cmd: "cp $(in) $(out)",
- out: [
- "BuildConfig.cc",
- ],
-}
-
-// GN: //build/android:native_libraries_gen
-java_genrule {
- name: "cronet_aml_build_android_native_libraries_gen",
- cmd: "$(location build/android/gyp/write_native_libraries_java.py) --output " +
- "$(out) " +
- "--cpu-family " +
- "CPU_FAMILY_ARM",
- out: [
- "build/android/native_libraries_gen.srcjar",
- ],
- tool_files: [
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/write_native_libraries_java.py",
- "build/gn_helpers.py",
- ],
-}
-
-// GN: //build:branding_buildflags
-cc_genrule {
- name: "cronet_aml_build_branding_buildflags",
- cmd: "echo '--flags CHROMIUM_BRANDING=\"1\" GOOGLE_CHROME_BRANDING=\"0\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//build:branding_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "build/branding_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //build:chromecast_buildflags
-cc_genrule {
- name: "cronet_aml_build_chromecast_buildflags",
- cmd: "echo '--flags IS_CASTOS=\"false\" IS_CAST_ANDROID=\"false\" ENABLE_CAST_RECEIVER=\"false\" IS_CHROMECAST=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//build:chromecast_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "build/chromecast_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //build:chromeos_buildflags
-cc_genrule {
- name: "cronet_aml_build_chromeos_buildflags",
- cmd: "echo '--flags IS_CHROMEOS_DEVICE=\"false\" IS_CHROMEOS_LACROS=\"false\" IS_CHROMEOS_ASH=\"false\" IS_CHROMEOS_WITH_HW_DETAILS=\"false\" IS_REVEN=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//build:chromeos_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "build/chromeos_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //build/config/compiler:compiler_buildflags
-cc_genrule {
- name: "cronet_aml_build_config_compiler_compiler_buildflags",
- cmd: "echo '--flags CLANG_PGO=\"0\" SYMBOL_LEVEL=\"1\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//build/config/compiler:compiler_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "build/config/compiler/compiler_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //buildtools/third_party/libc++:libc++
-cc_object {
- name: "cronet_aml_buildtools_third_party_libc___libc__",
- srcs: [
- "buildtools/third_party/libc++/trunk/src/algorithm.cpp",
- "buildtools/third_party/libc++/trunk/src/any.cpp",
- "buildtools/third_party/libc++/trunk/src/atomic.cpp",
- "buildtools/third_party/libc++/trunk/src/barrier.cpp",
- "buildtools/third_party/libc++/trunk/src/bind.cpp",
- "buildtools/third_party/libc++/trunk/src/charconv.cpp",
- "buildtools/third_party/libc++/trunk/src/chrono.cpp",
- "buildtools/third_party/libc++/trunk/src/condition_variable.cpp",
- "buildtools/third_party/libc++/trunk/src/condition_variable_destructor.cpp",
- "buildtools/third_party/libc++/trunk/src/exception.cpp",
- "buildtools/third_party/libc++/trunk/src/format.cpp",
- "buildtools/third_party/libc++/trunk/src/functional.cpp",
- "buildtools/third_party/libc++/trunk/src/future.cpp",
- "buildtools/third_party/libc++/trunk/src/hash.cpp",
- "buildtools/third_party/libc++/trunk/src/ios.cpp",
- "buildtools/third_party/libc++/trunk/src/ios.instantiations.cpp",
- "buildtools/third_party/libc++/trunk/src/iostream.cpp",
- "buildtools/third_party/libc++/trunk/src/legacy_pointer_safety.cpp",
- "buildtools/third_party/libc++/trunk/src/locale.cpp",
- "buildtools/third_party/libc++/trunk/src/memory.cpp",
- "buildtools/third_party/libc++/trunk/src/mutex.cpp",
- "buildtools/third_party/libc++/trunk/src/mutex_destructor.cpp",
- "buildtools/third_party/libc++/trunk/src/new.cpp",
- "buildtools/third_party/libc++/trunk/src/optional.cpp",
- "buildtools/third_party/libc++/trunk/src/random.cpp",
- "buildtools/third_party/libc++/trunk/src/random_shuffle.cpp",
- "buildtools/third_party/libc++/trunk/src/regex.cpp",
- "buildtools/third_party/libc++/trunk/src/ryu/d2fixed.cpp",
- "buildtools/third_party/libc++/trunk/src/ryu/d2s.cpp",
- "buildtools/third_party/libc++/trunk/src/ryu/f2s.cpp",
- "buildtools/third_party/libc++/trunk/src/shared_mutex.cpp",
- "buildtools/third_party/libc++/trunk/src/stdexcept.cpp",
- "buildtools/third_party/libc++/trunk/src/string.cpp",
- "buildtools/third_party/libc++/trunk/src/strstream.cpp",
- "buildtools/third_party/libc++/trunk/src/system_error.cpp",
- "buildtools/third_party/libc++/trunk/src/thread.cpp",
- "buildtools/third_party/libc++/trunk/src/typeinfo.cpp",
- "buildtools/third_party/libc++/trunk/src/utility.cpp",
- "buildtools/third_party/libc++/trunk/src/valarray.cpp",
- "buildtools/third_party/libc++/trunk/src/variant.cpp",
- "buildtools/third_party/libc++/trunk/src/vector.cpp",
- "buildtools/third_party/libc++/trunk/src/verbose_abort.cpp",
- ],
- host_supported: true,
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DLIBCXX_BUILDING_LIBCXXABI",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED=1",
- "-D_LIBCPP_BUILDING_LIBRARY",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCPP_OVERRIDABLE_FUNC_VIS=__attribute__((__visibility__(\"default\")))",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++/trunk/src/",
- "buildtools/third_party/libc++abi/trunk/include",
- ],
- cpp_std: "c++20",
- cppflags: [
- "-fexceptions",
- ],
- rtti: true,
- target: {
- android_arm: {
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DHAVE_SYS_UIO_H",
- ],
- },
- android_arm64: {
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DHAVE_SYS_UIO_H",
- ],
- },
- android_x86: {
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DHAVE_SYS_UIO_H",
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DHAVE_SYS_UIO_H",
- "-msse3",
- ],
- },
- host: {
- cflags: [
- "-DCR_SYSROOT_KEY=20220331T153654Z-0",
- "-DNO_UNWIND_TABLES",
- "-DUSE_AURA=1",
- "-DUSE_OZONE=1",
- "-DUSE_UDEV",
- "-D_FILE_OFFSET_BITS=64",
- "-D_LARGEFILE64_SOURCE",
- "-D_LARGEFILE_SOURCE",
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //buildtools/third_party/libc++abi:libc++abi
-cc_object {
- name: "cronet_aml_buildtools_third_party_libc__abi_libc__abi",
- srcs: [
- "buildtools/third_party/libc++abi/trunk/src/abort_message.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_aux_runtime.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_default_handlers.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_exception.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_exception_storage.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_guard.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_handlers.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_personality.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_thread_atexit.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_vector.cpp",
- "buildtools/third_party/libc++abi/trunk/src/cxa_virtual.cpp",
- "buildtools/third_party/libc++abi/trunk/src/fallback_malloc.cpp",
- "buildtools/third_party/libc++abi/trunk/src/private_typeinfo.cpp",
- "buildtools/third_party/libc++abi/trunk/src/stdlib_exception.cpp",
- "buildtools/third_party/libc++abi/trunk/src/stdlib_stdexcept.cpp",
- "buildtools/third_party/libc++abi/trunk/src/stdlib_typeinfo.cpp",
- ],
- host_supported: true,
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DLIBCXXABI_SILENT_TERMINATE",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_BUILDING_LIBRARY",
- "-D_LIBCPP_CONSTINIT=constinit",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++/trunk/src/",
- "buildtools/third_party/libc++abi/trunk/include",
- ],
- cpp_std: "c++20",
- cppflags: [
- "-fexceptions",
- ],
- rtti: true,
- target: {
- android_arm: {
- srcs: [
- "buildtools/third_party/libc++abi/cxa_demangle_stub.cc",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DHAVE_SYS_UIO_H",
- ],
- },
- android_arm64: {
- srcs: [
- "buildtools/third_party/libc++abi/cxa_demangle_stub.cc",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DHAVE_SYS_UIO_H",
- ],
- },
- android_x86: {
- srcs: [
- "buildtools/third_party/libc++abi/cxa_demangle_stub.cc",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DHAVE_SYS_UIO_H",
- "-msse3",
- ],
- },
- android_x86_64: {
- srcs: [
- "buildtools/third_party/libc++abi/cxa_demangle_stub.cc",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DHAVE_SYS_UIO_H",
- "-msse3",
- ],
- },
- host: {
- srcs: [
- "buildtools/third_party/libc++abi/trunk/src/cxa_demangle.cpp",
- ],
- cflags: [
- "-DCR_SYSROOT_KEY=20220331T153654Z-0",
- "-DNO_UNWIND_TABLES",
- "-DUSE_AURA=1",
- "-DUSE_OZONE=1",
- "-DUSE_UDEV",
- "-D_FILE_OFFSET_BITS=64",
- "-D_LARGEFILE64_SOURCE",
- "-D_LARGEFILE_SOURCE",
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //components/cronet/android:buildflags
-cc_genrule {
- name: "cronet_aml_components_cronet_android_buildflags",
- cmd: "echo '--flags INTEGRATED_MODE=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//components/cronet/android:buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "components/cronet/android/buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //components/cronet/android:cronet
-cc_library_shared {
- name: "cronet_aml_components_cronet_android_cronet",
- srcs: [
- ":cronet_aml_buildtools_third_party_libc___libc__",
- ":cronet_aml_buildtools_third_party_libc__abi_libc__abi",
- ":cronet_aml_components_cronet_android_cronet_static",
- ":cronet_aml_components_cronet_cronet_common",
- ":cronet_aml_components_cronet_metrics_util",
- ":cronet_aml_components_metrics_library_support",
- "components/cronet/android/cronet_jni.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_components_prefs_prefs",
- "cronet_aml_crypto_crypto",
- "cronet_aml_net_net",
- "cronet_aml_net_preload_decoder",
- "cronet_aml_net_third_party_quiche_quiche",
- "cronet_aml_net_uri_template",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_brotli_common",
- "cronet_aml_third_party_brotli_dec",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- "cronet_aml_url_url",
- ],
- generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_components_cronet_android_buildflags",
- "cronet_aml_components_cronet_android_cronet_jni_headers",
- "cronet_aml_components_cronet_android_cronet_jni_registration",
- "cronet_aml_components_cronet_cronet_buildflags",
- "cronet_aml_components_cronet_cronet_version_header_action",
- "cronet_aml_third_party_metrics_proto_metrics_proto_gen_headers",
- "cronet_aml_url_buildflags",
- ],
- export_generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_components_cronet_android_buildflags",
- "cronet_aml_components_cronet_android_cronet_jni_headers",
- "cronet_aml_components_cronet_android_cronet_jni_registration",
- "cronet_aml_components_cronet_cronet_buildflags",
- "cronet_aml_components_cronet_cronet_version_header_action",
- "cronet_aml_third_party_metrics_proto_metrics_proto_gen_headers",
- "cronet_aml_url_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "net/third_party/quiche/overrides/",
- "net/third_party/quiche/src/",
- "net/third_party/quiche/src/quiche/common/platform/default/",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- ldflags: [
- "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
- ],
- stem: "libcronet.108.0.5359.128",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //components/cronet/android:cronet_jni_headers
-cc_genrule {
- name: "cronet_aml_components_cronet_android_cronet_jni_headers",
- srcs: [
- "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUploadDataStream.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java",
- ],
- cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
- "long " +
- "--output_dir " +
- "$(genDir)/components/cronet/android/cronet_jni_headers " +
- "--includes " +
- "base/android/jni_generator/jni_generator_helper.h " +
- "--use_proxy_hash " +
- "--output_name " +
- "CronetBidirectionalStream_jni.h " +
- "--output_name " +
- "CronetLibraryLoader_jni.h " +
- "--output_name " +
- "CronetUploadDataStream_jni.h " +
- "--output_name " +
- "CronetUrlRequest_jni.h " +
- "--output_name " +
- "CronetUrlRequestContext_jni.h " +
- "--input_file " +
- "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java) " +
- "--input_file " +
- "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java) " +
- "--input_file " +
- "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetUploadDataStream.java) " +
- "--input_file " +
- "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java) " +
- "--input_file " +
- "$(location components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java) " +
- "--package_prefix " +
- "android.net.http.internal",
- out: [
- "components/cronet/android/cronet_jni_headers/CronetBidirectionalStream_jni.h",
- "components/cronet/android/cronet_jni_headers/CronetLibraryLoader_jni.h",
- "components/cronet/android/cronet_jni_headers/CronetUploadDataStream_jni.h",
- "components/cronet/android/cronet_jni_headers/CronetUrlRequestContext_jni.h",
- "components/cronet/android/cronet_jni_headers/CronetUrlRequest_jni.h",
- ],
- tool_files: [
- "base/android/jni_generator/android_jar.classes",
- "base/android/jni_generator/jni_generator.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/gn_helpers.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //components/cronet/android:cronet_jni_registration
-cc_genrule {
- name: "cronet_aml_components_cronet_android_cronet_jni_registration",
- srcs: [
- "base/android/java/src/org/chromium/base/ActivityState.java",
- "base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java",
- "base/android/java/src/org/chromium/base/ApkAssets.java",
- "base/android/java/src/org/chromium/base/ApplicationStatus.java",
- "base/android/java/src/org/chromium/base/BaseFeatureList.java",
- "base/android/java/src/org/chromium/base/BuildInfo.java",
- "base/android/java/src/org/chromium/base/BundleUtils.java",
- "base/android/java/src/org/chromium/base/ByteArrayGenerator.java",
- "base/android/java/src/org/chromium/base/Callback.java",
- "base/android/java/src/org/chromium/base/CallbackController.java",
- "base/android/java/src/org/chromium/base/CollectionUtil.java",
- "base/android/java/src/org/chromium/base/CommandLine.java",
- "base/android/java/src/org/chromium/base/CommandLineInitUtil.java",
- "base/android/java/src/org/chromium/base/Consumer.java",
- "base/android/java/src/org/chromium/base/ContentUriUtils.java",
- "base/android/java/src/org/chromium/base/ContextUtils.java",
- "base/android/java/src/org/chromium/base/CpuFeatures.java",
- "base/android/java/src/org/chromium/base/DiscardableReferencePool.java",
- "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
- "base/android/java/src/org/chromium/base/EventLog.java",
- "base/android/java/src/org/chromium/base/FeatureList.java",
- "base/android/java/src/org/chromium/base/Features.java",
- "base/android/java/src/org/chromium/base/FieldTrialList.java",
- "base/android/java/src/org/chromium/base/FileUtils.java",
- "base/android/java/src/org/chromium/base/Function.java",
- "base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
- "base/android/java/src/org/chromium/base/IntStringCallback.java",
- "base/android/java/src/org/chromium/base/JNIUtils.java",
- "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
- "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
- "base/android/java/src/org/chromium/base/JniException.java",
- "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
- "base/android/java/src/org/chromium/base/LifetimeAssert.java",
- "base/android/java/src/org/chromium/base/LocaleUtils.java",
- "base/android/java/src/org/chromium/base/Log.java",
- "base/android/java/src/org/chromium/base/MathUtils.java",
- "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
- "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
- "base/android/java/src/org/chromium/base/ObserverList.java",
- "base/android/java/src/org/chromium/base/PackageManagerUtils.java",
- "base/android/java/src/org/chromium/base/PackageUtils.java",
- "base/android/java/src/org/chromium/base/PathService.java",
- "base/android/java/src/org/chromium/base/PathUtils.java",
- "base/android/java/src/org/chromium/base/PiiElider.java",
- "base/android/java/src/org/chromium/base/PowerMonitor.java",
- "base/android/java/src/org/chromium/base/PowerMonitorForQ.java",
- "base/android/java/src/org/chromium/base/Predicate.java",
- "base/android/java/src/org/chromium/base/Promise.java",
- "base/android/java/src/org/chromium/base/RadioUtils.java",
- "base/android/java/src/org/chromium/base/StreamUtil.java",
- "base/android/java/src/org/chromium/base/StrictModeContext.java",
- "base/android/java/src/org/chromium/base/SysUtils.java",
- "base/android/java/src/org/chromium/base/ThreadUtils.java",
- "base/android/java/src/org/chromium/base/TimeUtils.java",
- "base/android/java/src/org/chromium/base/TimezoneUtils.java",
- "base/android/java/src/org/chromium/base/TraceEvent.java",
- "base/android/java/src/org/chromium/base/UnguessableToken.java",
- "base/android/java/src/org/chromium/base/UnownedUserData.java",
- "base/android/java/src/org/chromium/base/UnownedUserDataHost.java",
- "base/android/java/src/org/chromium/base/UnownedUserDataKey.java",
- "base/android/java/src/org/chromium/base/UserData.java",
- "base/android/java/src/org/chromium/base/UserDataHost.java",
- "base/android/java/src/org/chromium/base/WrappedClassLoader.java",
- "base/android/java/src/org/chromium/base/annotations/AccessedByNative.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNative.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNativeForTesting.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
- "base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
- "base/android/java/src/org/chromium/base/annotations/JNINamespace.java",
- "base/android/java/src/org/chromium/base/annotations/JniIgnoreNatives.java",
- "base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
- "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForM.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForN.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForO.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForOMR1.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForP.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForR.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForS.java",
- "base/android/java/src/org/chromium/base/jank_tracker/DummyJankTracker.java",
- "base/android/java/src/org/chromium/base/jank_tracker/FrameMetrics.java",
- "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java",
- "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetricCalculator.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java",
- "base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java",
- "base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
- "base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java",
- "base/android/java/src/org/chromium/base/library_loader/Linker.java",
- "base/android/java/src/org/chromium/base/library_loader/LinkerJni.java",
- "base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java",
- "base/android/java/src/org/chromium/base/library_loader/ModernLinker.java",
- "base/android/java/src/org/chromium/base/library_loader/ModernLinkerJni.java",
- "base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
- "base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
- "base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java",
- "base/android/java/src/org/chromium/base/lifetime/Destroyable.java",
- "base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java",
- "base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/RecordHistogram.java",
- "base/android/java/src/org/chromium/base/metrics/RecordUserAction.java",
- "base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java",
- "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
- "base/android/java/src/org/chromium/base/metrics/TimingMetric.java",
- "base/android/java/src/org/chromium/base/metrics/UmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java",
- "base/android/java/src/org/chromium/base/supplier/BooleanSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java",
- "base/android/java/src/org/chromium/base/supplier/OneShotCallback.java",
- "base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java",
- "base/android/java/src/org/chromium/base/supplier/Supplier.java",
- "base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java",
- "base/android/java/src/org/chromium/base/task/AsyncTask.java",
- "base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java",
- "base/android/java/src/org/chromium/base/task/ChainedTasks.java",
- "base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java",
- "base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java",
- "base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java",
- "base/android/java/src/org/chromium/base/task/PostTask.java",
- "base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java",
- "base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java",
- "base/android/java/src/org/chromium/base/task/SerialExecutor.java",
- "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunner.java",
- "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java",
- "base/android/java/src/org/chromium/base/task/TaskExecutor.java",
- "base/android/java/src/org/chromium/base/task/TaskRunner.java",
- "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
- "base/android/java/src/org/chromium/base/task/TaskTraits.java",
- "base/android/java/src/org/chromium/base/task/TaskTraitsExtensionDescriptor.java",
- "build/android/java/src/org/chromium/build/annotations/AlwaysInline.java",
- "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
- "build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java",
- "build/android/java/src/org/chromium/build/annotations/DoNotInline.java",
- "build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java",
- "build/android/java/src/org/chromium/build/annotations/MainDex.java",
- "build/android/java/src/org/chromium/build/annotations/MockedInTests.java",
- "build/android/java/src/org/chromium/build/annotations/UsedByReflection.java",
- "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamNetworkException.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CallbackExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBase.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLogger.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLoggerFactory.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetManifest.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetMetrics.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUploadDataStream.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java",
- "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/NetworkExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/NoOpLogger.java",
- "components/cronet/android/java/src/org/chromium/net/impl/Preconditions.java",
- "components/cronet/android/java/src/org/chromium/net/impl/QuicExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/RequestFinishedInfoImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBase.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UserAgent.java",
- "components/cronet/android/java/src/org/chromium/net/impl/VersionSafeCallbacks.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetBufferedOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetChunkedOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetFixedModeOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetInputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java",
- "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
- "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
- "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
- "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
- "net/android/java/src/org/chromium/net/ChromiumNetworkAdapter.java",
- "net/android/java/src/org/chromium/net/DnsStatus.java",
- "net/android/java/src/org/chromium/net/GURLUtils.java",
- "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
- "net/android/java/src/org/chromium/net/HttpNegotiateConstants.java",
- "net/android/java/src/org/chromium/net/HttpUtil.java",
- "net/android/java/src/org/chromium/net/MimeTypeFilter.java",
- "net/android/java/src/org/chromium/net/NetStringUtil.java",
- "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
- "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
- "net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java",
- "net/android/java/src/org/chromium/net/NetworkTrafficAnnotationTag.java",
- "net/android/java/src/org/chromium/net/ProxyBroadcastReceiver.java",
- "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
- "net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java",
- "net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java",
- "net/android/java/src/org/chromium/net/ThreadStatsUid.java",
- "net/android/java/src/org/chromium/net/X509Util.java",
- "url/android/java/src/org/chromium/url/IDNStringUtil.java",
- ],
- cmd: "current_dir=`basename \\`pwd\\``; " +
- "for f in $(in); " +
- "do " +
- "echo \"../$$current_dir/$$f\" >> $(genDir)/java.sources; " +
- "done; " +
- "python3 $(location base/android/jni_generator/jni_registration_generator.py) --srcjar-path " +
- "$(genDir)/components/cronet/android/cronet_jni_registration.srcjar " +
- "--depfile " +
- "$(genDir)/components/cronet/android/cronet_jni_registration.d " +
- "--sources-files " +
- "$(genDir)/java.sources " +
- "--include_test_only " +
- "--use_proxy_hash " +
- "--header-path " +
- "$(genDir)/components/cronet/android/cronet_jni_registration.h " +
- "--manual_jni_registration " +
- "--package_prefix " +
- "android.net.http.internal " +
- ";sed -i -e 's/OUT_SOONG_.TEMP_SBOX_.*_OUT/GEN/g' " +
- "$(genDir)/components/cronet/android/cronet_jni_registration.h",
- out: [
- "components/cronet/android/cronet_jni_registration.h",
- "components/cronet/android/cronet_jni_registration.srcjar",
- ],
- tool_files: [
- "base/android/jni_generator/jni_generator.py",
- "base/android/jni_generator/jni_registration_generator.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/gn_helpers.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //components/cronet/android:cronet_jni_registration
-java_genrule {
- name: "cronet_aml_components_cronet_android_cronet_jni_registration__java",
- srcs: [
- "base/android/java/src/org/chromium/base/ActivityState.java",
- "base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java",
- "base/android/java/src/org/chromium/base/ApkAssets.java",
- "base/android/java/src/org/chromium/base/ApplicationStatus.java",
- "base/android/java/src/org/chromium/base/BaseFeatureList.java",
- "base/android/java/src/org/chromium/base/BuildInfo.java",
- "base/android/java/src/org/chromium/base/BundleUtils.java",
- "base/android/java/src/org/chromium/base/ByteArrayGenerator.java",
- "base/android/java/src/org/chromium/base/Callback.java",
- "base/android/java/src/org/chromium/base/CallbackController.java",
- "base/android/java/src/org/chromium/base/CollectionUtil.java",
- "base/android/java/src/org/chromium/base/CommandLine.java",
- "base/android/java/src/org/chromium/base/CommandLineInitUtil.java",
- "base/android/java/src/org/chromium/base/Consumer.java",
- "base/android/java/src/org/chromium/base/ContentUriUtils.java",
- "base/android/java/src/org/chromium/base/ContextUtils.java",
- "base/android/java/src/org/chromium/base/CpuFeatures.java",
- "base/android/java/src/org/chromium/base/DiscardableReferencePool.java",
- "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
- "base/android/java/src/org/chromium/base/EventLog.java",
- "base/android/java/src/org/chromium/base/FeatureList.java",
- "base/android/java/src/org/chromium/base/Features.java",
- "base/android/java/src/org/chromium/base/FieldTrialList.java",
- "base/android/java/src/org/chromium/base/FileUtils.java",
- "base/android/java/src/org/chromium/base/Function.java",
- "base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
- "base/android/java/src/org/chromium/base/IntStringCallback.java",
- "base/android/java/src/org/chromium/base/JNIUtils.java",
- "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
- "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
- "base/android/java/src/org/chromium/base/JniException.java",
- "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
- "base/android/java/src/org/chromium/base/LifetimeAssert.java",
- "base/android/java/src/org/chromium/base/LocaleUtils.java",
- "base/android/java/src/org/chromium/base/Log.java",
- "base/android/java/src/org/chromium/base/MathUtils.java",
- "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
- "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
- "base/android/java/src/org/chromium/base/ObserverList.java",
- "base/android/java/src/org/chromium/base/PackageManagerUtils.java",
- "base/android/java/src/org/chromium/base/PackageUtils.java",
- "base/android/java/src/org/chromium/base/PathService.java",
- "base/android/java/src/org/chromium/base/PathUtils.java",
- "base/android/java/src/org/chromium/base/PiiElider.java",
- "base/android/java/src/org/chromium/base/PowerMonitor.java",
- "base/android/java/src/org/chromium/base/PowerMonitorForQ.java",
- "base/android/java/src/org/chromium/base/Predicate.java",
- "base/android/java/src/org/chromium/base/Promise.java",
- "base/android/java/src/org/chromium/base/RadioUtils.java",
- "base/android/java/src/org/chromium/base/StreamUtil.java",
- "base/android/java/src/org/chromium/base/StrictModeContext.java",
- "base/android/java/src/org/chromium/base/SysUtils.java",
- "base/android/java/src/org/chromium/base/ThreadUtils.java",
- "base/android/java/src/org/chromium/base/TimeUtils.java",
- "base/android/java/src/org/chromium/base/TimezoneUtils.java",
- "base/android/java/src/org/chromium/base/TraceEvent.java",
- "base/android/java/src/org/chromium/base/UnguessableToken.java",
- "base/android/java/src/org/chromium/base/UnownedUserData.java",
- "base/android/java/src/org/chromium/base/UnownedUserDataHost.java",
- "base/android/java/src/org/chromium/base/UnownedUserDataKey.java",
- "base/android/java/src/org/chromium/base/UserData.java",
- "base/android/java/src/org/chromium/base/UserDataHost.java",
- "base/android/java/src/org/chromium/base/WrappedClassLoader.java",
- "base/android/java/src/org/chromium/base/annotations/AccessedByNative.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNative.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNativeForTesting.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
- "base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
- "base/android/java/src/org/chromium/base/annotations/JNINamespace.java",
- "base/android/java/src/org/chromium/base/annotations/JniIgnoreNatives.java",
- "base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
- "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForM.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForN.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForO.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForOMR1.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForP.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForR.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForS.java",
- "base/android/java/src/org/chromium/base/jank_tracker/DummyJankTracker.java",
- "base/android/java/src/org/chromium/base/jank_tracker/FrameMetrics.java",
- "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java",
- "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetricCalculator.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java",
- "base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java",
- "base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
- "base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java",
- "base/android/java/src/org/chromium/base/library_loader/Linker.java",
- "base/android/java/src/org/chromium/base/library_loader/LinkerJni.java",
- "base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java",
- "base/android/java/src/org/chromium/base/library_loader/ModernLinker.java",
- "base/android/java/src/org/chromium/base/library_loader/ModernLinkerJni.java",
- "base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
- "base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
- "base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java",
- "base/android/java/src/org/chromium/base/lifetime/Destroyable.java",
- "base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java",
- "base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/RecordHistogram.java",
- "base/android/java/src/org/chromium/base/metrics/RecordUserAction.java",
- "base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java",
- "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
- "base/android/java/src/org/chromium/base/metrics/TimingMetric.java",
- "base/android/java/src/org/chromium/base/metrics/UmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java",
- "base/android/java/src/org/chromium/base/supplier/BooleanSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java",
- "base/android/java/src/org/chromium/base/supplier/OneShotCallback.java",
- "base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java",
- "base/android/java/src/org/chromium/base/supplier/Supplier.java",
- "base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java",
- "base/android/java/src/org/chromium/base/task/AsyncTask.java",
- "base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java",
- "base/android/java/src/org/chromium/base/task/ChainedTasks.java",
- "base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java",
- "base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java",
- "base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java",
- "base/android/java/src/org/chromium/base/task/PostTask.java",
- "base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java",
- "base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java",
- "base/android/java/src/org/chromium/base/task/SerialExecutor.java",
- "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunner.java",
- "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java",
- "base/android/java/src/org/chromium/base/task/TaskExecutor.java",
- "base/android/java/src/org/chromium/base/task/TaskRunner.java",
- "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
- "base/android/java/src/org/chromium/base/task/TaskTraits.java",
- "base/android/java/src/org/chromium/base/task/TaskTraitsExtensionDescriptor.java",
- "build/android/java/src/org/chromium/build/annotations/AlwaysInline.java",
- "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
- "build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java",
- "build/android/java/src/org/chromium/build/annotations/DoNotInline.java",
- "build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java",
- "build/android/java/src/org/chromium/build/annotations/MainDex.java",
- "build/android/java/src/org/chromium/build/annotations/MockedInTests.java",
- "build/android/java/src/org/chromium/build/annotations/UsedByReflection.java",
- "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamNetworkException.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CallbackExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBase.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLogger.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLoggerFactory.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetManifest.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetMetrics.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUploadDataStream.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java",
- "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/NetworkExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/NoOpLogger.java",
- "components/cronet/android/java/src/org/chromium/net/impl/Preconditions.java",
- "components/cronet/android/java/src/org/chromium/net/impl/QuicExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/RequestFinishedInfoImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBase.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UserAgent.java",
- "components/cronet/android/java/src/org/chromium/net/impl/VersionSafeCallbacks.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetBufferedOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetChunkedOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetFixedModeOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetInputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java",
- "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
- "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
- "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
- "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
- "net/android/java/src/org/chromium/net/ChromiumNetworkAdapter.java",
- "net/android/java/src/org/chromium/net/DnsStatus.java",
- "net/android/java/src/org/chromium/net/GURLUtils.java",
- "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
- "net/android/java/src/org/chromium/net/HttpNegotiateConstants.java",
- "net/android/java/src/org/chromium/net/HttpUtil.java",
- "net/android/java/src/org/chromium/net/MimeTypeFilter.java",
- "net/android/java/src/org/chromium/net/NetStringUtil.java",
- "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
- "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
- "net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java",
- "net/android/java/src/org/chromium/net/NetworkTrafficAnnotationTag.java",
- "net/android/java/src/org/chromium/net/ProxyBroadcastReceiver.java",
- "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
- "net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java",
- "net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java",
- "net/android/java/src/org/chromium/net/ThreadStatsUid.java",
- "net/android/java/src/org/chromium/net/X509Util.java",
- "url/android/java/src/org/chromium/url/IDNStringUtil.java",
- ],
- cmd: "current_dir=`basename \\`pwd\\``; " +
- "for f in $(in); " +
- "do " +
- "echo \"../$$current_dir/$$f\" >> $(genDir)/java.sources; " +
- "done; " +
- "python3 $(location base/android/jni_generator/jni_registration_generator.py) --srcjar-path " +
- "$(genDir)/components/cronet/android/cronet_jni_registration.srcjar " +
- "--depfile " +
- "$(genDir)/components/cronet/android/cronet_jni_registration.d " +
- "--sources-files " +
- "$(genDir)/java.sources " +
- "--include_test_only " +
- "--use_proxy_hash " +
- "--header-path " +
- "$(genDir)/components/cronet/android/cronet_jni_registration.h " +
- "--manual_jni_registration " +
- "--package_prefix " +
- "android.net.http.internal " +
- ";sed -i -e 's/OUT_SOONG_.TEMP_SBOX_.*_OUT/GEN/g' " +
- "$(genDir)/components/cronet/android/cronet_jni_registration.h",
- out: [
- "components/cronet/android/cronet_jni_registration.srcjar",
- ],
- tool_files: [
- "base/android/jni_generator/jni_generator.py",
- "base/android/jni_generator/jni_registration_generator.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/gn_helpers.py",
- ],
-}
-
-// GN: //components/cronet/android:cronet_static
-cc_object {
- name: "cronet_aml_components_cronet_android_cronet_static",
- srcs: [
- "components/cronet/android/cronet_bidirectional_stream_adapter.cc",
- "components/cronet/android/cronet_context_adapter.cc",
- "components/cronet/android/cronet_library_loader.cc",
- "components/cronet/android/cronet_upload_data_stream_adapter.cc",
- "components/cronet/android/cronet_url_request_adapter.cc",
- "components/cronet/android/io_buffer_with_byte_buffer.cc",
- "components/cronet/android/url_request_error.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_components_prefs_prefs",
- "cronet_aml_crypto_crypto",
- "cronet_aml_net_net",
- "cronet_aml_net_preload_decoder",
- "cronet_aml_net_third_party_quiche_quiche",
- "cronet_aml_net_uri_template",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_brotli_common",
- "cronet_aml_third_party_brotli_dec",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- "cronet_aml_url_url",
- ],
- generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_components_cronet_android_buildflags",
- "cronet_aml_components_cronet_android_cronet_jni_headers",
- "cronet_aml_components_cronet_android_cronet_jni_registration",
- "cronet_aml_components_cronet_cronet_buildflags",
- "cronet_aml_components_cronet_cronet_version_header_action",
- "cronet_aml_third_party_metrics_proto_metrics_proto_gen_headers",
- "cronet_aml_url_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "net/third_party/quiche/overrides/",
- "net/third_party/quiche/src/",
- "net/third_party/quiche/src/quiche/common/platform/default/",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //components/cronet/android:http_cache_type_java
-java_genrule {
- name: "cronet_aml_components_cronet_android_http_cache_type_java",
- cmd: "$(location build/android/gyp/java_cpp_enum.py) --srcjar " +
- "$(out) " +
- "$(location components/cronet/url_request_context_config.h)",
- out: [
- "components/cronet/android/http_cache_type_java.srcjar",
- ],
- tool_files: [
- "build/android/gyp/java_cpp_enum.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- "components/cronet/url_request_context_config.h",
- ],
-}
-
-// GN: //components/cronet/android:implementation_api_version
-java_genrule {
- name: "cronet_aml_components_cronet_android_implementation_api_version",
- cmd: "$(location build/util/version.py) --official " +
- "-f " +
- "$(location chrome/VERSION) " +
- "-f " +
- "$(location build/util/LASTCHANGE) " +
- "-e " +
- "'API_LEVEL=19' " +
- "-o " +
- "$(out) " +
- "$(location components/cronet/android/java/src/org/chromium/net/impl/ImplVersion.template)",
- out: [
- "components/cronet/android/templates/org/chromium/net/impl/ImplVersion.java",
- ],
- tool_files: [
- "build/util/LASTCHANGE",
- "build/util/android_chrome_version.py",
- "build/util/version.py",
- "chrome/VERSION",
- "components/cronet/android/java/src/org/chromium/net/impl/ImplVersion.template",
- ],
-}
-
-// GN: //components/cronet/android:integrated_mode_state
-genrule {
- name: "cronet_aml_components_cronet_android_integrated_mode_state",
- srcs: [
- ":cronet_aml_components_cronet_android_integrated_mode_state_preprocess",
- ],
- tools: [
- "soong_zip",
- ],
- cmd: "cp $(in) $(genDir)/IntegratedModeState.java && " +
- "$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/IntegratedModeState.java",
- out: [
- "IntegratedModeState.srcjar",
- ],
-}
-
-// GN: //components/cronet/android:integrated_mode_state
-cc_object {
- name: "cronet_aml_components_cronet_android_integrated_mode_state_preprocess",
- srcs: [
- ":cronet_aml_components_cronet_android_integrated_mode_state_rename",
- ],
- cflags: [
- "-DANDROID",
- "-E",
- "-P",
- ],
- compile_multilib: "first",
-}
-
-// GN: //components/cronet/android:integrated_mode_state
-genrule {
- name: "cronet_aml_components_cronet_android_integrated_mode_state_rename",
- srcs: [
- "components/cronet/android/java/src/org/chromium/net/impl/IntegratedModeState.template",
- ],
- cmd: "cp $(in) $(out)",
- out: [
- "IntegratedModeState.cc",
- ],
-}
-
-// GN: //components/cronet/android:interface_api_version
-java_genrule {
- name: "cronet_aml_components_cronet_android_interface_api_version",
- cmd: "$(location build/util/version.py) --official " +
- "-f " +
- "$(location chrome/VERSION) " +
- "-f " +
- "$(location build/util/LASTCHANGE) " +
- "-e " +
- "'API_LEVEL=19' " +
- "-o " +
- "$(out) " +
- "$(location components/cronet/android/api/src/android/net/http/ApiVersion.template)",
- out: [
- "components/cronet/android/templates/org/chromium/net/ApiVersion.java",
- ],
- tool_files: [
- "build/util/LASTCHANGE",
- "build/util/android_chrome_version.py",
- "build/util/version.py",
- "chrome/VERSION",
- "components/cronet/android/api/src/android/net/http/ApiVersion.template",
- ],
-}
-
-// GN: //components/cronet/android:load_states_list
-genrule {
- name: "cronet_aml_components_cronet_android_load_states_list",
- srcs: [
- ":cronet_aml_components_cronet_android_load_states_list_preprocess",
- ],
- tools: [
- "soong_zip",
- ],
- cmd: "cp $(in) $(genDir)/LoadState.java && " +
- "$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/LoadState.java",
- out: [
- "LoadState.srcjar",
- ],
-}
-
-// GN: //components/cronet/android:load_states_list
-cc_object {
- name: "cronet_aml_components_cronet_android_load_states_list_preprocess",
- srcs: [
- ":cronet_aml_components_cronet_android_load_states_list_rename",
- ],
- cflags: [
- "-DANDROID",
- "-E",
- "-P",
- ],
- compile_multilib: "first",
-}
-
-// GN: //components/cronet/android:load_states_list
-genrule {
- name: "cronet_aml_components_cronet_android_load_states_list_rename",
- srcs: [
- "components/cronet/android/java/src/org/chromium/net/impl/LoadState.template",
- ],
- cmd: "cp $(in) $(out)",
- out: [
- "LoadState.cc",
- ],
-}
-
-// GN: //components/cronet/android:net_idempotency_java
-java_genrule {
- name: "cronet_aml_components_cronet_android_net_idempotency_java",
- cmd: "$(location build/android/gyp/java_cpp_enum.py) --srcjar " +
- "$(out) " +
- "$(location net/base/idempotency.h)",
- out: [
- "components/cronet/android/net_idempotency_java.srcjar",
- ],
- tool_files: [
- "build/android/gyp/java_cpp_enum.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- "net/base/idempotency.h",
- ],
-}
-
-// GN: //components/cronet/android:net_request_priority_java
-java_genrule {
- name: "cronet_aml_components_cronet_android_net_request_priority_java",
- cmd: "$(location build/android/gyp/java_cpp_enum.py) --srcjar " +
- "$(out) " +
- "$(location net/base/request_priority.h)",
- out: [
- "components/cronet/android/net_request_priority_java.srcjar",
- ],
- tool_files: [
- "build/android/gyp/java_cpp_enum.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- "net/base/request_priority.h",
- ],
-}
-
-// GN: //components/cronet/android:network_quality_observation_source_java
-java_genrule {
- name: "cronet_aml_components_cronet_android_network_quality_observation_source_java",
- cmd: "$(location build/android/gyp/java_cpp_enum.py) --srcjar " +
- "$(out) " +
- "$(location net/nqe/network_quality_observation_source.h)",
- out: [
- "components/cronet/android/network_quality_observation_source_java.srcjar",
- ],
- tool_files: [
- "build/android/gyp/java_cpp_enum.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- "net/nqe/network_quality_observation_source.h",
- ],
-}
-
-// GN: //components/cronet/android:rtt_throughput_values_java
-java_genrule {
- name: "cronet_aml_components_cronet_android_rtt_throughput_values_java",
- cmd: "$(location build/android/gyp/java_cpp_enum.py) --srcjar " +
- "$(out) " +
- "$(location net/nqe/network_quality.h)",
- out: [
- "components/cronet/android/rtt_throughput_values_java.srcjar",
- ],
- tool_files: [
- "build/android/gyp/java_cpp_enum.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- "net/nqe/network_quality.h",
- ],
-}
-
-// GN: //components/cronet/android:url_request_error_java
-java_genrule {
- name: "cronet_aml_components_cronet_android_url_request_error_java",
- cmd: "$(location build/android/gyp/java_cpp_enum.py) --srcjar " +
- "$(out) " +
- "$(location components/cronet/android/url_request_error.h)",
- out: [
- "components/cronet/android/url_request_error_java.srcjar",
- ],
- tool_files: [
- "build/android/gyp/java_cpp_enum.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- "components/cronet/android/url_request_error.h",
- ],
-}
-
-// GN: //components/cronet:cronet_buildflags
-cc_genrule {
- name: "cronet_aml_components_cronet_cronet_buildflags",
- cmd: "echo '--flags DISABLE_HISTOGRAM_SUPPORT=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//components/cronet:cronet_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "components/cronet/cronet_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //components/cronet:cronet_common
-cc_object {
- name: "cronet_aml_components_cronet_cronet_common",
- srcs: [
- "components/cronet/cronet_context.cc",
- "components/cronet/cronet_prefs_manager.cc",
- "components/cronet/cronet_upload_data_stream.cc",
- "components/cronet/cronet_url_request.cc",
- "components/cronet/host_cache_persistence_manager.cc",
- "components/cronet/stale_host_resolver.cc",
- "components/cronet/url_request_context_config.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_components_prefs_prefs",
- "cronet_aml_crypto_crypto",
- "cronet_aml_net_net",
- "cronet_aml_net_preload_decoder",
- "cronet_aml_net_third_party_quiche_quiche",
- "cronet_aml_net_uri_template",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_brotli_common",
- "cronet_aml_third_party_brotli_dec",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- "cronet_aml_url_url",
- ],
- generated_headers: [
- "cronet_aml_components_cronet_cronet_buildflags",
- "cronet_aml_components_cronet_cronet_version_header_action",
- "cronet_aml_third_party_metrics_proto_metrics_proto_gen_headers",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "net/third_party/quiche/overrides/",
- "net/third_party/quiche/src/",
- "net/third_party/quiche/src/quiche/common/platform/default/",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //components/cronet:cronet_version_header_action
-cc_genrule {
- name: "cronet_aml_components_cronet_cronet_version_header_action",
- cmd: "$(location build/util/version.py) --official " +
- "-f " +
- "$(location chrome/VERSION) " +
- "-e " +
- "'VERSION_FULL=\"%s.%s.%s.%s\" % (MAJOR,MINOR,BUILD,PATCH)' " +
- "-o " +
- "$(out) " +
- "$(location components/cronet/version.h.in)",
- out: [
- "components/cronet/version.h",
- ],
- tool_files: [
- "build/util/LASTCHANGE",
- "build/util/android_chrome_version.py",
- "build/util/version.py",
- "chrome/VERSION",
- "components/cronet/version.h.in",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //components/cronet:metrics_util
-cc_object {
- name: "cronet_aml_components_cronet_metrics_util",
- srcs: [
- "components/cronet/metrics_util.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //components/metrics:library_support
-cc_object {
- name: "cronet_aml_components_metrics_library_support",
- srcs: [
- ":cronet_aml_third_party_metrics_proto_metrics_proto_gen",
- "components/metrics/histogram_encoder.cc",
- "components/metrics/library_support/histogram_manager.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libprotobuf-cpp-lite",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- ],
- generated_headers: [
- "cronet_aml_third_party_metrics_proto_metrics_proto_gen_headers",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //components/prefs/android:jni_headers
-cc_genrule {
- name: "cronet_aml_components_prefs_android_jni_headers",
- srcs: [
- "components/prefs/android/java/src/org/chromium/components/prefs/PrefService.java",
- ],
- cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
- "long " +
- "--output_dir " +
- "$(genDir)/components/prefs/android/jni_headers " +
- "--includes " +
- "base/android/jni_generator/jni_generator_helper.h " +
- "--use_proxy_hash " +
- "--output_name " +
- "PrefService_jni.h " +
- "--input_file " +
- "$(location components/prefs/android/java/src/org/chromium/components/prefs/PrefService.java) " +
- "--package_prefix " +
- "android.net.http.internal",
- out: [
- "components/prefs/android/jni_headers/PrefService_jni.h",
- ],
- tool_files: [
- "base/android/jni_generator/android_jar.classes",
- "base/android/jni_generator/jni_generator.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/gn_helpers.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //components/prefs:prefs
-cc_library_static {
- name: "cronet_aml_components_prefs_prefs",
- srcs: [
- "components/prefs/android/pref_service_android.cc",
- "components/prefs/command_line_pref_store.cc",
- "components/prefs/default_pref_store.cc",
- "components/prefs/in_memory_pref_store.cc",
- "components/prefs/json_pref_store.cc",
- "components/prefs/overlay_user_pref_store.cc",
- "components/prefs/persistent_pref_store.cc",
- "components/prefs/pref_change_registrar.cc",
- "components/prefs/pref_member.cc",
- "components/prefs/pref_notifier_impl.cc",
- "components/prefs/pref_registry.cc",
- "components/prefs/pref_registry_simple.cc",
- "components/prefs/pref_service.cc",
- "components/prefs/pref_service_factory.cc",
- "components/prefs/pref_store.cc",
- "components/prefs/pref_value_map.cc",
- "components/prefs/pref_value_store.cc",
- "components/prefs/scoped_user_pref_update.cc",
- "components/prefs/segregated_pref_store.cc",
- "components/prefs/value_map_pref_store.cc",
- "components/prefs/writeable_pref_store.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- ],
- generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_components_prefs_android_jni_headers",
- ],
- export_generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_components_prefs_android_jni_headers",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCOMPONENTS_PREFS_IMPLEMENTATION",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //crypto:buildflags
-cc_genrule {
- name: "cronet_aml_crypto_buildflags",
- cmd: "echo '--flags USE_NSS_CERTS=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//crypto:buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "crypto/crypto_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //crypto:crypto
-cc_library_static {
- name: "cronet_aml_crypto_crypto",
- srcs: [
- "crypto/aead.cc",
- "crypto/ec_private_key.cc",
- "crypto/ec_signature_creator.cc",
- "crypto/ec_signature_creator_impl.cc",
- "crypto/encryptor.cc",
- "crypto/hkdf.cc",
- "crypto/hmac.cc",
- "crypto/openssl_util.cc",
- "crypto/p224_spake.cc",
- "crypto/random.cc",
- "crypto/rsa_private_key.cc",
- "crypto/secure_hash.cc",
- "crypto/secure_util.cc",
- "crypto/sha2.cc",
- "crypto/signature_creator.cc",
- "crypto/signature_verifier.cc",
- "crypto/symmetric_key.cc",
- "crypto/unexportable_key.cc",
- "crypto/unexportable_key_metrics.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- ],
- generated_headers: [
- "cronet_aml_crypto_buildflags",
- ],
- export_generated_headers: [
- "cronet_aml_crypto_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCRYPTO_IMPLEMENTATION",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //gn:default_deps
-cc_defaults {
- name: "cronet_aml_defaults",
- cflags: [
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-O2",
- "-Wno-ambiguous-reversed-operator",
- "-Wno-error=return-type",
- "-Wno-macro-redefined",
- "-Wno-missing-field-initializers",
- "-Wno-non-virtual-dtor",
- "-Wno-null-pointer-subtraction",
- "-Wno-sign-compare",
- "-Wno-sign-promo",
- "-Wno-unreachable-code-loop-increment",
- "-Wno-unused-parameter",
- "-fPIC",
- "-fvisibility=hidden",
- ],
- stl: "none",
- apex_available: [
- "com.android.tethering",
- ],
- min_sdk_version: "29",
- target: {
- android: {
- shared_libs: [
- "libmediandk",
- ],
- header_libs: [
- "jni_headers",
- ],
- },
- host: {
- cflags: [
- "-UANDROID",
- ],
- },
- },
-}
-
-// GN: //gn:java
-java_library {
- name: "cronet_aml_java",
- srcs: [
- ":cronet_aml_base_base_android_java_enums_srcjar",
- ":cronet_aml_base_java_features_srcjar",
- ":cronet_aml_base_java_switches_srcjar",
- ":cronet_aml_build_android_build_config_gen",
- ":cronet_aml_build_android_native_libraries_gen",
- ":cronet_aml_components_cronet_android_cronet_jni_registration__java",
- ":cronet_aml_components_cronet_android_http_cache_type_java",
- ":cronet_aml_components_cronet_android_implementation_api_version",
- ":cronet_aml_components_cronet_android_integrated_mode_state",
- ":cronet_aml_components_cronet_android_interface_api_version",
- ":cronet_aml_components_cronet_android_load_states_list",
- ":cronet_aml_components_cronet_android_net_idempotency_java",
- ":cronet_aml_components_cronet_android_net_request_priority_java",
- ":cronet_aml_components_cronet_android_network_quality_observation_source_java",
- ":cronet_aml_components_cronet_android_rtt_throughput_values_java",
- ":cronet_aml_components_cronet_android_url_request_error_java",
- ":cronet_aml_net_android_net_android_java_enums_srcjar",
- ":cronet_aml_net_android_net_errors_java",
- ":cronet_aml_net_effective_connection_type_java",
- "base/android/java/src/org/chromium/base/ActivityState.java",
- "base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java",
- "base/android/java/src/org/chromium/base/ApkAssets.java",
- "base/android/java/src/org/chromium/base/ApplicationStatus.java",
- "base/android/java/src/org/chromium/base/BaseFeatureList.java",
- "base/android/java/src/org/chromium/base/BuildInfo.java",
- "base/android/java/src/org/chromium/base/BundleUtils.java",
- "base/android/java/src/org/chromium/base/ByteArrayGenerator.java",
- "base/android/java/src/org/chromium/base/Callback.java",
- "base/android/java/src/org/chromium/base/CallbackController.java",
- "base/android/java/src/org/chromium/base/CollectionUtil.java",
- "base/android/java/src/org/chromium/base/CommandLine.java",
- "base/android/java/src/org/chromium/base/CommandLineInitUtil.java",
- "base/android/java/src/org/chromium/base/Consumer.java",
- "base/android/java/src/org/chromium/base/ContentUriUtils.java",
- "base/android/java/src/org/chromium/base/ContextUtils.java",
- "base/android/java/src/org/chromium/base/CpuFeatures.java",
- "base/android/java/src/org/chromium/base/DiscardableReferencePool.java",
- "base/android/java/src/org/chromium/base/EarlyTraceEvent.java",
- "base/android/java/src/org/chromium/base/EventLog.java",
- "base/android/java/src/org/chromium/base/FeatureList.java",
- "base/android/java/src/org/chromium/base/Features.java",
- "base/android/java/src/org/chromium/base/FieldTrialList.java",
- "base/android/java/src/org/chromium/base/FileUtils.java",
- "base/android/java/src/org/chromium/base/Function.java",
- "base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
- "base/android/java/src/org/chromium/base/IntStringCallback.java",
- "base/android/java/src/org/chromium/base/JNIUtils.java",
- "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
- "base/android/java/src/org/chromium/base/JavaHandlerThread.java",
- "base/android/java/src/org/chromium/base/JniException.java",
- "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
- "base/android/java/src/org/chromium/base/LifetimeAssert.java",
- "base/android/java/src/org/chromium/base/LocaleUtils.java",
- "base/android/java/src/org/chromium/base/Log.java",
- "base/android/java/src/org/chromium/base/MathUtils.java",
- "base/android/java/src/org/chromium/base/MemoryPressureListener.java",
- "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
- "base/android/java/src/org/chromium/base/ObserverList.java",
- "base/android/java/src/org/chromium/base/PackageManagerUtils.java",
- "base/android/java/src/org/chromium/base/PackageUtils.java",
- "base/android/java/src/org/chromium/base/PathService.java",
- "base/android/java/src/org/chromium/base/PathUtils.java",
- "base/android/java/src/org/chromium/base/PiiElider.java",
- "base/android/java/src/org/chromium/base/PowerMonitor.java",
- "base/android/java/src/org/chromium/base/PowerMonitorForQ.java",
- "base/android/java/src/org/chromium/base/Predicate.java",
- "base/android/java/src/org/chromium/base/Promise.java",
- "base/android/java/src/org/chromium/base/RadioUtils.java",
- "base/android/java/src/org/chromium/base/StreamUtil.java",
- "base/android/java/src/org/chromium/base/StrictModeContext.java",
- "base/android/java/src/org/chromium/base/SysUtils.java",
- "base/android/java/src/org/chromium/base/ThreadUtils.java",
- "base/android/java/src/org/chromium/base/TimeUtils.java",
- "base/android/java/src/org/chromium/base/TimezoneUtils.java",
- "base/android/java/src/org/chromium/base/TraceEvent.java",
- "base/android/java/src/org/chromium/base/UnguessableToken.java",
- "base/android/java/src/org/chromium/base/UnownedUserData.java",
- "base/android/java/src/org/chromium/base/UnownedUserDataHost.java",
- "base/android/java/src/org/chromium/base/UnownedUserDataKey.java",
- "base/android/java/src/org/chromium/base/UserData.java",
- "base/android/java/src/org/chromium/base/UserDataHost.java",
- "base/android/java/src/org/chromium/base/WrappedClassLoader.java",
- "base/android/java/src/org/chromium/base/annotations/AccessedByNative.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNative.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNativeForTesting.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
- "base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
- "base/android/java/src/org/chromium/base/annotations/JNINamespace.java",
- "base/android/java/src/org/chromium/base/annotations/JniIgnoreNatives.java",
- "base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
- "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForM.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForN.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForO.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForOMR1.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForP.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForR.java",
- "base/android/java/src/org/chromium/base/compat/ApiHelperForS.java",
- "base/android/java/src/org/chromium/base/jank_tracker/DummyJankTracker.java",
- "base/android/java/src/org/chromium/base/jank_tracker/FrameMetrics.java",
- "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java",
- "base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetricCalculator.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java",
- "base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java",
- "base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java",
- "base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
- "base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java",
- "base/android/java/src/org/chromium/base/library_loader/Linker.java",
- "base/android/java/src/org/chromium/base/library_loader/LinkerJni.java",
- "base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java",
- "base/android/java/src/org/chromium/base/library_loader/ModernLinker.java",
- "base/android/java/src/org/chromium/base/library_loader/ModernLinkerJni.java",
- "base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
- "base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
- "base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java",
- "base/android/java/src/org/chromium/base/lifetime/Destroyable.java",
- "base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java",
- "base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java",
- "base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/RecordHistogram.java",
- "base/android/java/src/org/chromium/base/metrics/RecordUserAction.java",
- "base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java",
- "base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
- "base/android/java/src/org/chromium/base/metrics/TimingMetric.java",
- "base/android/java/src/org/chromium/base/metrics/UmaRecorder.java",
- "base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java",
- "base/android/java/src/org/chromium/base/supplier/BooleanSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java",
- "base/android/java/src/org/chromium/base/supplier/OneShotCallback.java",
- "base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java",
- "base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java",
- "base/android/java/src/org/chromium/base/supplier/Supplier.java",
- "base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java",
- "base/android/java/src/org/chromium/base/task/AsyncTask.java",
- "base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java",
- "base/android/java/src/org/chromium/base/task/ChainedTasks.java",
- "base/android/java/src/org/chromium/base/task/ChoreographerTaskRunner.java",
- "base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java",
- "base/android/java/src/org/chromium/base/task/DefaultTaskExecutor.java",
- "base/android/java/src/org/chromium/base/task/PostTask.java",
- "base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java",
- "base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java",
- "base/android/java/src/org/chromium/base/task/SerialExecutor.java",
- "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunner.java",
- "base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java",
- "base/android/java/src/org/chromium/base/task/TaskExecutor.java",
- "base/android/java/src/org/chromium/base/task/TaskRunner.java",
- "base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java",
- "base/android/java/src/org/chromium/base/task/TaskTraits.java",
- "base/android/java/src/org/chromium/base/task/TaskTraitsExtensionDescriptor.java",
- "build/android/java/src/org/chromium/build/annotations/AlwaysInline.java",
- "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
- "build/android/java/src/org/chromium/build/annotations/DoNotClassMerge.java",
- "build/android/java/src/org/chromium/build/annotations/DoNotInline.java",
- "build/android/java/src/org/chromium/build/annotations/IdentifierNameString.java",
- "build/android/java/src/org/chromium/build/annotations/MainDex.java",
- "build/android/java/src/org/chromium/build/annotations/MockedInTests.java",
- "build/android/java/src/org/chromium/build/annotations/UsedByReflection.java",
- "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/BidirectionalStreamNetworkException.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CallbackExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetBidirectionalStream.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBase.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLibraryLoader.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLogger.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetLoggerFactory.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetManifest.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetMetrics.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUploadDataStream.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java",
- "components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java",
- "components/cronet/android/java/src/org/chromium/net/impl/NativeCronetEngineBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/NetworkExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/NoOpLogger.java",
- "components/cronet/android/java/src/org/chromium/net/impl/Preconditions.java",
- "components/cronet/android/java/src/org/chromium/net/impl/QuicExceptionImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/RequestFinishedInfoImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBase.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UrlRequestBuilderImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java",
- "components/cronet/android/java/src/org/chromium/net/impl/UserAgent.java",
- "components/cronet/android/java/src/org/chromium/net/impl/VersionSafeCallbacks.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetBufferedOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetChunkedOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetFixedModeOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandler.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetInputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetOutputStream.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java",
- "components/cronet/android/java/src/org/chromium/net/urlconnection/MessageLoop.java",
- "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
- "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
- "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
- "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
- "net/android/java/src/org/chromium/net/ChromiumNetworkAdapter.java",
- "net/android/java/src/org/chromium/net/DnsStatus.java",
- "net/android/java/src/org/chromium/net/GURLUtils.java",
- "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
- "net/android/java/src/org/chromium/net/HttpNegotiateConstants.java",
- "net/android/java/src/org/chromium/net/HttpUtil.java",
- "net/android/java/src/org/chromium/net/MimeTypeFilter.java",
- "net/android/java/src/org/chromium/net/NetStringUtil.java",
- "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
- "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
- "net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java",
- "net/android/java/src/org/chromium/net/NetworkTrafficAnnotationTag.java",
- "net/android/java/src/org/chromium/net/ProxyBroadcastReceiver.java",
- "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
- "net/android/java/src/org/chromium/net/RegistrationPolicyAlwaysRegister.java",
- "net/android/java/src/org/chromium/net/RegistrationPolicyApplicationStatus.java",
- "net/android/java/src/org/chromium/net/ThreadStatsUid.java",
- "net/android/java/src/org/chromium/net/X509Util.java",
- "url/android/java/src/org/chromium/url/IDNStringUtil.java",
- ],
- static_libs: [
- "modules-utils-build_system",
- ],
- apex_available: [
- "com.android.tethering",
- ],
- min_sdk_version: "30",
- libs: [
- "androidx.annotation_annotation",
- "androidx.annotation_annotation-experimental-nodeps",
- "cronet_aml_api_java",
- "framework-connectivity-t.stubs.module_lib",
- "framework-connectivity.stubs.module_lib",
- "framework-mediaprovider.stubs.module_lib",
- "framework-tethering.stubs.module_lib",
- "framework-wifi.stubs.module_lib",
- "jsr305",
- ],
- aidl: {
- include_dirs: [
- "frameworks/base/core/java/",
- ],
- local_include_dirs: [
- "base/android/java/src/",
- ],
- },
- plugins: [
- "cronet_aml_java_jni_annotation_preprocessor",
- ],
- sdk_version: "module_current",
- javacflags: [
- "-Aorg.chromium.chrome.skipGenJni",
- "-Apackage_prefix=android.net.http.internal",
- ],
-}
-
-// GN: //base/android/jni_generator:jni_processor
-java_plugin {
- name: "cronet_aml_java_jni_annotation_preprocessor",
- srcs: [
- ":cronet_aml_build_android_build_config_gen",
- "base/android/java/src/org/chromium/base/JniException.java",
- "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
- "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
- "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
- "base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java",
- "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
- "build/android/java/src/org/chromium/build/annotations/MainDex.java",
- ],
- static_libs: [
- "auto_service_annotations",
- "guava",
- "javapoet",
- ],
- processor_class: "org.chromium.jni_generator.JniProcessor",
-}
-
-// GN: //net/android:net_android_java_enums_srcjar
-java_genrule {
- name: "cronet_aml_net_android_net_android_java_enums_srcjar",
- srcs: [
- "net/android/network_change_notifier_android.cc",
- "net/android/traffic_stats.cc",
- "net/socket/socket_tag.cc",
- ],
- cmd: "$(location build/android/gyp/java_cpp_enum.py) --srcjar " +
- "$(out) " +
- "$(location net/base/network_change_notifier.h) " +
- "$(location net/socket/socket_tag.cc) " +
- "$(location net/android/cert_verify_result_android.h) " +
- "$(location net/android/keystore.h) " +
- "$(location net/android/network_change_notifier_android.cc) " +
- "$(location net/android/traffic_stats.cc)",
- out: [
- "net/android/net_android_java_enums_srcjar.srcjar",
- ],
- tool_files: [
- "build/android/gyp/java_cpp_enum.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- "net/android/cert_verify_result_android.h",
- "net/android/keystore.h",
- "net/base/network_change_notifier.h",
- ],
-}
-
-// GN: //net/android:net_errors_java
-genrule {
- name: "cronet_aml_net_android_net_errors_java",
- srcs: [
- ":cronet_aml_net_android_net_errors_java_preprocess",
- ],
- tools: [
- "soong_zip",
- ],
- cmd: "cp $(in) $(genDir)/NetError.java && " +
- "$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/NetError.java",
- out: [
- "NetError.srcjar",
- ],
-}
-
-// GN: //net/android:net_errors_java
-cc_object {
- name: "cronet_aml_net_android_net_errors_java_preprocess",
- srcs: [
- ":cronet_aml_net_android_net_errors_java_rename",
- ],
- cflags: [
- "-DANDROID",
- "-E",
- "-P",
- ],
- compile_multilib: "first",
-}
-
-// GN: //net/android:net_errors_java
-genrule {
- name: "cronet_aml_net_android_net_errors_java_rename",
- srcs: [
- "net/android/java/NetError.template",
- ],
- cmd: "cp $(in) $(out)",
- out: [
- "NetError.cc",
- ],
-}
-
-// GN: //net/base/registry_controlled_domains:registry_controlled_domains
-cc_genrule {
- name: "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
- cmd: "$(location net/tools/dafsa/make_dafsa.py) --reverse " +
- "$(location net/base/registry_controlled_domains/effective_tld_names.gperf) " +
- "$(location net/base/registry_controlled_domains/effective_tld_names-reversed-inc.cc) " +
- "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
- "--reverse " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest1.gperf) " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest1-reversed-inc.cc) " +
- "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
- "--reverse " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest2.gperf) " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest2-reversed-inc.cc) " +
- "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
- "--reverse " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest3.gperf) " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest3-reversed-inc.cc) " +
- "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
- "--reverse " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest4.gperf) " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest4-reversed-inc.cc) " +
- "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
- "--reverse " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest5.gperf) " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest5-reversed-inc.cc) " +
- "&& python3 $(location net/tools/dafsa/make_dafsa.py) " +
- "--reverse " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest6.gperf) " +
- "$(location net/base/registry_controlled_domains/effective_tld_names_unittest6-reversed-inc.cc)",
- out: [
- "net/base/registry_controlled_domains/effective_tld_names-reversed-inc.cc",
- "net/base/registry_controlled_domains/effective_tld_names_unittest1-reversed-inc.cc",
- "net/base/registry_controlled_domains/effective_tld_names_unittest2-reversed-inc.cc",
- "net/base/registry_controlled_domains/effective_tld_names_unittest3-reversed-inc.cc",
- "net/base/registry_controlled_domains/effective_tld_names_unittest4-reversed-inc.cc",
- "net/base/registry_controlled_domains/effective_tld_names_unittest5-reversed-inc.cc",
- "net/base/registry_controlled_domains/effective_tld_names_unittest6-reversed-inc.cc",
- ],
- tool_files: [
- "net/base/registry_controlled_domains/effective_tld_names.gperf",
- "net/base/registry_controlled_domains/effective_tld_names_unittest1.gperf",
- "net/base/registry_controlled_domains/effective_tld_names_unittest2.gperf",
- "net/base/registry_controlled_domains/effective_tld_names_unittest3.gperf",
- "net/base/registry_controlled_domains/effective_tld_names_unittest4.gperf",
- "net/base/registry_controlled_domains/effective_tld_names_unittest5.gperf",
- "net/base/registry_controlled_domains/effective_tld_names_unittest6.gperf",
- "net/tools/dafsa/make_dafsa.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net:buildflags
-cc_genrule {
- name: "cronet_aml_net_buildflags",
- cmd: "if [[ ( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags POSIX_BYPASS_MMAP=\"true\" DISABLE_FILE_SUPPORT=\"true\" ENABLE_MDNS=\"false\" ENABLE_REPORTING=\"true\" ENABLE_WEBSOCKETS=\"false\" INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST=\"false\" USE_KERBEROS=\"true\" USE_EXTERNAL_GSSAPI=\"false\" TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=\"false\" CHROME_ROOT_STORE_SUPPORTED=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//net:buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi; " +
- "if [[ ( $$CC_ARCH == 'x86' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags POSIX_BYPASS_MMAP=\"false\" DISABLE_FILE_SUPPORT=\"true\" ENABLE_MDNS=\"false\" ENABLE_REPORTING=\"true\" ENABLE_WEBSOCKETS=\"false\" INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST=\"false\" USE_KERBEROS=\"true\" USE_EXTERNAL_GSSAPI=\"false\" TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=\"false\" CHROME_ROOT_STORE_SUPPORTED=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//net:buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi; " +
- "if [[ ( $$CC_ARCH == 'arm' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags POSIX_BYPASS_MMAP=\"true\" DISABLE_FILE_SUPPORT=\"true\" ENABLE_MDNS=\"false\" ENABLE_REPORTING=\"true\" ENABLE_WEBSOCKETS=\"false\" INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST=\"false\" USE_KERBEROS=\"true\" USE_EXTERNAL_GSSAPI=\"false\" TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=\"false\" CHROME_ROOT_STORE_SUPPORTED=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//net:buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi; " +
- "if [[ ( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' ) ]]; " +
- "then " +
- "echo '--flags POSIX_BYPASS_MMAP=\"true\" DISABLE_FILE_SUPPORT=\"true\" ENABLE_MDNS=\"false\" ENABLE_REPORTING=\"true\" ENABLE_WEBSOCKETS=\"false\" INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST=\"false\" USE_KERBEROS=\"true\" USE_EXTERNAL_GSSAPI=\"false\" TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=\"false\" CHROME_ROOT_STORE_SUPPORTED=\"false\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//net:buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin; " +
- "fi;",
- out: [
- "net/net_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net/dns:dns
-cc_object {
- name: "cronet_aml_net_dns_dns",
- srcs: [
- "net/dns/address_info.cc",
- "net/dns/address_sorter_posix.cc",
- "net/dns/context_host_resolver.cc",
- "net/dns/dns_alias_utility.cc",
- "net/dns/dns_client.cc",
- "net/dns/dns_config.cc",
- "net/dns/dns_config_service.cc",
- "net/dns/dns_config_service_android.cc",
- "net/dns/dns_hosts.cc",
- "net/dns/dns_query.cc",
- "net/dns/dns_reloader.cc",
- "net/dns/dns_response.cc",
- "net/dns/dns_response_result_extractor.cc",
- "net/dns/dns_server_iterator.cc",
- "net/dns/dns_session.cc",
- "net/dns/dns_transaction.cc",
- "net/dns/dns_udp_tracker.cc",
- "net/dns/dns_util.cc",
- "net/dns/host_cache.cc",
- "net/dns/host_resolver.cc",
- "net/dns/host_resolver_manager.cc",
- "net/dns/host_resolver_mdns_listener_impl.cc",
- "net/dns/host_resolver_mdns_task.cc",
- "net/dns/host_resolver_nat64_task.cc",
- "net/dns/host_resolver_proc.cc",
- "net/dns/host_resolver_system_task.cc",
- "net/dns/https_record_rdata.cc",
- "net/dns/httpssvc_metrics.cc",
- "net/dns/mapped_host_resolver.cc",
- "net/dns/nsswitch_reader.cc",
- "net/dns/opt_record_rdata.cc",
- "net/dns/record_parsed.cc",
- "net/dns/record_rdata.cc",
- "net/dns/resolve_context.cc",
- "net/dns/serial_worker.cc",
- "net/dns/system_dns_config_change_notifier.cc",
- "net/dns/test_dns_config_service.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_crypto_crypto",
- "cronet_aml_net_preload_decoder",
- "cronet_aml_net_third_party_quiche_quiche",
- "cronet_aml_net_uri_template",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_brotli_common",
- "cronet_aml_third_party_brotli_dec",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- "cronet_aml_url_url",
- ],
- generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
- "cronet_aml_net_buildflags",
- "cronet_aml_net_isolation_info_proto_gen_headers",
- "cronet_aml_net_net_jni_headers",
- "cronet_aml_net_net_nqe_proto_gen_headers",
- "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
- "cronet_aml_url_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DENABLE_BUILT_IN_DNS",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNET_IMPLEMENTATION",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "net/third_party/quiche/overrides/",
- "net/third_party/quiche/src/",
- "net/third_party/quiche/src/quiche/common/platform/default/",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/brotli/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //net/dns/public:public
-cc_object {
- name: "cronet_aml_net_dns_public_public",
- srcs: [
- "net/dns/public/dns_config_overrides.cc",
- "net/dns/public/dns_over_https_config.cc",
- "net/dns/public/dns_over_https_server_config.cc",
- "net/dns/public/dns_query_type.cc",
- "net/dns/public/doh_provider_entry.cc",
- "net/dns/public/host_resolver_results.cc",
- "net/dns/public/resolve_error_info.cc",
- "net/dns/public/util.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_crypto_crypto",
- "cronet_aml_net_preload_decoder",
- "cronet_aml_net_third_party_quiche_quiche",
- "cronet_aml_net_uri_template",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_brotli_common",
- "cronet_aml_third_party_brotli_dec",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- "cronet_aml_url_url",
- ],
- generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
- "cronet_aml_net_buildflags",
- "cronet_aml_net_isolation_info_proto_gen_headers",
- "cronet_aml_net_net_jni_headers",
- "cronet_aml_net_net_nqe_proto_gen_headers",
- "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
- "cronet_aml_url_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DENABLE_BUILT_IN_DNS",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNET_IMPLEMENTATION",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "net/third_party/quiche/overrides/",
- "net/third_party/quiche/src/",
- "net/third_party/quiche/src/quiche/common/platform/default/",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/brotli/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //net:effective_connection_type_java
-java_genrule {
- name: "cronet_aml_net_effective_connection_type_java",
- cmd: "$(location build/android/gyp/java_cpp_enum.py) --srcjar " +
- "$(out) " +
- "$(location net/nqe/effective_connection_type.h)",
- out: [
- "net/effective_connection_type_java.srcjar",
- ],
- tool_files: [
- "build/android/gyp/java_cpp_enum.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/android/gyp/util/java_cpp_utils.py",
- "build/gn_helpers.py",
- "net/nqe/effective_connection_type.h",
- ],
-}
-
-// GN: //net/http:transport_security_state_generated_files
-cc_object {
- name: "cronet_aml_net_http_transport_security_state_generated_files",
- srcs: [
- "net/http/transport_security_state.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_crypto_crypto",
- "cronet_aml_net_preload_decoder",
- "cronet_aml_net_third_party_quiche_quiche",
- "cronet_aml_net_uri_template",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_brotli_common",
- "cronet_aml_third_party_brotli_dec",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- "cronet_aml_url_url",
- ],
- generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_branding_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
- "cronet_aml_net_buildflags",
- "cronet_aml_net_isolation_info_proto_gen_headers",
- "cronet_aml_net_net_jni_headers",
- "cronet_aml_net_net_nqe_proto_gen_headers",
- "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
- "cronet_aml_url_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DENABLE_BUILT_IN_DNS",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNET_IMPLEMENTATION",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "net/third_party/quiche/overrides/",
- "net/third_party/quiche/src/",
- "net/third_party/quiche/src/quiche/common/platform/default/",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/brotli/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //net:ios_cronet_buildflags
-cc_genrule {
- name: "cronet_aml_net_ios_cronet_buildflags",
- cmd: "echo '--flags CRONET_BUILD=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//net:ios_cronet_buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "net/socket/ios_cronet_buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net:isolation_info_proto
-cc_genrule {
- name: "cronet_aml_net_isolation_info_proto_gen",
- srcs: [
- "net/base/isolation_info.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/base --cpp_out=lite=true:$(genDir)/external/cronet/net/base/ $(in)",
- out: [
- "external/cronet/net/base/isolation_info.pb.cc",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net:isolation_info_proto
-cc_genrule {
- name: "cronet_aml_net_isolation_info_proto_gen_headers",
- srcs: [
- "net/base/isolation_info.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/base --cpp_out=lite=true:$(genDir)/external/cronet/net/base/ $(in)",
- out: [
- "external/cronet/net/base/isolation_info.pb.h",
- ],
- export_include_dirs: [
- ".",
- "net/base",
- "protos",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net:net
-cc_library_static {
- name: "cronet_aml_net_net",
- srcs: [
- ":cronet_aml_net_dns_dns",
- ":cronet_aml_net_dns_public_public",
- ":cronet_aml_net_http_transport_security_state_generated_files",
- ":cronet_aml_net_net_deps",
- ":cronet_aml_net_net_public_deps",
- ":cronet_aml_net_traffic_annotation_traffic_annotation",
- "net/android/android_http_util.cc",
- "net/android/cert_verify_result_android.cc",
- "net/android/gurl_utils.cc",
- "net/android/http_auth_negotiate_android.cc",
- "net/android/keystore.cc",
- "net/android/network_change_notifier_android.cc",
- "net/android/network_change_notifier_delegate_android.cc",
- "net/android/network_change_notifier_factory_android.cc",
- "net/android/network_library.cc",
- "net/android/radio_activity_tracker.cc",
- "net/android/traffic_stats.cc",
- "net/base/address_family.cc",
- "net/base/address_list.cc",
- "net/base/address_tracker_linux.cc",
- "net/base/auth.cc",
- "net/base/backoff_entry.cc",
- "net/base/backoff_entry_serializer.cc",
- "net/base/cache_metrics.cc",
- "net/base/chunked_upload_data_stream.cc",
- "net/base/connection_endpoint_metadata.cc",
- "net/base/data_url.cc",
- "net/base/datagram_buffer.cc",
- "net/base/elements_upload_data_stream.cc",
- "net/base/features.cc",
- "net/base/file_stream.cc",
- "net/base/file_stream_context.cc",
- "net/base/file_stream_context_posix.cc",
- "net/base/filename_util.cc",
- "net/base/filename_util_internal.cc",
- "net/base/hash_value.cc",
- "net/base/hex_utils.cc",
- "net/base/host_mapping_rules.cc",
- "net/base/host_port_pair.cc",
- "net/base/io_buffer.cc",
- "net/base/ip_address.cc",
- "net/base/ip_endpoint.cc",
- "net/base/isolation_info.cc",
- "net/base/load_timing_info.cc",
- "net/base/logging_network_change_observer.cc",
- "net/base/lookup_string_in_fixed_set.cc",
- "net/base/mime_sniffer.cc",
- "net/base/mime_util.cc",
- "net/base/net_errors.cc",
- "net/base/net_errors_posix.cc",
- "net/base/net_module.cc",
- "net/base/net_string_util_icu_alternatives_android.cc",
- "net/base/network_activity_monitor.cc",
- "net/base/network_anonymization_key.cc",
- "net/base/network_change_notifier.cc",
- "net/base/network_change_notifier_posix.cc",
- "net/base/network_delegate.cc",
- "net/base/network_delegate_impl.cc",
- "net/base/network_interfaces.cc",
- "net/base/network_interfaces_getifaddrs.cc",
- "net/base/network_interfaces_getifaddrs_android.cc",
- "net/base/network_interfaces_linux.cc",
- "net/base/network_interfaces_posix.cc",
- "net/base/network_isolation_key.cc",
- "net/base/parse_number.cc",
- "net/base/platform_mime_util_linux.cc",
- "net/base/port_util.cc",
- "net/base/prioritized_dispatcher.cc",
- "net/base/prioritized_task_runner.cc",
- "net/base/privacy_mode.cc",
- "net/base/proxy_server.cc",
- "net/base/proxy_string_util.cc",
- "net/base/registry_controlled_domains/registry_controlled_domain.cc",
- "net/base/request_priority.cc",
- "net/base/scheme_host_port_matcher.cc",
- "net/base/scheme_host_port_matcher_rule.cc",
- "net/base/schemeful_site.cc",
- "net/base/sockaddr_storage.cc",
- "net/base/sockaddr_util_posix.cc",
- "net/base/transport_info.cc",
- "net/base/upload_bytes_element_reader.cc",
- "net/base/upload_data_stream.cc",
- "net/base/upload_element_reader.cc",
- "net/base/upload_file_element_reader.cc",
- "net/base/url_util.cc",
- "net/cert/asn1_util.cc",
- "net/cert/caching_cert_verifier.cc",
- "net/cert/cert_and_ct_verifier.cc",
- "net/cert/cert_database.cc",
- "net/cert/cert_status_flags.cc",
- "net/cert/cert_verifier.cc",
- "net/cert/cert_verify_proc.cc",
- "net/cert/cert_verify_proc_android.cc",
- "net/cert/cert_verify_proc_builtin.cc",
- "net/cert/cert_verify_result.cc",
- "net/cert/coalescing_cert_verifier.cc",
- "net/cert/crl_set.cc",
- "net/cert/ct_log_response_parser.cc",
- "net/cert/ct_log_verifier.cc",
- "net/cert/ct_log_verifier_util.cc",
- "net/cert/ct_objects_extractor.cc",
- "net/cert/ct_policy_enforcer.cc",
- "net/cert/ct_sct_to_string.cc",
- "net/cert/ct_serialization.cc",
- "net/cert/ct_signed_certificate_timestamp_log_param.cc",
- "net/cert/do_nothing_ct_verifier.cc",
- "net/cert/ev_root_ca_metadata.cc",
- "net/cert/internal/cert_issuer_source_aia.cc",
- "net/cert/internal/revocation_checker.cc",
- "net/cert/internal/system_trust_store.cc",
- "net/cert/known_roots.cc",
- "net/cert/merkle_audit_proof.cc",
- "net/cert/merkle_consistency_proof.cc",
- "net/cert/merkle_tree_leaf.cc",
- "net/cert/multi_log_ct_verifier.cc",
- "net/cert/multi_threaded_cert_verifier.cc",
- "net/cert/ocsp_verify_result.cc",
- "net/cert/pem.cc",
- "net/cert/pki/cert_error_id.cc",
- "net/cert/pki/cert_error_params.cc",
- "net/cert/pki/cert_errors.cc",
- "net/cert/pki/cert_issuer_source_static.cc",
- "net/cert/pki/certificate_policies.cc",
- "net/cert/pki/common_cert_errors.cc",
- "net/cert/pki/crl.cc",
- "net/cert/pki/extended_key_usage.cc",
- "net/cert/pki/general_names.cc",
- "net/cert/pki/name_constraints.cc",
- "net/cert/pki/ocsp.cc",
- "net/cert/pki/parse_certificate.cc",
- "net/cert/pki/parse_name.cc",
- "net/cert/pki/parsed_certificate.cc",
- "net/cert/pki/path_builder.cc",
- "net/cert/pki/revocation_util.cc",
- "net/cert/pki/signature_algorithm.cc",
- "net/cert/pki/simple_path_builder_delegate.cc",
- "net/cert/pki/string_util.cc",
- "net/cert/pki/trust_store.cc",
- "net/cert/pki/trust_store_collection.cc",
- "net/cert/pki/trust_store_in_memory.cc",
- "net/cert/pki/verify_certificate_chain.cc",
- "net/cert/pki/verify_name_match.cc",
- "net/cert/pki/verify_signed_data.cc",
- "net/cert/sct_status_flags.cc",
- "net/cert/signed_certificate_timestamp.cc",
- "net/cert/signed_certificate_timestamp_and_status.cc",
- "net/cert/signed_tree_head.cc",
- "net/cert/symantec_certs.cc",
- "net/cert/test_root_certs.cc",
- "net/cert/test_root_certs_android.cc",
- "net/cert/trial_comparison_cert_verifier_util.cc",
- "net/cert/x509_cert_types.cc",
- "net/cert/x509_certificate.cc",
- "net/cert/x509_certificate_net_log_param.cc",
- "net/cert/x509_util.cc",
- "net/cert/x509_util_android.cc",
- "net/cert_net/cert_net_fetcher_url_request.cc",
- "net/cookies/canonical_cookie.cc",
- "net/cookies/cookie_access_delegate.cc",
- "net/cookies/cookie_access_result.cc",
- "net/cookies/cookie_change_dispatcher.cc",
- "net/cookies/cookie_constants.cc",
- "net/cookies/cookie_deletion_info.cc",
- "net/cookies/cookie_inclusion_status.cc",
- "net/cookies/cookie_monster.cc",
- "net/cookies/cookie_monster_change_dispatcher.cc",
- "net/cookies/cookie_monster_netlog_params.cc",
- "net/cookies/cookie_options.cc",
- "net/cookies/cookie_partition_key.cc",
- "net/cookies/cookie_partition_key_collection.cc",
- "net/cookies/cookie_store.cc",
- "net/cookies/cookie_util.cc",
- "net/cookies/parsed_cookie.cc",
- "net/cookies/site_for_cookies.cc",
- "net/cookies/static_cookie_policy.cc",
- "net/der/encode_values.cc",
- "net/der/input.cc",
- "net/der/parse_values.cc",
- "net/der/parser.cc",
- "net/der/tag.cc",
- "net/disk_cache/backend_cleanup_tracker.cc",
- "net/disk_cache/blockfile/addr.cc",
- "net/disk_cache/blockfile/backend_impl.cc",
- "net/disk_cache/blockfile/bitmap.cc",
- "net/disk_cache/blockfile/block_files.cc",
- "net/disk_cache/blockfile/disk_format.cc",
- "net/disk_cache/blockfile/entry_impl.cc",
- "net/disk_cache/blockfile/eviction.cc",
- "net/disk_cache/blockfile/file.cc",
- "net/disk_cache/blockfile/file_lock.cc",
- "net/disk_cache/blockfile/file_posix.cc",
- "net/disk_cache/blockfile/in_flight_backend_io.cc",
- "net/disk_cache/blockfile/in_flight_io.cc",
- "net/disk_cache/blockfile/mapped_file.cc",
- "net/disk_cache/blockfile/rankings.cc",
- "net/disk_cache/blockfile/sparse_control.cc",
- "net/disk_cache/blockfile/stats.cc",
- "net/disk_cache/cache_util.cc",
- "net/disk_cache/cache_util_posix.cc",
- "net/disk_cache/disk_cache.cc",
- "net/disk_cache/memory/mem_backend_impl.cc",
- "net/disk_cache/memory/mem_entry_impl.cc",
- "net/disk_cache/net_log_parameters.cc",
- "net/disk_cache/simple/post_doom_waiter.cc",
- "net/disk_cache/simple/simple_backend_impl.cc",
- "net/disk_cache/simple/simple_entry_format.cc",
- "net/disk_cache/simple/simple_entry_impl.cc",
- "net/disk_cache/simple/simple_entry_operation.cc",
- "net/disk_cache/simple/simple_file_enumerator.cc",
- "net/disk_cache/simple/simple_file_tracker.cc",
- "net/disk_cache/simple/simple_index.cc",
- "net/disk_cache/simple/simple_index_file.cc",
- "net/disk_cache/simple/simple_net_log_parameters.cc",
- "net/disk_cache/simple/simple_synchronous_entry.cc",
- "net/disk_cache/simple/simple_util.cc",
- "net/disk_cache/simple/simple_util_posix.cc",
- "net/disk_cache/simple/simple_version_upgrade.cc",
- "net/filter/brotli_source_stream.cc",
- "net/filter/filter_source_stream.cc",
- "net/filter/gzip_header.cc",
- "net/filter/gzip_source_stream.cc",
- "net/filter/source_stream.cc",
- "net/first_party_sets/addition_overlaps_union_find.cc",
- "net/first_party_sets/first_party_set_entry.cc",
- "net/first_party_sets/first_party_set_metadata.cc",
- "net/first_party_sets/first_party_sets_cache_filter.cc",
- "net/first_party_sets/first_party_sets_context_config.cc",
- "net/first_party_sets/global_first_party_sets.cc",
- "net/first_party_sets/same_party_context.cc",
- "net/http/alternative_service.cc",
- "net/http/bidirectional_stream.cc",
- "net/http/bidirectional_stream_impl.cc",
- "net/http/bidirectional_stream_request_info.cc",
- "net/http/broken_alternative_services.cc",
- "net/http/http_auth.cc",
- "net/http/http_auth_cache.cc",
- "net/http/http_auth_challenge_tokenizer.cc",
- "net/http/http_auth_controller.cc",
- "net/http/http_auth_filter.cc",
- "net/http/http_auth_handler.cc",
- "net/http/http_auth_handler_basic.cc",
- "net/http/http_auth_handler_digest.cc",
- "net/http/http_auth_handler_factory.cc",
- "net/http/http_auth_handler_negotiate.cc",
- "net/http/http_auth_handler_ntlm.cc",
- "net/http/http_auth_handler_ntlm_portable.cc",
- "net/http/http_auth_multi_round_parse.cc",
- "net/http/http_auth_ntlm_mechanism.cc",
- "net/http/http_auth_preferences.cc",
- "net/http/http_auth_scheme.cc",
- "net/http/http_basic_state.cc",
- "net/http/http_basic_stream.cc",
- "net/http/http_byte_range.cc",
- "net/http/http_cache.cc",
- "net/http/http_cache_lookup_manager.cc",
- "net/http/http_cache_transaction.cc",
- "net/http/http_cache_writers.cc",
- "net/http/http_chunked_decoder.cc",
- "net/http/http_content_disposition.cc",
- "net/http/http_log_util.cc",
- "net/http/http_network_layer.cc",
- "net/http/http_network_session.cc",
- "net/http/http_network_session_peer.cc",
- "net/http/http_network_transaction.cc",
- "net/http/http_proxy_client_socket.cc",
- "net/http/http_proxy_connect_job.cc",
- "net/http/http_raw_request_headers.cc",
- "net/http/http_request_headers.cc",
- "net/http/http_request_info.cc",
- "net/http/http_response_body_drainer.cc",
- "net/http/http_response_headers.cc",
- "net/http/http_response_info.cc",
- "net/http/http_security_headers.cc",
- "net/http/http_server_properties.cc",
- "net/http/http_server_properties_manager.cc",
- "net/http/http_status_code.cc",
- "net/http/http_stream_factory.cc",
- "net/http/http_stream_factory_job.cc",
- "net/http/http_stream_factory_job_controller.cc",
- "net/http/http_stream_parser.cc",
- "net/http/http_stream_request.cc",
- "net/http/http_util.cc",
- "net/http/http_vary_data.cc",
- "net/http/partial_data.cc",
- "net/http/proxy_client_socket.cc",
- "net/http/proxy_fallback.cc",
- "net/http/transport_security_persister.cc",
- "net/http/transport_security_state_source.cc",
- "net/http/url_security_manager.cc",
- "net/http/url_security_manager_posix.cc",
- "net/http/webfonts_histogram.cc",
- "net/log/file_net_log_observer.cc",
- "net/log/net_log.cc",
- "net/log/net_log_capture_mode.cc",
- "net/log/net_log_entry.cc",
- "net/log/net_log_event_type.cc",
- "net/log/net_log_source.cc",
- "net/log/net_log_util.cc",
- "net/log/net_log_values.cc",
- "net/log/net_log_with_source.cc",
- "net/log/trace_net_log_observer.cc",
- "net/network_error_logging/network_error_logging_service.cc",
- "net/nqe/cached_network_quality.cc",
- "net/nqe/effective_connection_type.cc",
- "net/nqe/event_creator.cc",
- "net/nqe/network_id.cc",
- "net/nqe/network_qualities_prefs_manager.cc",
- "net/nqe/network_quality.cc",
- "net/nqe/network_quality_estimator.cc",
- "net/nqe/network_quality_estimator_params.cc",
- "net/nqe/network_quality_estimator_util.cc",
- "net/nqe/network_quality_observation.cc",
- "net/nqe/network_quality_store.cc",
- "net/nqe/observation_buffer.cc",
- "net/nqe/pref_names.cc",
- "net/nqe/socket_watcher.cc",
- "net/nqe/socket_watcher_factory.cc",
- "net/nqe/throughput_analyzer.cc",
- "net/ntlm/ntlm.cc",
- "net/ntlm/ntlm_buffer_reader.cc",
- "net/ntlm/ntlm_buffer_writer.cc",
- "net/ntlm/ntlm_client.cc",
- "net/ntlm/ntlm_constants.cc",
- "net/proxy_resolution/configured_proxy_resolution_request.cc",
- "net/proxy_resolution/configured_proxy_resolution_service.cc",
- "net/proxy_resolution/dhcp_pac_file_fetcher.cc",
- "net/proxy_resolution/multi_threaded_proxy_resolver.cc",
- "net/proxy_resolution/network_delegate_error_observer.cc",
- "net/proxy_resolution/pac_file_data.cc",
- "net/proxy_resolution/pac_file_decider.cc",
- "net/proxy_resolution/pac_file_fetcher.cc",
- "net/proxy_resolution/pac_file_fetcher_impl.cc",
- "net/proxy_resolution/polling_proxy_config_service.cc",
- "net/proxy_resolution/proxy_bypass_rules.cc",
- "net/proxy_resolution/proxy_config.cc",
- "net/proxy_resolution/proxy_config_service.cc",
- "net/proxy_resolution/proxy_config_service_android.cc",
- "net/proxy_resolution/proxy_config_service_fixed.cc",
- "net/proxy_resolution/proxy_config_with_annotation.cc",
- "net/proxy_resolution/proxy_info.cc",
- "net/proxy_resolution/proxy_list.cc",
- "net/proxy_resolution/proxy_resolver_factory.cc",
- "net/quic/bidirectional_stream_quic_impl.cc",
- "net/quic/crypto/proof_source_chromium.cc",
- "net/quic/crypto/proof_verifier_chromium.cc",
- "net/quic/dedicated_web_transport_http3_client.cc",
- "net/quic/network_connection.cc",
- "net/quic/platform/impl/quic_chromium_clock.cc",
- "net/quic/properties_based_quic_server_info.cc",
- "net/quic/quic_address_mismatch.cc",
- "net/quic/quic_chromium_alarm_factory.cc",
- "net/quic/quic_chromium_client_session.cc",
- "net/quic/quic_chromium_client_stream.cc",
- "net/quic/quic_chromium_connection_helper.cc",
- "net/quic/quic_chromium_packet_reader.cc",
- "net/quic/quic_chromium_packet_writer.cc",
- "net/quic/quic_clock_skew_detector.cc",
- "net/quic/quic_connection_logger.cc",
- "net/quic/quic_connectivity_monitor.cc",
- "net/quic/quic_context.cc",
- "net/quic/quic_crypto_client_config_handle.cc",
- "net/quic/quic_crypto_client_stream_factory.cc",
- "net/quic/quic_event_logger.cc",
- "net/quic/quic_http3_logger.cc",
- "net/quic/quic_http_stream.cc",
- "net/quic/quic_http_utils.cc",
- "net/quic/quic_proxy_client_socket.cc",
- "net/quic/quic_server_info.cc",
- "net/quic/quic_session_key.cc",
- "net/quic/quic_stream_factory.cc",
- "net/quic/set_quic_flag.cc",
- "net/quic/web_transport_client.cc",
- "net/quic/web_transport_error.cc",
- "net/reporting/reporting_browsing_data_remover.cc",
- "net/reporting/reporting_cache.cc",
- "net/reporting/reporting_cache_impl.cc",
- "net/reporting/reporting_cache_observer.cc",
- "net/reporting/reporting_context.cc",
- "net/reporting/reporting_delegate.cc",
- "net/reporting/reporting_delivery_agent.cc",
- "net/reporting/reporting_endpoint.cc",
- "net/reporting/reporting_endpoint_manager.cc",
- "net/reporting/reporting_garbage_collector.cc",
- "net/reporting/reporting_header_parser.cc",
- "net/reporting/reporting_network_change_observer.cc",
- "net/reporting/reporting_policy.cc",
- "net/reporting/reporting_report.cc",
- "net/reporting/reporting_service.cc",
- "net/reporting/reporting_uploader.cc",
- "net/socket/client_socket_factory.cc",
- "net/socket/client_socket_handle.cc",
- "net/socket/client_socket_pool.cc",
- "net/socket/client_socket_pool_manager.cc",
- "net/socket/client_socket_pool_manager_impl.cc",
- "net/socket/connect_job.cc",
- "net/socket/connect_job_factory.cc",
- "net/socket/network_binding_client_socket_factory.cc",
- "net/socket/next_proto.cc",
- "net/socket/server_socket.cc",
- "net/socket/socket.cc",
- "net/socket/socket_bio_adapter.cc",
- "net/socket/socket_descriptor.cc",
- "net/socket/socket_net_log_params.cc",
- "net/socket/socket_options.cc",
- "net/socket/socket_posix.cc",
- "net/socket/socket_tag.cc",
- "net/socket/socks5_client_socket.cc",
- "net/socket/socks_client_socket.cc",
- "net/socket/socks_connect_job.cc",
- "net/socket/ssl_client_socket.cc",
- "net/socket/ssl_client_socket_impl.cc",
- "net/socket/ssl_connect_job.cc",
- "net/socket/ssl_server_socket_impl.cc",
- "net/socket/stream_socket.cc",
- "net/socket/tcp_client_socket.cc",
- "net/socket/tcp_server_socket.cc",
- "net/socket/tcp_socket_posix.cc",
- "net/socket/transport_client_socket.cc",
- "net/socket/transport_client_socket_pool.cc",
- "net/socket/transport_connect_job.cc",
- "net/socket/transport_connect_sub_job.cc",
- "net/socket/udp_client_socket.cc",
- "net/socket/udp_net_log_parameters.cc",
- "net/socket/udp_server_socket.cc",
- "net/socket/udp_socket_global_limits.cc",
- "net/socket/udp_socket_posix.cc",
- "net/socket/unix_domain_client_socket_posix.cc",
- "net/socket/unix_domain_server_socket_posix.cc",
- "net/socket/websocket_endpoint_lock_manager.cc",
- "net/socket/websocket_transport_client_socket_pool.cc",
- "net/spdy/alps_decoder.cc",
- "net/spdy/bidirectional_stream_spdy_impl.cc",
- "net/spdy/buffered_spdy_framer.cc",
- "net/spdy/header_coalescer.cc",
- "net/spdy/http2_priority_dependencies.cc",
- "net/spdy/http2_push_promise_index.cc",
- "net/spdy/multiplexed_http_stream.cc",
- "net/spdy/multiplexed_session.cc",
- "net/spdy/spdy_buffer.cc",
- "net/spdy/spdy_buffer_producer.cc",
- "net/spdy/spdy_http_stream.cc",
- "net/spdy/spdy_http_utils.cc",
- "net/spdy/spdy_log_util.cc",
- "net/spdy/spdy_proxy_client_socket.cc",
- "net/spdy/spdy_read_queue.cc",
- "net/spdy/spdy_session.cc",
- "net/spdy/spdy_session_key.cc",
- "net/spdy/spdy_session_pool.cc",
- "net/spdy/spdy_stream.cc",
- "net/spdy/spdy_write_queue.cc",
- "net/ssl/cert_compression.cc",
- "net/ssl/client_cert_identity.cc",
- "net/ssl/openssl_ssl_util.cc",
- "net/ssl/ssl_cert_request_info.cc",
- "net/ssl/ssl_cipher_suite_names.cc",
- "net/ssl/ssl_client_auth_cache.cc",
- "net/ssl/ssl_client_session_cache.cc",
- "net/ssl/ssl_config.cc",
- "net/ssl/ssl_config_service.cc",
- "net/ssl/ssl_config_service_defaults.cc",
- "net/ssl/ssl_info.cc",
- "net/ssl/ssl_key_logger.cc",
- "net/ssl/ssl_key_logger_impl.cc",
- "net/ssl/ssl_platform_key_android.cc",
- "net/ssl/ssl_platform_key_util.cc",
- "net/ssl/ssl_private_key.cc",
- "net/ssl/ssl_server_config.cc",
- "net/ssl/threaded_ssl_private_key.cc",
- "net/url_request/redirect_info.cc",
- "net/url_request/redirect_util.cc",
- "net/url_request/report_sender.cc",
- "net/url_request/static_http_user_agent_settings.cc",
- "net/url_request/url_request.cc",
- "net/url_request/url_request_context.cc",
- "net/url_request/url_request_context_builder.cc",
- "net/url_request/url_request_context_getter.cc",
- "net/url_request/url_request_error_job.cc",
- "net/url_request/url_request_filter.cc",
- "net/url_request/url_request_http_job.cc",
- "net/url_request/url_request_interceptor.cc",
- "net/url_request/url_request_job.cc",
- "net/url_request/url_request_job_factory.cc",
- "net/url_request/url_request_netlog_params.cc",
- "net/url_request/url_request_redirect_job.cc",
- "net/url_request/url_request_throttler_entry.cc",
- "net/url_request/url_request_throttler_manager.cc",
- "net/url_request/view_cache_helper.cc",
- "net/url_request/websocket_handshake_userdata_key.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_crypto_crypto",
- "cronet_aml_net_preload_decoder",
- "cronet_aml_net_third_party_quiche_quiche",
- "cronet_aml_net_uri_template",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_brotli_common",
- "cronet_aml_third_party_brotli_dec",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- "cronet_aml_url_url",
- ],
- generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_branding_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
- "cronet_aml_net_buildflags",
- "cronet_aml_net_ios_cronet_buildflags",
- "cronet_aml_net_isolation_info_proto_gen_headers",
- "cronet_aml_net_net_jni_headers",
- "cronet_aml_net_net_nqe_proto_gen_headers",
- "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
- "cronet_aml_url_buildflags",
- ],
- export_generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_branding_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
- "cronet_aml_net_buildflags",
- "cronet_aml_net_ios_cronet_buildflags",
- "cronet_aml_net_isolation_info_proto_gen_headers",
- "cronet_aml_net_net_jni_headers",
- "cronet_aml_net_net_nqe_proto_gen_headers",
- "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
- "cronet_aml_url_buildflags",
- ],
- export_static_lib_headers: [
- "cronet_aml_crypto_crypto",
- "cronet_aml_net_third_party_quiche_quiche",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DENABLE_BUILT_IN_DNS",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNET_IMPLEMENTATION",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "net/third_party/quiche/overrides/",
- "net/third_party/quiche/src/",
- "net/third_party/quiche/src/quiche/common/platform/default/",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/brotli/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_arm: {
- srcs: [
- "net/disk_cache/blockfile/mapped_file_bypass_mmap_posix.cc",
- ],
- },
- android_arm64: {
- srcs: [
- "net/disk_cache/blockfile/mapped_file_bypass_mmap_posix.cc",
- ],
- },
- android_x86: {
- srcs: [
- "net/disk_cache/blockfile/mapped_file_posix.cc",
- ],
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- srcs: [
- "net/disk_cache/blockfile/mapped_file_bypass_mmap_posix.cc",
- ],
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //net:net_deps
-cc_object {
- name: "cronet_aml_net_net_deps",
- srcs: [
- ":cronet_aml_net_isolation_info_proto_gen",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libprotobuf-cpp-lite",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_net_preload_decoder",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_brotli_common",
- "cronet_aml_third_party_brotli_dec",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- ],
- generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_net_base_registry_controlled_domains_registry_controlled_domains",
- "cronet_aml_net_isolation_info_proto_gen_headers",
- "cronet_aml_net_net_jni_headers",
- "cronet_aml_url_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DENABLE_BUILT_IN_DNS",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNET_IMPLEMENTATION",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/brotli/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //net:net_jni_headers
-cc_genrule {
- name: "cronet_aml_net_net_jni_headers",
- srcs: [
- "net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java",
- "net/android/java/src/org/chromium/net/AndroidKeyStore.java",
- "net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java",
- "net/android/java/src/org/chromium/net/AndroidTrafficStats.java",
- "net/android/java/src/org/chromium/net/DnsStatus.java",
- "net/android/java/src/org/chromium/net/GURLUtils.java",
- "net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java",
- "net/android/java/src/org/chromium/net/HttpUtil.java",
- "net/android/java/src/org/chromium/net/NetStringUtil.java",
- "net/android/java/src/org/chromium/net/NetworkActiveNotifier.java",
- "net/android/java/src/org/chromium/net/NetworkChangeNotifier.java",
- "net/android/java/src/org/chromium/net/ProxyChangeListener.java",
- "net/android/java/src/org/chromium/net/X509Util.java",
- ],
- cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
- "long " +
- "--output_dir " +
- "$(genDir)/net/net_jni_headers " +
- "--includes " +
- "base/android/jni_generator/jni_generator_helper.h " +
- "--use_proxy_hash " +
- "--output_name " +
- "AndroidCertVerifyResult_jni.h " +
- "--output_name " +
- "AndroidKeyStore_jni.h " +
- "--output_name " +
- "AndroidNetworkLibrary_jni.h " +
- "--output_name " +
- "AndroidTrafficStats_jni.h " +
- "--output_name " +
- "DnsStatus_jni.h " +
- "--output_name " +
- "GURLUtils_jni.h " +
- "--output_name " +
- "HttpNegotiateAuthenticator_jni.h " +
- "--output_name " +
- "HttpUtil_jni.h " +
- "--output_name " +
- "NetStringUtil_jni.h " +
- "--output_name " +
- "NetworkActiveNotifier_jni.h " +
- "--output_name " +
- "NetworkChangeNotifier_jni.h " +
- "--output_name " +
- "ProxyChangeListener_jni.h " +
- "--output_name " +
- "X509Util_jni.h " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/AndroidKeyStore.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/AndroidTrafficStats.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/DnsStatus.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/GURLUtils.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/HttpNegotiateAuthenticator.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/HttpUtil.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/NetStringUtil.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/NetworkActiveNotifier.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/NetworkChangeNotifier.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/ProxyChangeListener.java) " +
- "--input_file " +
- "$(location net/android/java/src/org/chromium/net/X509Util.java) " +
- "--package_prefix " +
- "android.net.http.internal",
- out: [
- "net/net_jni_headers/AndroidCertVerifyResult_jni.h",
- "net/net_jni_headers/AndroidKeyStore_jni.h",
- "net/net_jni_headers/AndroidNetworkLibrary_jni.h",
- "net/net_jni_headers/AndroidTrafficStats_jni.h",
- "net/net_jni_headers/DnsStatus_jni.h",
- "net/net_jni_headers/GURLUtils_jni.h",
- "net/net_jni_headers/HttpNegotiateAuthenticator_jni.h",
- "net/net_jni_headers/HttpUtil_jni.h",
- "net/net_jni_headers/NetStringUtil_jni.h",
- "net/net_jni_headers/NetworkActiveNotifier_jni.h",
- "net/net_jni_headers/NetworkChangeNotifier_jni.h",
- "net/net_jni_headers/ProxyChangeListener_jni.h",
- "net/net_jni_headers/X509Util_jni.h",
- ],
- tool_files: [
- "base/android/jni_generator/android_jar.classes",
- "base/android/jni_generator/jni_generator.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/gn_helpers.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net:net_nqe_proto
-cc_genrule {
- name: "cronet_aml_net_net_nqe_proto_gen",
- srcs: [
- "net/nqe/proto/network_id_proto.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/nqe/proto --cpp_out=lite=true:$(genDir)/external/cronet/net/nqe/proto/ $(in)",
- out: [
- "external/cronet/net/nqe/proto/network_id_proto.pb.cc",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net:net_nqe_proto
-cc_genrule {
- name: "cronet_aml_net_net_nqe_proto_gen_headers",
- srcs: [
- "net/nqe/proto/network_id_proto.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/nqe/proto --cpp_out=lite=true:$(genDir)/external/cronet/net/nqe/proto/ $(in)",
- out: [
- "external/cronet/net/nqe/proto/network_id_proto.pb.h",
- ],
- export_include_dirs: [
- ".",
- "net/nqe/proto",
- "protos",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net:net_public_deps
-cc_object {
- name: "cronet_aml_net_net_public_deps",
- srcs: [
- ":cronet_aml_net_net_nqe_proto_gen",
- ":cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libprotobuf-cpp-lite",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_crypto_crypto",
- "cronet_aml_net_third_party_quiche_quiche",
- "cronet_aml_net_uri_template",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- "cronet_aml_url_url",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_net_buildflags",
- "cronet_aml_net_net_nqe_proto_gen_headers",
- "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "net/third_party/quiche/overrides/",
- "net/third_party/quiche/src/",
- "net/third_party/quiche/src/quiche/common/platform/default/",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //net:preload_decoder
-cc_library_static {
- name: "cronet_aml_net_preload_decoder",
- srcs: [
- "net/extras/preload_data/decoder.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //net/third_party/quiche:net_quic_proto
-cc_genrule {
- name: "cronet_aml_net_third_party_quiche_net_quic_proto_gen",
- srcs: [
- "net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.proto",
- "net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.proto",
- "net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/third_party/quiche/src --cpp_out=lite=true:$(genDir)/external/cronet/net/third_party/quiche/src/ $(in)",
- out: [
- "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.pb.cc",
- "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.pb.cc",
- "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.pb.cc",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net/third_party/quiche:net_quic_proto
-cc_genrule {
- name: "cronet_aml_net_third_party_quiche_net_quic_proto_gen_headers",
- srcs: [
- "net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.proto",
- "net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.proto",
- "net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/third_party/quiche/src --cpp_out=lite=true:$(genDir)/external/cronet/net/third_party/quiche/src/ $(in)",
- out: [
- "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/cached_network_parameters.pb.h",
- "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/crypto_server_config.pb.h",
- "external/cronet/net/third_party/quiche/src/quiche/quic/core/proto/source_address_token.pb.h",
- ],
- export_include_dirs: [
- ".",
- "net/third_party/quiche/src",
- "protos",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net/third_party/quiche:net_quic_test_tools_proto
-cc_genrule {
- name: "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen",
- srcs: [
- "net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/third_party/quiche/src/quiche/quic/test_tools --cpp_out=lite=true:$(genDir)/external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/ $(in)",
- out: [
- "external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.pb.cc",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net/third_party/quiche:net_quic_test_tools_proto
-cc_genrule {
- name: "cronet_aml_net_third_party_quiche_net_quic_test_tools_proto_gen_headers",
- srcs: [
- "net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/net/third_party/quiche/src/quiche/quic/test_tools --cpp_out=lite=true:$(genDir)/external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/ $(in)",
- out: [
- "external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/send_algorithm_test_result.pb.h",
- ],
- export_include_dirs: [
- ".",
- "net/third_party/quiche/src/quiche/quic/test_tools",
- "protos",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //net/third_party/quiche:quiche
-cc_library_static {
- name: "cronet_aml_net_third_party_quiche_quiche",
- srcs: [
- ":cronet_aml_net_third_party_quiche_net_quic_proto_gen",
- ":cronet_aml_third_party_abseil_cpp_absl_base_base",
- ":cronet_aml_third_party_abseil_cpp_absl_base_log_severity",
- ":cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait",
- ":cronet_aml_third_party_abseil_cpp_absl_base_strerror",
- ":cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate",
- ":cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler",
- ":cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace",
- ":cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize",
- ":cronet_aml_third_party_abseil_cpp_absl_hash_city",
- ":cronet_aml_third_party_abseil_cpp_absl_hash_hash",
- ":cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash",
- ":cronet_aml_third_party_abseil_cpp_absl_numeric_int128",
- ":cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased",
- ":cronet_aml_third_party_abseil_cpp_absl_random_distributions",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_platform",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow",
- ":cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material",
- ":cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception",
- ":cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences",
- ":cronet_aml_third_party_abseil_cpp_absl_status_status",
- ":cronet_aml_third_party_abseil_cpp_absl_status_statusor",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cord",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_strings_strings",
- ":cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal",
- ":cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization",
- ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time",
- ":cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone",
- ":cronet_aml_third_party_abseil_cpp_absl_time_time",
- ":cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access",
- ":cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access",
- "net/third_party/quiche/overrides/quiche_platform_impl/quiche_mutex_impl.cc",
- "net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.cc",
- "net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.cc",
- "net/third_party/quiche/src/quiche/common/platform/api/quiche_hostname_utils.cc",
- "net/third_party/quiche/src/quiche/common/platform/api/quiche_mutex.cc",
- "net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc",
- "net/third_party/quiche/src/quiche/common/quiche_buffer_allocator.cc",
- "net/third_party/quiche/src/quiche/common/quiche_crypto_logging.cc",
- "net/third_party/quiche/src/quiche/common/quiche_data_reader.cc",
- "net/third_party/quiche/src/quiche/common/quiche_data_writer.cc",
- "net/third_party/quiche/src/quiche/common/quiche_ip_address.cc",
- "net/third_party/quiche/src/quiche/common/quiche_ip_address_family.cc",
- "net/third_party/quiche/src/quiche/common/quiche_mem_slice_storage.cc",
- "net/third_party/quiche/src/quiche/common/quiche_random.cc",
- "net/third_party/quiche/src/quiche/common/quiche_text_utils.cc",
- "net/third_party/quiche/src/quiche/common/simple_buffer_allocator.cc",
- "net/third_party/quiche/src/quiche/common/structured_headers.cc",
- "net/third_party/quiche/src/quiche/http2/adapter/event_forwarder.cc",
- "net/third_party/quiche/src/quiche/http2/adapter/header_validator.cc",
- "net/third_party/quiche/src/quiche/http2/adapter/http2_protocol.cc",
- "net/third_party/quiche/src/quiche/http2/adapter/http2_util.cc",
- "net/third_party/quiche/src/quiche/http2/adapter/noop_header_validator.cc",
- "net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.cc",
- "net/third_party/quiche/src/quiche/http2/adapter/oghttp2_session.cc",
- "net/third_party/quiche/src/quiche/http2/adapter/oghttp2_util.cc",
- "net/third_party/quiche/src/quiche/http2/adapter/window_manager.cc",
- "net/third_party/quiche/src/quiche/http2/core/http2_trace_logging.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/decode_buffer.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/decode_http2_structures.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/decode_status.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/frame_decoder_state.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/http2_frame_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/http2_frame_decoder_listener.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/http2_structure_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/altsvc_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/continuation_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/data_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/goaway_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/headers_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/ping_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/priority_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/priority_update_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/push_promise_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/settings_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/unknown_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/decoder/payload_decoders/window_update_payload_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_block_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder_listener.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder_state.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder_string_buffer.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoder_tables.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_decoding_error.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_entry_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_entry_decoder_listener.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_entry_type_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_string_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_string_decoder_listener.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_whole_entry_buffer.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_whole_entry_listener.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/http2_hpack_constants.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/huffman/huffman_spec_tables.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/varint/hpack_varint_decoder.cc",
- "net/third_party/quiche/src/quiche/http2/hpack/varint/hpack_varint_encoder.cc",
- "net/third_party/quiche/src/quiche/http2/http2_constants.cc",
- "net/third_party/quiche/src/quiche/http2/http2_structures.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/bandwidth_sampler.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_drain.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_misc.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_probe_bw.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_probe_rtt.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_startup.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr_sender.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/cubic_bytes.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/general_loss_algorithm.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/hybrid_slow_start.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/pacing_sender.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/prr_sender.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/rtt_stats.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/send_algorithm_interface.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.cc",
- "net/third_party/quiche/src/quiche/quic/core/congestion_control/uber_loss_algorithm.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aead_base_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aead_base_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aes_128_gcm_12_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aes_128_gcm_12_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aes_128_gcm_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aes_128_gcm_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aes_256_gcm_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aes_256_gcm_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aes_base_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/aes_base_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/cert_compressor.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/certificate_util.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/chacha20_poly1305_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/chacha20_poly1305_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/chacha20_poly1305_tls_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/chacha20_poly1305_tls_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/chacha_base_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/chacha_base_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/channel_id.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/client_proof_source.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_framer.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_handshake.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_handshake_message.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_secret_boxer.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_utils.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/curve25519_key_exchange.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/key_exchange.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/null_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/null_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/p256_key_exchange.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/proof_source_x509.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/quic_client_session_cache.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/quic_compressed_certs_cache.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_client_config.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_proof.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_server_config.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/quic_encrypter.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/quic_hkdf.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/tls_client_connection.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/tls_connection.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/transport_parameters.cc",
- "net/third_party/quiche/src/quiche/quic/core/crypto/web_transport_fingerprint_proof_verifier.cc",
- "net/third_party/quiche/src/quiche/quic/core/deterministic_connection_id_generator.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_ack_frequency_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_blocked_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_connection_close_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_crypto_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_goaway_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_handshake_done_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_max_streams_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_message_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_new_connection_id_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_new_token_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_padding_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_path_challenge_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_path_response_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_ping_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_retire_connection_id_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_rst_stream_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_stop_sending_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_stop_waiting_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_stream_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_streams_blocked_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/frames/quic_window_update_frame.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/capsule.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/http_constants.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/http_decoder.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/http_encoder.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_client_promised_info.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_client_push_promise_index.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_header_list.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_headers_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_receive_control_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_send_control_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_server_initiated_spdy_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream_body_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/spdy_server_push_utils.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/spdy_utils.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/web_transport_http3.cc",
- "net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc",
- "net/third_party/quiche/src/quiche/quic/core/legacy_quic_stream_id_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_blocking_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoded_headers_accumulator.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_receiver.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_receiver.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_header_table.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_index_conversions.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_decoder.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instructions.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_progressive_decoder.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_receive_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_required_insert_count.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_send_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_static_table.cc",
- "net/third_party/quiche/src/quiche/quic/core/qpack/value_splitting_header_list.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_ack_listener_interface.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_alarm.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_bandwidth.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_chaos_protector.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_clock.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_coalesced_packet.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_config.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_connection.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_connection_context.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_connection_id.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_connection_id_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_connection_stats.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_constants.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_control_frame_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_handshaker.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_crypto_client_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_crypto_handshaker.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_crypto_server_stream_base.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_data_reader.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_data_writer.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_datagram_queue.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_error_codes.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_framer.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_idle_network_detector.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_legacy_version_encapsulator.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_mtu_discovery.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_network_blackhole_detector.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_packet_creator.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_packet_number.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_packets.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_path_validator.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_ping_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_sent_packet_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_server_id.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_session.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_socket_address_coder.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_stream.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_stream_id_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_stream_send_buffer.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_stream_sequencer_buffer.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_sustained_bandwidth_recorder.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_tag.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_time.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_transmission_info.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_types.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_utils.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_version_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_versions.cc",
- "net/third_party/quiche/src/quiche/quic/core/quic_write_blocked_list.cc",
- "net/third_party/quiche/src/quiche/quic/core/tls_client_handshaker.cc",
- "net/third_party/quiche/src/quiche/quic/core/tls_handshaker.cc",
- "net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc",
- "net/third_party/quiche/src/quiche/quic/core/uber_quic_stream_id_manager.cc",
- "net/third_party/quiche/src/quiche/quic/core/uber_received_packet_manager.cc",
- "net/third_party/quiche/src/quiche/quic/platform/api/quic_socket_address.cc",
- "net/third_party/quiche/src/quiche/spdy/core/array_output_buffer.cc",
- "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_constants.cc",
- "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_decoder_adapter.cc",
- "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_encoder.cc",
- "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_entry.cc",
- "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_header_table.cc",
- "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_output_stream.cc",
- "net/third_party/quiche/src/quiche/spdy/core/hpack/hpack_static_table.cc",
- "net/third_party/quiche/src/quiche/spdy/core/http2_frame_decoder_adapter.cc",
- "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.cc",
- "net/third_party/quiche/src/quiche/spdy/core/http2_header_storage.cc",
- "net/third_party/quiche/src/quiche/spdy/core/recording_headers_handler.cc",
- "net/third_party/quiche/src/quiche/spdy/core/spdy_alt_svc_wire_format.cc",
- "net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.cc",
- "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.cc",
- "net/third_party/quiche/src/quiche/spdy/core/spdy_no_op_visitor.cc",
- "net/third_party/quiche/src/quiche/spdy/core/spdy_pinnable_buffer_piece.cc",
- "net/third_party/quiche/src/quiche/spdy/core/spdy_prefixed_buffer_reader.cc",
- "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.cc",
- "net/third_party/quiche/src/quiche/spdy/core/spdy_simple_arena.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- "libprotobuf-cpp-lite",
- "libz",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_net_uri_template",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- "cronet_aml_third_party_protobuf_protobuf_lite",
- "cronet_aml_url_url",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_net_third_party_quiche_net_quic_proto_gen_headers",
- ],
- export_generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_net_third_party_quiche_net_quic_proto_gen_headers",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DIS_QUICHE_IMPL",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "net/third_party/quiche/overrides/",
- "net/third_party/quiche/src/",
- "net/third_party/quiche/src/quiche/common/platform/default/",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //net/traffic_annotation:traffic_annotation
-cc_object {
- name: "cronet_aml_net_traffic_annotation_traffic_annotation",
- srcs: [
- "net/traffic_annotation/network_traffic_annotation_android.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //net:uri_template
-cc_library_static {
- name: "cronet_aml_net_uri_template",
- srcs: [
- "net/third_party/uri_template/uri_template.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DIS_URI_TEMPLATE_IMPL",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:base
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_base_base",
- srcs: [
- "third_party/abseil-cpp/absl/base/internal/cycleclock.cc",
- "third_party/abseil-cpp/absl/base/internal/spinlock.cc",
- "third_party/abseil-cpp/absl/base/internal/sysinfo.cc",
- "third_party/abseil-cpp/absl/base/internal/thread_identity.cc",
- "third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:log_severity
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_base_log_severity",
- srcs: [
- "third_party/abseil-cpp/absl/base/log_severity.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:malloc_internal
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_base_malloc_internal",
- srcs: [
- "third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:raw_logging_internal
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_base_raw_logging_internal",
- srcs: [
- "third_party/abseil-cpp/absl/base/internal/raw_logging.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:spinlock_wait
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_base_spinlock_wait",
- srcs: [
- "third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:strerror
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_base_strerror",
- srcs: [
- "third_party/abseil-cpp/absl/base/internal/strerror.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/base:throw_delegate
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_base_throw_delegate",
- srcs: [
- "third_party/abseil-cpp/absl/base/internal/throw_delegate.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:hashtablez_sampler
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_container_hashtablez_sampler",
- srcs: [
- "third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc",
- "third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/container:raw_hash_set
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_container_raw_hash_set",
- srcs: [
- "third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/debugging:debugging_internal
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_debugging_debugging_internal",
- srcs: [
- "third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc",
- "third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc",
- "third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/debugging:demangle_internal
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_debugging_demangle_internal",
- srcs: [
- "third_party/abseil-cpp/absl/debugging/internal/demangle.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/debugging:examine_stack
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_debugging_examine_stack",
- srcs: [
- "third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/debugging:failure_signal_handler
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_debugging_failure_signal_handler",
- srcs: [
- "third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/debugging:stacktrace
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_debugging_stacktrace",
- srcs: [
- "third_party/abseil-cpp/absl/debugging/stacktrace.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/debugging:symbolize
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_debugging_symbolize",
- srcs: [
- "third_party/abseil-cpp/absl/debugging/symbolize.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/hash:city
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_hash_city",
- srcs: [
- "third_party/abseil-cpp/absl/hash/internal/city.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/hash:hash
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_hash_hash",
- srcs: [
- "third_party/abseil-cpp/absl/hash/internal/hash.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/hash:low_level_hash
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_hash_low_level_hash",
- srcs: [
- "third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/numeric:int128
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_numeric_int128",
- srcs: [
- "third_party/abseil-cpp/absl/numeric/int128.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/profiling:exponential_biased
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_profiling_exponential_biased",
- srcs: [
- "third_party/abseil-cpp/absl/profiling/internal/exponential_biased.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random:distributions
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_distributions",
- srcs: [
- "third_party/abseil-cpp/absl/random/discrete_distribution.cc",
- "third_party/abseil-cpp/absl/random/gaussian_distribution.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:platform
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_platform",
- srcs: [
- "third_party/abseil-cpp/absl/random/internal/randen_round_keys.cc",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:pool_urbg
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_pool_urbg",
- srcs: [
- "third_party/abseil-cpp/absl/random/internal/pool_urbg.cc",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:randen
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen",
- srcs: [
- "third_party/abseil-cpp/absl/random/internal/randen.cc",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:randen_hwaes
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes",
- srcs: [
- "third_party/abseil-cpp/absl/random/internal/randen_detect.cc",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:randen_hwaes_impl
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_hwaes_impl",
- srcs: [
- "third_party/abseil-cpp/absl/random/internal/randen_hwaes.cc",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:randen_slow
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_randen_slow",
- srcs: [
- "third_party/abseil-cpp/absl/random/internal/randen_slow.cc",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random/internal:seed_material
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_internal_seed_material",
- srcs: [
- "third_party/abseil-cpp/absl/random/internal/seed_material.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random:seed_gen_exception
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_seed_gen_exception",
- srcs: [
- "third_party/abseil-cpp/absl/random/seed_gen_exception.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/random:seed_sequences
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_random_seed_sequences",
- srcs: [
- "third_party/abseil-cpp/absl/random/seed_sequences.cc",
- ],
- generated_headers: [
- "cronet_aml_build_chromeos_buildflags",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/status:status
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_status_status",
- srcs: [
- "third_party/abseil-cpp/absl/status/status.cc",
- "third_party/abseil-cpp/absl/status/status_payload_printer.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/status:statusor
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_status_statusor",
- srcs: [
- "third_party/abseil-cpp/absl/status/statusor.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:cord
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_strings_cord",
- srcs: [
- "third_party/abseil-cpp/absl/strings/cord.cc",
- "third_party/abseil-cpp/absl/strings/cord_analysis.cc",
- "third_party/abseil-cpp/absl/strings/cord_buffer.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:cord_internal
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_strings_cord_internal",
- srcs: [
- "third_party/abseil-cpp/absl/strings/internal/cord_internal.cc",
- "third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.cc",
- "third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc",
- "third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.cc",
- "third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.cc",
- "third_party/abseil-cpp/absl/strings/internal/cord_rep_crc.cc",
- "third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:cordz_functions
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_functions",
- srcs: [
- "third_party/abseil-cpp/absl/strings/internal/cordz_functions.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:cordz_handle
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_handle",
- srcs: [
- "third_party/abseil-cpp/absl/strings/internal/cordz_handle.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:cordz_info
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_strings_cordz_info",
- srcs: [
- "third_party/abseil-cpp/absl/strings/internal/cordz_info.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:internal
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_strings_internal",
- srcs: [
- "third_party/abseil-cpp/absl/strings/internal/escaping.cc",
- "third_party/abseil-cpp/absl/strings/internal/ostringstream.cc",
- "third_party/abseil-cpp/absl/strings/internal/utf8.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:str_format_internal
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_strings_str_format_internal",
- srcs: [
- "third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc",
- "third_party/abseil-cpp/absl/strings/internal/str_format/bind.cc",
- "third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc",
- "third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc",
- "third_party/abseil-cpp/absl/strings/internal/str_format/output.cc",
- "third_party/abseil-cpp/absl/strings/internal/str_format/parser.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/strings:strings
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_strings_strings",
- srcs: [
- "third_party/abseil-cpp/absl/strings/ascii.cc",
- "third_party/abseil-cpp/absl/strings/charconv.cc",
- "third_party/abseil-cpp/absl/strings/escaping.cc",
- "third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc",
- "third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc",
- "third_party/abseil-cpp/absl/strings/internal/memutil.cc",
- "third_party/abseil-cpp/absl/strings/match.cc",
- "third_party/abseil-cpp/absl/strings/numbers.cc",
- "third_party/abseil-cpp/absl/strings/str_cat.cc",
- "third_party/abseil-cpp/absl/strings/str_replace.cc",
- "third_party/abseil-cpp/absl/strings/str_split.cc",
- "third_party/abseil-cpp/absl/strings/string_view.cc",
- "third_party/abseil-cpp/absl/strings/substitute.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/synchronization:graphcycles_internal
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_synchronization_graphcycles_internal",
- srcs: [
- "third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/synchronization:synchronization
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_synchronization_synchronization",
- srcs: [
- "third_party/abseil-cpp/absl/synchronization/barrier.cc",
- "third_party/abseil-cpp/absl/synchronization/blocking_counter.cc",
- "third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc",
- "third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc",
- "third_party/abseil-cpp/absl/synchronization/internal/waiter.cc",
- "third_party/abseil-cpp/absl/synchronization/mutex.cc",
- "third_party/abseil-cpp/absl/synchronization/notification.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/time/internal/cctz:civil_time
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_civil_time",
- srcs: [
- "third_party/abseil-cpp/absl/time/internal/cctz/src/civil_time_detail.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/time/internal/cctz:time_zone
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_time_internal_cctz_time_zone",
- srcs: [
- "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc",
- "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc",
- "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc",
- "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc",
- "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc",
- "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc",
- "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc",
- "third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc",
- "third_party/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/time:time
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_time_time",
- srcs: [
- "third_party/abseil-cpp/absl/time/civil_time.cc",
- "third_party/abseil-cpp/absl/time/clock.cc",
- "third_party/abseil-cpp/absl/time/duration.cc",
- "third_party/abseil-cpp/absl/time/format.cc",
- "third_party/abseil-cpp/absl/time/time.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/types:bad_optional_access
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_types_bad_optional_access",
- srcs: [
- "third_party/abseil-cpp/absl/types/bad_optional_access.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/abseil-cpp/absl/types:bad_variant_access
-cc_object {
- name: "cronet_aml_third_party_abseil_cpp_absl_types_bad_variant_access",
- srcs: [
- "third_party/abseil-cpp/absl/types/bad_variant_access.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DABSL_ALLOCATOR_NOTHROW=1",
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/android_ndk:cpu_features
-cc_object {
- name: "cronet_aml_third_party_android_ndk_cpu_features",
- srcs: [
- "third_party/android_ndk/sources/android/cpufeatures/cpu-features.c",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/android_ndk/sources/android/cpufeatures/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/ashmem:ashmem
-cc_object {
- name: "cronet_aml_third_party_ashmem_ashmem",
- srcs: [
- "third_party/ashmem/ashmem-dev.c",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/boringssl:boringssl
-cc_library_static {
- name: "cronet_aml_third_party_boringssl_boringssl",
- srcs: [
- ":cronet_aml_third_party_boringssl_boringssl_asm",
- "third_party/boringssl/err_data.c",
- "third_party/boringssl/src/crypto/asn1/a_bitstr.c",
- "third_party/boringssl/src/crypto/asn1/a_bool.c",
- "third_party/boringssl/src/crypto/asn1/a_d2i_fp.c",
- "third_party/boringssl/src/crypto/asn1/a_dup.c",
- "third_party/boringssl/src/crypto/asn1/a_gentm.c",
- "third_party/boringssl/src/crypto/asn1/a_i2d_fp.c",
- "third_party/boringssl/src/crypto/asn1/a_int.c",
- "third_party/boringssl/src/crypto/asn1/a_mbstr.c",
- "third_party/boringssl/src/crypto/asn1/a_object.c",
- "third_party/boringssl/src/crypto/asn1/a_octet.c",
- "third_party/boringssl/src/crypto/asn1/a_print.c",
- "third_party/boringssl/src/crypto/asn1/a_strex.c",
- "third_party/boringssl/src/crypto/asn1/a_strnid.c",
- "third_party/boringssl/src/crypto/asn1/a_time.c",
- "third_party/boringssl/src/crypto/asn1/a_type.c",
- "third_party/boringssl/src/crypto/asn1/a_utctm.c",
- "third_party/boringssl/src/crypto/asn1/a_utf8.c",
- "third_party/boringssl/src/crypto/asn1/asn1_lib.c",
- "third_party/boringssl/src/crypto/asn1/asn1_par.c",
- "third_party/boringssl/src/crypto/asn1/asn_pack.c",
- "third_party/boringssl/src/crypto/asn1/f_int.c",
- "third_party/boringssl/src/crypto/asn1/f_string.c",
- "third_party/boringssl/src/crypto/asn1/posix_time.c",
- "third_party/boringssl/src/crypto/asn1/tasn_dec.c",
- "third_party/boringssl/src/crypto/asn1/tasn_enc.c",
- "third_party/boringssl/src/crypto/asn1/tasn_fre.c",
- "third_party/boringssl/src/crypto/asn1/tasn_new.c",
- "third_party/boringssl/src/crypto/asn1/tasn_typ.c",
- "third_party/boringssl/src/crypto/asn1/tasn_utl.c",
- "third_party/boringssl/src/crypto/base64/base64.c",
- "third_party/boringssl/src/crypto/bio/bio.c",
- "third_party/boringssl/src/crypto/bio/bio_mem.c",
- "third_party/boringssl/src/crypto/bio/connect.c",
- "third_party/boringssl/src/crypto/bio/fd.c",
- "third_party/boringssl/src/crypto/bio/file.c",
- "third_party/boringssl/src/crypto/bio/hexdump.c",
- "third_party/boringssl/src/crypto/bio/pair.c",
- "third_party/boringssl/src/crypto/bio/printf.c",
- "third_party/boringssl/src/crypto/bio/socket.c",
- "third_party/boringssl/src/crypto/bio/socket_helper.c",
- "third_party/boringssl/src/crypto/blake2/blake2.c",
- "third_party/boringssl/src/crypto/bn_extra/bn_asn1.c",
- "third_party/boringssl/src/crypto/bn_extra/convert.c",
- "third_party/boringssl/src/crypto/buf/buf.c",
- "third_party/boringssl/src/crypto/bytestring/asn1_compat.c",
- "third_party/boringssl/src/crypto/bytestring/ber.c",
- "third_party/boringssl/src/crypto/bytestring/cbb.c",
- "third_party/boringssl/src/crypto/bytestring/cbs.c",
- "third_party/boringssl/src/crypto/bytestring/unicode.c",
- "third_party/boringssl/src/crypto/chacha/chacha.c",
- "third_party/boringssl/src/crypto/cipher_extra/cipher_extra.c",
- "third_party/boringssl/src/crypto/cipher_extra/derive_key.c",
- "third_party/boringssl/src/crypto/cipher_extra/e_aesctrhmac.c",
- "third_party/boringssl/src/crypto/cipher_extra/e_aesgcmsiv.c",
- "third_party/boringssl/src/crypto/cipher_extra/e_chacha20poly1305.c",
- "third_party/boringssl/src/crypto/cipher_extra/e_des.c",
- "third_party/boringssl/src/crypto/cipher_extra/e_null.c",
- "third_party/boringssl/src/crypto/cipher_extra/e_rc2.c",
- "third_party/boringssl/src/crypto/cipher_extra/e_rc4.c",
- "third_party/boringssl/src/crypto/cipher_extra/e_tls.c",
- "third_party/boringssl/src/crypto/cipher_extra/tls_cbc.c",
- "third_party/boringssl/src/crypto/conf/conf.c",
- "third_party/boringssl/src/crypto/cpu_aarch64_apple.c",
- "third_party/boringssl/src/crypto/cpu_aarch64_fuchsia.c",
- "third_party/boringssl/src/crypto/cpu_aarch64_linux.c",
- "third_party/boringssl/src/crypto/cpu_aarch64_win.c",
- "third_party/boringssl/src/crypto/cpu_arm.c",
- "third_party/boringssl/src/crypto/cpu_arm_linux.c",
- "third_party/boringssl/src/crypto/cpu_intel.c",
- "third_party/boringssl/src/crypto/cpu_ppc64le.c",
- "third_party/boringssl/src/crypto/crypto.c",
- "third_party/boringssl/src/crypto/curve25519/curve25519.c",
- "third_party/boringssl/src/crypto/curve25519/spake25519.c",
- "third_party/boringssl/src/crypto/des/des.c",
- "third_party/boringssl/src/crypto/dh_extra/dh_asn1.c",
- "third_party/boringssl/src/crypto/dh_extra/params.c",
- "third_party/boringssl/src/crypto/digest_extra/digest_extra.c",
- "third_party/boringssl/src/crypto/dsa/dsa.c",
- "third_party/boringssl/src/crypto/dsa/dsa_asn1.c",
- "third_party/boringssl/src/crypto/ec_extra/ec_asn1.c",
- "third_party/boringssl/src/crypto/ec_extra/ec_derive.c",
- "third_party/boringssl/src/crypto/ec_extra/hash_to_curve.c",
- "third_party/boringssl/src/crypto/ecdh_extra/ecdh_extra.c",
- "third_party/boringssl/src/crypto/ecdsa_extra/ecdsa_asn1.c",
- "third_party/boringssl/src/crypto/engine/engine.c",
- "third_party/boringssl/src/crypto/err/err.c",
- "third_party/boringssl/src/crypto/evp/evp.c",
- "third_party/boringssl/src/crypto/evp/evp_asn1.c",
- "third_party/boringssl/src/crypto/evp/evp_ctx.c",
- "third_party/boringssl/src/crypto/evp/p_dsa_asn1.c",
- "third_party/boringssl/src/crypto/evp/p_ec.c",
- "third_party/boringssl/src/crypto/evp/p_ec_asn1.c",
- "third_party/boringssl/src/crypto/evp/p_ed25519.c",
- "third_party/boringssl/src/crypto/evp/p_ed25519_asn1.c",
- "third_party/boringssl/src/crypto/evp/p_hkdf.c",
- "third_party/boringssl/src/crypto/evp/p_rsa.c",
- "third_party/boringssl/src/crypto/evp/p_rsa_asn1.c",
- "third_party/boringssl/src/crypto/evp/p_x25519.c",
- "third_party/boringssl/src/crypto/evp/p_x25519_asn1.c",
- "third_party/boringssl/src/crypto/evp/pbkdf.c",
- "third_party/boringssl/src/crypto/evp/print.c",
- "third_party/boringssl/src/crypto/evp/scrypt.c",
- "third_party/boringssl/src/crypto/evp/sign.c",
- "third_party/boringssl/src/crypto/ex_data.c",
- "third_party/boringssl/src/crypto/fipsmodule/bcm.c",
- "third_party/boringssl/src/crypto/fipsmodule/fips_shared_support.c",
- "third_party/boringssl/src/crypto/hkdf/hkdf.c",
- "third_party/boringssl/src/crypto/hpke/hpke.c",
- "third_party/boringssl/src/crypto/hrss/hrss.c",
- "third_party/boringssl/src/crypto/lhash/lhash.c",
- "third_party/boringssl/src/crypto/mem.c",
- "third_party/boringssl/src/crypto/obj/obj.c",
- "third_party/boringssl/src/crypto/obj/obj_xref.c",
- "third_party/boringssl/src/crypto/pem/pem_all.c",
- "third_party/boringssl/src/crypto/pem/pem_info.c",
- "third_party/boringssl/src/crypto/pem/pem_lib.c",
- "third_party/boringssl/src/crypto/pem/pem_oth.c",
- "third_party/boringssl/src/crypto/pem/pem_pk8.c",
- "third_party/boringssl/src/crypto/pem/pem_pkey.c",
- "third_party/boringssl/src/crypto/pem/pem_x509.c",
- "third_party/boringssl/src/crypto/pem/pem_xaux.c",
- "third_party/boringssl/src/crypto/pkcs7/pkcs7.c",
- "third_party/boringssl/src/crypto/pkcs7/pkcs7_x509.c",
- "third_party/boringssl/src/crypto/pkcs8/p5_pbev2.c",
- "third_party/boringssl/src/crypto/pkcs8/pkcs8.c",
- "third_party/boringssl/src/crypto/pkcs8/pkcs8_x509.c",
- "third_party/boringssl/src/crypto/poly1305/poly1305.c",
- "third_party/boringssl/src/crypto/poly1305/poly1305_arm.c",
- "third_party/boringssl/src/crypto/poly1305/poly1305_vec.c",
- "third_party/boringssl/src/crypto/pool/pool.c",
- "third_party/boringssl/src/crypto/rand_extra/deterministic.c",
- "third_party/boringssl/src/crypto/rand_extra/forkunsafe.c",
- "third_party/boringssl/src/crypto/rand_extra/fuchsia.c",
- "third_party/boringssl/src/crypto/rand_extra/passive.c",
- "third_party/boringssl/src/crypto/rand_extra/rand_extra.c",
- "third_party/boringssl/src/crypto/rand_extra/windows.c",
- "third_party/boringssl/src/crypto/rc4/rc4.c",
- "third_party/boringssl/src/crypto/refcount_c11.c",
- "third_party/boringssl/src/crypto/refcount_lock.c",
- "third_party/boringssl/src/crypto/rsa_extra/rsa_asn1.c",
- "third_party/boringssl/src/crypto/rsa_extra/rsa_print.c",
- "third_party/boringssl/src/crypto/siphash/siphash.c",
- "third_party/boringssl/src/crypto/stack/stack.c",
- "third_party/boringssl/src/crypto/thread.c",
- "third_party/boringssl/src/crypto/thread_none.c",
- "third_party/boringssl/src/crypto/thread_pthread.c",
- "third_party/boringssl/src/crypto/thread_win.c",
- "third_party/boringssl/src/crypto/trust_token/pmbtoken.c",
- "third_party/boringssl/src/crypto/trust_token/trust_token.c",
- "third_party/boringssl/src/crypto/trust_token/voprf.c",
- "third_party/boringssl/src/crypto/x509/a_digest.c",
- "third_party/boringssl/src/crypto/x509/a_sign.c",
- "third_party/boringssl/src/crypto/x509/a_verify.c",
- "third_party/boringssl/src/crypto/x509/algorithm.c",
- "third_party/boringssl/src/crypto/x509/asn1_gen.c",
- "third_party/boringssl/src/crypto/x509/by_dir.c",
- "third_party/boringssl/src/crypto/x509/by_file.c",
- "third_party/boringssl/src/crypto/x509/i2d_pr.c",
- "third_party/boringssl/src/crypto/x509/name_print.c",
- "third_party/boringssl/src/crypto/x509/rsa_pss.c",
- "third_party/boringssl/src/crypto/x509/t_crl.c",
- "third_party/boringssl/src/crypto/x509/t_req.c",
- "third_party/boringssl/src/crypto/x509/t_x509.c",
- "third_party/boringssl/src/crypto/x509/t_x509a.c",
- "third_party/boringssl/src/crypto/x509/x509.c",
- "third_party/boringssl/src/crypto/x509/x509_att.c",
- "third_party/boringssl/src/crypto/x509/x509_cmp.c",
- "third_party/boringssl/src/crypto/x509/x509_d2.c",
- "third_party/boringssl/src/crypto/x509/x509_def.c",
- "third_party/boringssl/src/crypto/x509/x509_ext.c",
- "third_party/boringssl/src/crypto/x509/x509_lu.c",
- "third_party/boringssl/src/crypto/x509/x509_obj.c",
- "third_party/boringssl/src/crypto/x509/x509_req.c",
- "third_party/boringssl/src/crypto/x509/x509_set.c",
- "third_party/boringssl/src/crypto/x509/x509_trs.c",
- "third_party/boringssl/src/crypto/x509/x509_txt.c",
- "third_party/boringssl/src/crypto/x509/x509_v3.c",
- "third_party/boringssl/src/crypto/x509/x509_vfy.c",
- "third_party/boringssl/src/crypto/x509/x509_vpm.c",
- "third_party/boringssl/src/crypto/x509/x509cset.c",
- "third_party/boringssl/src/crypto/x509/x509name.c",
- "third_party/boringssl/src/crypto/x509/x509rset.c",
- "third_party/boringssl/src/crypto/x509/x509spki.c",
- "third_party/boringssl/src/crypto/x509/x_algor.c",
- "third_party/boringssl/src/crypto/x509/x_all.c",
- "third_party/boringssl/src/crypto/x509/x_attrib.c",
- "third_party/boringssl/src/crypto/x509/x_crl.c",
- "third_party/boringssl/src/crypto/x509/x_exten.c",
- "third_party/boringssl/src/crypto/x509/x_info.c",
- "third_party/boringssl/src/crypto/x509/x_name.c",
- "third_party/boringssl/src/crypto/x509/x_pkey.c",
- "third_party/boringssl/src/crypto/x509/x_pubkey.c",
- "third_party/boringssl/src/crypto/x509/x_req.c",
- "third_party/boringssl/src/crypto/x509/x_sig.c",
- "third_party/boringssl/src/crypto/x509/x_spki.c",
- "third_party/boringssl/src/crypto/x509/x_val.c",
- "third_party/boringssl/src/crypto/x509/x_x509.c",
- "third_party/boringssl/src/crypto/x509/x_x509a.c",
- "third_party/boringssl/src/crypto/x509v3/pcy_cache.c",
- "third_party/boringssl/src/crypto/x509v3/pcy_data.c",
- "third_party/boringssl/src/crypto/x509v3/pcy_map.c",
- "third_party/boringssl/src/crypto/x509v3/pcy_node.c",
- "third_party/boringssl/src/crypto/x509v3/pcy_tree.c",
- "third_party/boringssl/src/crypto/x509v3/v3_akey.c",
- "third_party/boringssl/src/crypto/x509v3/v3_akeya.c",
- "third_party/boringssl/src/crypto/x509v3/v3_alt.c",
- "third_party/boringssl/src/crypto/x509v3/v3_bcons.c",
- "third_party/boringssl/src/crypto/x509v3/v3_bitst.c",
- "third_party/boringssl/src/crypto/x509v3/v3_conf.c",
- "third_party/boringssl/src/crypto/x509v3/v3_cpols.c",
- "third_party/boringssl/src/crypto/x509v3/v3_crld.c",
- "third_party/boringssl/src/crypto/x509v3/v3_enum.c",
- "third_party/boringssl/src/crypto/x509v3/v3_extku.c",
- "third_party/boringssl/src/crypto/x509v3/v3_genn.c",
- "third_party/boringssl/src/crypto/x509v3/v3_ia5.c",
- "third_party/boringssl/src/crypto/x509v3/v3_info.c",
- "third_party/boringssl/src/crypto/x509v3/v3_int.c",
- "third_party/boringssl/src/crypto/x509v3/v3_lib.c",
- "third_party/boringssl/src/crypto/x509v3/v3_ncons.c",
- "third_party/boringssl/src/crypto/x509v3/v3_ocsp.c",
- "third_party/boringssl/src/crypto/x509v3/v3_pci.c",
- "third_party/boringssl/src/crypto/x509v3/v3_pcia.c",
- "third_party/boringssl/src/crypto/x509v3/v3_pcons.c",
- "third_party/boringssl/src/crypto/x509v3/v3_pmaps.c",
- "third_party/boringssl/src/crypto/x509v3/v3_prn.c",
- "third_party/boringssl/src/crypto/x509v3/v3_purp.c",
- "third_party/boringssl/src/crypto/x509v3/v3_skey.c",
- "third_party/boringssl/src/crypto/x509v3/v3_utl.c",
- "third_party/boringssl/src/ssl/bio_ssl.cc",
- "third_party/boringssl/src/ssl/d1_both.cc",
- "third_party/boringssl/src/ssl/d1_lib.cc",
- "third_party/boringssl/src/ssl/d1_pkt.cc",
- "third_party/boringssl/src/ssl/d1_srtp.cc",
- "third_party/boringssl/src/ssl/dtls_method.cc",
- "third_party/boringssl/src/ssl/dtls_record.cc",
- "third_party/boringssl/src/ssl/encrypted_client_hello.cc",
- "third_party/boringssl/src/ssl/extensions.cc",
- "third_party/boringssl/src/ssl/handoff.cc",
- "third_party/boringssl/src/ssl/handshake.cc",
- "third_party/boringssl/src/ssl/handshake_client.cc",
- "third_party/boringssl/src/ssl/handshake_server.cc",
- "third_party/boringssl/src/ssl/s3_both.cc",
- "third_party/boringssl/src/ssl/s3_lib.cc",
- "third_party/boringssl/src/ssl/s3_pkt.cc",
- "third_party/boringssl/src/ssl/ssl_aead_ctx.cc",
- "third_party/boringssl/src/ssl/ssl_asn1.cc",
- "third_party/boringssl/src/ssl/ssl_buffer.cc",
- "third_party/boringssl/src/ssl/ssl_cert.cc",
- "third_party/boringssl/src/ssl/ssl_cipher.cc",
- "third_party/boringssl/src/ssl/ssl_file.cc",
- "third_party/boringssl/src/ssl/ssl_key_share.cc",
- "third_party/boringssl/src/ssl/ssl_lib.cc",
- "third_party/boringssl/src/ssl/ssl_privkey.cc",
- "third_party/boringssl/src/ssl/ssl_session.cc",
- "third_party/boringssl/src/ssl/ssl_stat.cc",
- "third_party/boringssl/src/ssl/ssl_transcript.cc",
- "third_party/boringssl/src/ssl/ssl_versions.cc",
- "third_party/boringssl/src/ssl/ssl_x509.cc",
- "third_party/boringssl/src/ssl/t1_enc.cc",
- "third_party/boringssl/src/ssl/tls13_both.cc",
- "third_party/boringssl/src/ssl/tls13_client.cc",
- "third_party/boringssl/src/ssl/tls13_enc.cc",
- "third_party/boringssl/src/ssl/tls13_server.cc",
- "third_party/boringssl/src/ssl/tls_method.cc",
- "third_party/boringssl/src/ssl/tls_record.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DBORINGSSL_ALLOW_CXX_RUNTIME",
- "-DBORINGSSL_IMPLEMENTATION",
- "-DBORINGSSL_NO_STATIC_INITIALIZER",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-DOPENSSL_SMALL",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/boringssl/src/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/boringssl:boringssl_asm
-cc_object {
- name: "cronet_aml_third_party_boringssl_boringssl_asm",
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/boringssl/src/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_arm: {
- srcs: [
- "third_party/boringssl/linux-arm/crypto/chacha/chacha-armv4.S",
- "third_party/boringssl/linux-arm/crypto/fipsmodule/aesv8-armx32.S",
- "third_party/boringssl/linux-arm/crypto/fipsmodule/armv4-mont.S",
- "third_party/boringssl/linux-arm/crypto/fipsmodule/bsaes-armv7.S",
- "third_party/boringssl/linux-arm/crypto/fipsmodule/ghash-armv4.S",
- "third_party/boringssl/linux-arm/crypto/fipsmodule/ghashv8-armx32.S",
- "third_party/boringssl/linux-arm/crypto/fipsmodule/sha1-armv4-large.S",
- "third_party/boringssl/linux-arm/crypto/fipsmodule/sha256-armv4.S",
- "third_party/boringssl/linux-arm/crypto/fipsmodule/sha512-armv4.S",
- "third_party/boringssl/linux-arm/crypto/fipsmodule/vpaes-armv7.S",
- "third_party/boringssl/linux-arm/crypto/test/trampoline-armv4.S",
- "third_party/boringssl/src/crypto/curve25519/asm/x25519-asm-arm.S",
- "third_party/boringssl/src/crypto/poly1305/poly1305_arm_asm.S",
- ],
- },
- android_arm64: {
- srcs: [
- "third_party/boringssl/linux-aarch64/crypto/chacha/chacha-armv8.S",
- "third_party/boringssl/linux-aarch64/crypto/cipher_extra/chacha20_poly1305_armv8.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/armv8-mont.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/p256-armv8-asm.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/p256_beeu-armv8-asm.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha1-armv8.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha256-armv8.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha512-armv8.S",
- "third_party/boringssl/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S",
- "third_party/boringssl/linux-aarch64/crypto/test/trampoline-armv8.S",
- ],
- },
- android_x86: {
- srcs: [
- "third_party/boringssl/linux-x86/crypto/chacha/chacha-x86.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/aesni-x86.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/bn-586.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/co-586.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-x86.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/md5-586.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/sha1-586.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/sha256-586.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/sha512-586.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/vpaes-x86.S",
- "third_party/boringssl/linux-x86/crypto/fipsmodule/x86-mont.S",
- "third_party/boringssl/linux-x86/crypto/test/trampoline-x86.S",
- ],
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- srcs: [
- "third_party/boringssl/linux-x86_64/crypto/chacha/chacha-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/md5-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont.S",
- "third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S",
- "third_party/boringssl/linux-x86_64/crypto/test/trampoline-x86_64.S",
- "third_party/boringssl/src/crypto/hrss/asm/poly_rq_mul.S",
- ],
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/brotli:common
-cc_library_static {
- name: "cronet_aml_third_party_brotli_common",
- srcs: [
- "third_party/brotli/common/constants.c",
- "third_party/brotli/common/context.c",
- "third_party/brotli/common/dictionary.c",
- "third_party/brotli/common/platform.c",
- "third_party/brotli/common/shared_dictionary.c",
- "third_party/brotli/common/transform.c",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/brotli/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/brotli:dec
-cc_library_static {
- name: "cronet_aml_third_party_brotli_dec",
- srcs: [
- "third_party/brotli/dec/bit_reader.c",
- "third_party/brotli/dec/decode.c",
- "third_party/brotli/dec/huffman.c",
- "third_party/brotli/dec/state.c",
- ],
- static_libs: [
- "cronet_aml_third_party_brotli_common",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/brotli/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/icu:icui18n
-cc_library_static {
- name: "cronet_aml_third_party_icu_icui18n",
- srcs: [
- "third_party/icu/source/i18n/alphaindex.cpp",
- "third_party/icu/source/i18n/anytrans.cpp",
- "third_party/icu/source/i18n/astro.cpp",
- "third_party/icu/source/i18n/basictz.cpp",
- "third_party/icu/source/i18n/bocsu.cpp",
- "third_party/icu/source/i18n/brktrans.cpp",
- "third_party/icu/source/i18n/buddhcal.cpp",
- "third_party/icu/source/i18n/calendar.cpp",
- "third_party/icu/source/i18n/casetrn.cpp",
- "third_party/icu/source/i18n/cecal.cpp",
- "third_party/icu/source/i18n/chnsecal.cpp",
- "third_party/icu/source/i18n/choicfmt.cpp",
- "third_party/icu/source/i18n/coleitr.cpp",
- "third_party/icu/source/i18n/coll.cpp",
- "third_party/icu/source/i18n/collation.cpp",
- "third_party/icu/source/i18n/collationbuilder.cpp",
- "third_party/icu/source/i18n/collationcompare.cpp",
- "third_party/icu/source/i18n/collationdata.cpp",
- "third_party/icu/source/i18n/collationdatabuilder.cpp",
- "third_party/icu/source/i18n/collationdatareader.cpp",
- "third_party/icu/source/i18n/collationdatawriter.cpp",
- "third_party/icu/source/i18n/collationfastlatin.cpp",
- "third_party/icu/source/i18n/collationfastlatinbuilder.cpp",
- "third_party/icu/source/i18n/collationfcd.cpp",
- "third_party/icu/source/i18n/collationiterator.cpp",
- "third_party/icu/source/i18n/collationkeys.cpp",
- "third_party/icu/source/i18n/collationroot.cpp",
- "third_party/icu/source/i18n/collationrootelements.cpp",
- "third_party/icu/source/i18n/collationruleparser.cpp",
- "third_party/icu/source/i18n/collationsets.cpp",
- "third_party/icu/source/i18n/collationsettings.cpp",
- "third_party/icu/source/i18n/collationtailoring.cpp",
- "third_party/icu/source/i18n/collationweights.cpp",
- "third_party/icu/source/i18n/compactdecimalformat.cpp",
- "third_party/icu/source/i18n/coptccal.cpp",
- "third_party/icu/source/i18n/cpdtrans.cpp",
- "third_party/icu/source/i18n/csdetect.cpp",
- "third_party/icu/source/i18n/csmatch.cpp",
- "third_party/icu/source/i18n/csr2022.cpp",
- "third_party/icu/source/i18n/csrecog.cpp",
- "third_party/icu/source/i18n/csrmbcs.cpp",
- "third_party/icu/source/i18n/csrsbcs.cpp",
- "third_party/icu/source/i18n/csrucode.cpp",
- "third_party/icu/source/i18n/csrutf8.cpp",
- "third_party/icu/source/i18n/curramt.cpp",
- "third_party/icu/source/i18n/currfmt.cpp",
- "third_party/icu/source/i18n/currpinf.cpp",
- "third_party/icu/source/i18n/currunit.cpp",
- "third_party/icu/source/i18n/dangical.cpp",
- "third_party/icu/source/i18n/datefmt.cpp",
- "third_party/icu/source/i18n/dayperiodrules.cpp",
- "third_party/icu/source/i18n/dcfmtsym.cpp",
- "third_party/icu/source/i18n/decContext.cpp",
- "third_party/icu/source/i18n/decNumber.cpp",
- "third_party/icu/source/i18n/decimfmt.cpp",
- "third_party/icu/source/i18n/double-conversion-bignum-dtoa.cpp",
- "third_party/icu/source/i18n/double-conversion-bignum.cpp",
- "third_party/icu/source/i18n/double-conversion-cached-powers.cpp",
- "third_party/icu/source/i18n/double-conversion-double-to-string.cpp",
- "third_party/icu/source/i18n/double-conversion-fast-dtoa.cpp",
- "third_party/icu/source/i18n/double-conversion-string-to-double.cpp",
- "third_party/icu/source/i18n/double-conversion-strtod.cpp",
- "third_party/icu/source/i18n/dtfmtsym.cpp",
- "third_party/icu/source/i18n/dtitvfmt.cpp",
- "third_party/icu/source/i18n/dtitvinf.cpp",
- "third_party/icu/source/i18n/dtptngen.cpp",
- "third_party/icu/source/i18n/dtrule.cpp",
- "third_party/icu/source/i18n/erarules.cpp",
- "third_party/icu/source/i18n/esctrn.cpp",
- "third_party/icu/source/i18n/ethpccal.cpp",
- "third_party/icu/source/i18n/fmtable.cpp",
- "third_party/icu/source/i18n/fmtable_cnv.cpp",
- "third_party/icu/source/i18n/format.cpp",
- "third_party/icu/source/i18n/formatted_string_builder.cpp",
- "third_party/icu/source/i18n/formattedval_iterimpl.cpp",
- "third_party/icu/source/i18n/formattedval_sbimpl.cpp",
- "third_party/icu/source/i18n/formattedvalue.cpp",
- "third_party/icu/source/i18n/fphdlimp.cpp",
- "third_party/icu/source/i18n/fpositer.cpp",
- "third_party/icu/source/i18n/funcrepl.cpp",
- "third_party/icu/source/i18n/gender.cpp",
- "third_party/icu/source/i18n/gregocal.cpp",
- "third_party/icu/source/i18n/gregoimp.cpp",
- "third_party/icu/source/i18n/hebrwcal.cpp",
- "third_party/icu/source/i18n/indiancal.cpp",
- "third_party/icu/source/i18n/inputext.cpp",
- "third_party/icu/source/i18n/islamcal.cpp",
- "third_party/icu/source/i18n/japancal.cpp",
- "third_party/icu/source/i18n/listformatter.cpp",
- "third_party/icu/source/i18n/measfmt.cpp",
- "third_party/icu/source/i18n/measunit.cpp",
- "third_party/icu/source/i18n/measunit_extra.cpp",
- "third_party/icu/source/i18n/measure.cpp",
- "third_party/icu/source/i18n/msgfmt.cpp",
- "third_party/icu/source/i18n/name2uni.cpp",
- "third_party/icu/source/i18n/nfrs.cpp",
- "third_party/icu/source/i18n/nfrule.cpp",
- "third_party/icu/source/i18n/nfsubs.cpp",
- "third_party/icu/source/i18n/nortrans.cpp",
- "third_party/icu/source/i18n/nultrans.cpp",
- "third_party/icu/source/i18n/number_affixutils.cpp",
- "third_party/icu/source/i18n/number_asformat.cpp",
- "third_party/icu/source/i18n/number_capi.cpp",
- "third_party/icu/source/i18n/number_compact.cpp",
- "third_party/icu/source/i18n/number_currencysymbols.cpp",
- "third_party/icu/source/i18n/number_decimalquantity.cpp",
- "third_party/icu/source/i18n/number_decimfmtprops.cpp",
- "third_party/icu/source/i18n/number_fluent.cpp",
- "third_party/icu/source/i18n/number_formatimpl.cpp",
- "third_party/icu/source/i18n/number_grouping.cpp",
- "third_party/icu/source/i18n/number_integerwidth.cpp",
- "third_party/icu/source/i18n/number_longnames.cpp",
- "third_party/icu/source/i18n/number_mapper.cpp",
- "third_party/icu/source/i18n/number_modifiers.cpp",
- "third_party/icu/source/i18n/number_multiplier.cpp",
- "third_party/icu/source/i18n/number_notation.cpp",
- "third_party/icu/source/i18n/number_output.cpp",
- "third_party/icu/source/i18n/number_padding.cpp",
- "third_party/icu/source/i18n/number_patternmodifier.cpp",
- "third_party/icu/source/i18n/number_patternstring.cpp",
- "third_party/icu/source/i18n/number_rounding.cpp",
- "third_party/icu/source/i18n/number_scientific.cpp",
- "third_party/icu/source/i18n/number_skeletons.cpp",
- "third_party/icu/source/i18n/number_symbolswrapper.cpp",
- "third_party/icu/source/i18n/number_usageprefs.cpp",
- "third_party/icu/source/i18n/number_utils.cpp",
- "third_party/icu/source/i18n/numfmt.cpp",
- "third_party/icu/source/i18n/numparse_affixes.cpp",
- "third_party/icu/source/i18n/numparse_compositions.cpp",
- "third_party/icu/source/i18n/numparse_currency.cpp",
- "third_party/icu/source/i18n/numparse_decimal.cpp",
- "third_party/icu/source/i18n/numparse_impl.cpp",
- "third_party/icu/source/i18n/numparse_parsednumber.cpp",
- "third_party/icu/source/i18n/numparse_scientific.cpp",
- "third_party/icu/source/i18n/numparse_symbols.cpp",
- "third_party/icu/source/i18n/numparse_validators.cpp",
- "third_party/icu/source/i18n/numrange_capi.cpp",
- "third_party/icu/source/i18n/numrange_fluent.cpp",
- "third_party/icu/source/i18n/numrange_impl.cpp",
- "third_party/icu/source/i18n/numsys.cpp",
- "third_party/icu/source/i18n/olsontz.cpp",
- "third_party/icu/source/i18n/persncal.cpp",
- "third_party/icu/source/i18n/pluralranges.cpp",
- "third_party/icu/source/i18n/plurfmt.cpp",
- "third_party/icu/source/i18n/plurrule.cpp",
- "third_party/icu/source/i18n/quant.cpp",
- "third_party/icu/source/i18n/quantityformatter.cpp",
- "third_party/icu/source/i18n/rbnf.cpp",
- "third_party/icu/source/i18n/rbt.cpp",
- "third_party/icu/source/i18n/rbt_data.cpp",
- "third_party/icu/source/i18n/rbt_pars.cpp",
- "third_party/icu/source/i18n/rbt_rule.cpp",
- "third_party/icu/source/i18n/rbt_set.cpp",
- "third_party/icu/source/i18n/rbtz.cpp",
- "third_party/icu/source/i18n/regexcmp.cpp",
- "third_party/icu/source/i18n/regeximp.cpp",
- "third_party/icu/source/i18n/regexst.cpp",
- "third_party/icu/source/i18n/regextxt.cpp",
- "third_party/icu/source/i18n/region.cpp",
- "third_party/icu/source/i18n/reldatefmt.cpp",
- "third_party/icu/source/i18n/reldtfmt.cpp",
- "third_party/icu/source/i18n/rematch.cpp",
- "third_party/icu/source/i18n/remtrans.cpp",
- "third_party/icu/source/i18n/repattrn.cpp",
- "third_party/icu/source/i18n/rulebasedcollator.cpp",
- "third_party/icu/source/i18n/scientificnumberformatter.cpp",
- "third_party/icu/source/i18n/scriptset.cpp",
- "third_party/icu/source/i18n/search.cpp",
- "third_party/icu/source/i18n/selfmt.cpp",
- "third_party/icu/source/i18n/sharedbreakiterator.cpp",
- "third_party/icu/source/i18n/simpletz.cpp",
- "third_party/icu/source/i18n/smpdtfmt.cpp",
- "third_party/icu/source/i18n/smpdtfst.cpp",
- "third_party/icu/source/i18n/sortkey.cpp",
- "third_party/icu/source/i18n/standardplural.cpp",
- "third_party/icu/source/i18n/string_segment.cpp",
- "third_party/icu/source/i18n/strmatch.cpp",
- "third_party/icu/source/i18n/strrepl.cpp",
- "third_party/icu/source/i18n/stsearch.cpp",
- "third_party/icu/source/i18n/taiwncal.cpp",
- "third_party/icu/source/i18n/timezone.cpp",
- "third_party/icu/source/i18n/titletrn.cpp",
- "third_party/icu/source/i18n/tmunit.cpp",
- "third_party/icu/source/i18n/tmutamt.cpp",
- "third_party/icu/source/i18n/tmutfmt.cpp",
- "third_party/icu/source/i18n/tolowtrn.cpp",
- "third_party/icu/source/i18n/toupptrn.cpp",
- "third_party/icu/source/i18n/translit.cpp",
- "third_party/icu/source/i18n/transreg.cpp",
- "third_party/icu/source/i18n/tridpars.cpp",
- "third_party/icu/source/i18n/tzfmt.cpp",
- "third_party/icu/source/i18n/tzgnames.cpp",
- "third_party/icu/source/i18n/tznames.cpp",
- "third_party/icu/source/i18n/tznames_impl.cpp",
- "third_party/icu/source/i18n/tzrule.cpp",
- "third_party/icu/source/i18n/tztrans.cpp",
- "third_party/icu/source/i18n/ucal.cpp",
- "third_party/icu/source/i18n/ucln_in.cpp",
- "third_party/icu/source/i18n/ucol.cpp",
- "third_party/icu/source/i18n/ucol_res.cpp",
- "third_party/icu/source/i18n/ucol_sit.cpp",
- "third_party/icu/source/i18n/ucoleitr.cpp",
- "third_party/icu/source/i18n/ucsdet.cpp",
- "third_party/icu/source/i18n/udat.cpp",
- "third_party/icu/source/i18n/udateintervalformat.cpp",
- "third_party/icu/source/i18n/udatpg.cpp",
- "third_party/icu/source/i18n/ufieldpositer.cpp",
- "third_party/icu/source/i18n/uitercollationiterator.cpp",
- "third_party/icu/source/i18n/ulistformatter.cpp",
- "third_party/icu/source/i18n/ulocdata.cpp",
- "third_party/icu/source/i18n/umsg.cpp",
- "third_party/icu/source/i18n/unesctrn.cpp",
- "third_party/icu/source/i18n/uni2name.cpp",
- "third_party/icu/source/i18n/units_complexconverter.cpp",
- "third_party/icu/source/i18n/units_converter.cpp",
- "third_party/icu/source/i18n/units_data.cpp",
- "third_party/icu/source/i18n/units_router.cpp",
- "third_party/icu/source/i18n/unum.cpp",
- "third_party/icu/source/i18n/unumsys.cpp",
- "third_party/icu/source/i18n/upluralrules.cpp",
- "third_party/icu/source/i18n/uregex.cpp",
- "third_party/icu/source/i18n/uregexc.cpp",
- "third_party/icu/source/i18n/uregion.cpp",
- "third_party/icu/source/i18n/usearch.cpp",
- "third_party/icu/source/i18n/uspoof.cpp",
- "third_party/icu/source/i18n/uspoof_build.cpp",
- "third_party/icu/source/i18n/uspoof_conf.cpp",
- "third_party/icu/source/i18n/uspoof_impl.cpp",
- "third_party/icu/source/i18n/utf16collationiterator.cpp",
- "third_party/icu/source/i18n/utf8collationiterator.cpp",
- "third_party/icu/source/i18n/utmscale.cpp",
- "third_party/icu/source/i18n/utrans.cpp",
- "third_party/icu/source/i18n/vtzone.cpp",
- "third_party/icu/source/i18n/vzone.cpp",
- "third_party/icu/source/i18n/windtfmt.cpp",
- "third_party/icu/source/i18n/winnmfmt.cpp",
- "third_party/icu/source/i18n/wintzimpl.cpp",
- "third_party/icu/source/i18n/zonemeta.cpp",
- "third_party/icu/source/i18n/zrule.cpp",
- "third_party/icu/source/i18n/ztrans.cpp",
- ],
- static_libs: [
- "cronet_aml_third_party_icu_icuuc_private",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_DLOPEN=0",
- "-DHAVE_SYS_UIO_H",
- "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-DUCONFIG_ONLY_HTML_CONVERSION=1",
- "-DUCONFIG_USE_WINDOWS_LCID_MAPPING_API=0",
- "-DUSE_CHROMIUM_ICU=1",
- "-DU_CHARSET_IS_UTF8=1",
- "-DU_ENABLE_DYLOAD=0",
- "-DU_ENABLE_RESOURCE_TRACING=0",
- "-DU_ENABLE_TRACING=1",
- "-DU_I18N_IMPLEMENTATION",
- "-DU_STATIC_IMPLEMENTATION",
- "-DU_USING_ICU_NAMESPACE=0",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/icu/source/common/",
- "third_party/icu/source/i18n/",
- ],
- cpp_std: "c++17",
- rtti: true,
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/icu:icuuc_private
-cc_library_static {
- name: "cronet_aml_third_party_icu_icuuc_private",
- srcs: [
- "third_party/icu/source/common/appendable.cpp",
- "third_party/icu/source/common/bmpset.cpp",
- "third_party/icu/source/common/brkeng.cpp",
- "third_party/icu/source/common/brkiter.cpp",
- "third_party/icu/source/common/bytesinkutil.cpp",
- "third_party/icu/source/common/bytestream.cpp",
- "third_party/icu/source/common/bytestrie.cpp",
- "third_party/icu/source/common/bytestriebuilder.cpp",
- "third_party/icu/source/common/bytestrieiterator.cpp",
- "third_party/icu/source/common/caniter.cpp",
- "third_party/icu/source/common/characterproperties.cpp",
- "third_party/icu/source/common/chariter.cpp",
- "third_party/icu/source/common/charstr.cpp",
- "third_party/icu/source/common/cmemory.cpp",
- "third_party/icu/source/common/cstr.cpp",
- "third_party/icu/source/common/cstring.cpp",
- "third_party/icu/source/common/cwchar.cpp",
- "third_party/icu/source/common/dictbe.cpp",
- "third_party/icu/source/common/dictionarydata.cpp",
- "third_party/icu/source/common/dtintrv.cpp",
- "third_party/icu/source/common/edits.cpp",
- "third_party/icu/source/common/emojiprops.cpp",
- "third_party/icu/source/common/errorcode.cpp",
- "third_party/icu/source/common/filteredbrk.cpp",
- "third_party/icu/source/common/filterednormalizer2.cpp",
- "third_party/icu/source/common/icudataver.cpp",
- "third_party/icu/source/common/icuplug.cpp",
- "third_party/icu/source/common/loadednormalizer2impl.cpp",
- "third_party/icu/source/common/localebuilder.cpp",
- "third_party/icu/source/common/localematcher.cpp",
- "third_party/icu/source/common/localeprioritylist.cpp",
- "third_party/icu/source/common/locavailable.cpp",
- "third_party/icu/source/common/locbased.cpp",
- "third_party/icu/source/common/locdispnames.cpp",
- "third_party/icu/source/common/locdistance.cpp",
- "third_party/icu/source/common/locdspnm.cpp",
- "third_party/icu/source/common/locid.cpp",
- "third_party/icu/source/common/loclikely.cpp",
- "third_party/icu/source/common/loclikelysubtags.cpp",
- "third_party/icu/source/common/locmap.cpp",
- "third_party/icu/source/common/locresdata.cpp",
- "third_party/icu/source/common/locutil.cpp",
- "third_party/icu/source/common/lsr.cpp",
- "third_party/icu/source/common/lstmbe.cpp",
- "third_party/icu/source/common/messagepattern.cpp",
- "third_party/icu/source/common/normalizer2.cpp",
- "third_party/icu/source/common/normalizer2impl.cpp",
- "third_party/icu/source/common/normlzr.cpp",
- "third_party/icu/source/common/parsepos.cpp",
- "third_party/icu/source/common/patternprops.cpp",
- "third_party/icu/source/common/pluralmap.cpp",
- "third_party/icu/source/common/propname.cpp",
- "third_party/icu/source/common/propsvec.cpp",
- "third_party/icu/source/common/punycode.cpp",
- "third_party/icu/source/common/putil.cpp",
- "third_party/icu/source/common/rbbi.cpp",
- "third_party/icu/source/common/rbbi_cache.cpp",
- "third_party/icu/source/common/rbbidata.cpp",
- "third_party/icu/source/common/rbbinode.cpp",
- "third_party/icu/source/common/rbbirb.cpp",
- "third_party/icu/source/common/rbbiscan.cpp",
- "third_party/icu/source/common/rbbisetb.cpp",
- "third_party/icu/source/common/rbbistbl.cpp",
- "third_party/icu/source/common/rbbitblb.cpp",
- "third_party/icu/source/common/resbund.cpp",
- "third_party/icu/source/common/resbund_cnv.cpp",
- "third_party/icu/source/common/resource.cpp",
- "third_party/icu/source/common/restrace.cpp",
- "third_party/icu/source/common/ruleiter.cpp",
- "third_party/icu/source/common/schriter.cpp",
- "third_party/icu/source/common/serv.cpp",
- "third_party/icu/source/common/servlk.cpp",
- "third_party/icu/source/common/servlkf.cpp",
- "third_party/icu/source/common/servls.cpp",
- "third_party/icu/source/common/servnotf.cpp",
- "third_party/icu/source/common/servrbf.cpp",
- "third_party/icu/source/common/servslkf.cpp",
- "third_party/icu/source/common/sharedobject.cpp",
- "third_party/icu/source/common/simpleformatter.cpp",
- "third_party/icu/source/common/static_unicode_sets.cpp",
- "third_party/icu/source/common/stringpiece.cpp",
- "third_party/icu/source/common/stringtriebuilder.cpp",
- "third_party/icu/source/common/uarrsort.cpp",
- "third_party/icu/source/common/ubidi.cpp",
- "third_party/icu/source/common/ubidi_props.cpp",
- "third_party/icu/source/common/ubidiln.cpp",
- "third_party/icu/source/common/ubiditransform.cpp",
- "third_party/icu/source/common/ubidiwrt.cpp",
- "third_party/icu/source/common/ubrk.cpp",
- "third_party/icu/source/common/ucase.cpp",
- "third_party/icu/source/common/ucasemap.cpp",
- "third_party/icu/source/common/ucasemap_titlecase_brkiter.cpp",
- "third_party/icu/source/common/ucat.cpp",
- "third_party/icu/source/common/uchar.cpp",
- "third_party/icu/source/common/ucharstrie.cpp",
- "third_party/icu/source/common/ucharstriebuilder.cpp",
- "third_party/icu/source/common/ucharstrieiterator.cpp",
- "third_party/icu/source/common/uchriter.cpp",
- "third_party/icu/source/common/ucln_cmn.cpp",
- "third_party/icu/source/common/ucmndata.cpp",
- "third_party/icu/source/common/ucnv.cpp",
- "third_party/icu/source/common/ucnv2022.cpp",
- "third_party/icu/source/common/ucnv_bld.cpp",
- "third_party/icu/source/common/ucnv_cb.cpp",
- "third_party/icu/source/common/ucnv_cnv.cpp",
- "third_party/icu/source/common/ucnv_ct.cpp",
- "third_party/icu/source/common/ucnv_err.cpp",
- "third_party/icu/source/common/ucnv_ext.cpp",
- "third_party/icu/source/common/ucnv_io.cpp",
- "third_party/icu/source/common/ucnv_lmb.cpp",
- "third_party/icu/source/common/ucnv_set.cpp",
- "third_party/icu/source/common/ucnv_u16.cpp",
- "third_party/icu/source/common/ucnv_u32.cpp",
- "third_party/icu/source/common/ucnv_u7.cpp",
- "third_party/icu/source/common/ucnv_u8.cpp",
- "third_party/icu/source/common/ucnvbocu.cpp",
- "third_party/icu/source/common/ucnvdisp.cpp",
- "third_party/icu/source/common/ucnvhz.cpp",
- "third_party/icu/source/common/ucnvisci.cpp",
- "third_party/icu/source/common/ucnvlat1.cpp",
- "third_party/icu/source/common/ucnvmbcs.cpp",
- "third_party/icu/source/common/ucnvscsu.cpp",
- "third_party/icu/source/common/ucnvsel.cpp",
- "third_party/icu/source/common/ucol_swp.cpp",
- "third_party/icu/source/common/ucptrie.cpp",
- "third_party/icu/source/common/ucurr.cpp",
- "third_party/icu/source/common/udata.cpp",
- "third_party/icu/source/common/udatamem.cpp",
- "third_party/icu/source/common/udataswp.cpp",
- "third_party/icu/source/common/uenum.cpp",
- "third_party/icu/source/common/uhash.cpp",
- "third_party/icu/source/common/uhash_us.cpp",
- "third_party/icu/source/common/uidna.cpp",
- "third_party/icu/source/common/uinit.cpp",
- "third_party/icu/source/common/uinvchar.cpp",
- "third_party/icu/source/common/uiter.cpp",
- "third_party/icu/source/common/ulist.cpp",
- "third_party/icu/source/common/uloc.cpp",
- "third_party/icu/source/common/uloc_keytype.cpp",
- "third_party/icu/source/common/uloc_tag.cpp",
- "third_party/icu/source/common/umapfile.cpp",
- "third_party/icu/source/common/umath.cpp",
- "third_party/icu/source/common/umutablecptrie.cpp",
- "third_party/icu/source/common/umutex.cpp",
- "third_party/icu/source/common/unames.cpp",
- "third_party/icu/source/common/unifiedcache.cpp",
- "third_party/icu/source/common/unifilt.cpp",
- "third_party/icu/source/common/unifunct.cpp",
- "third_party/icu/source/common/uniset.cpp",
- "third_party/icu/source/common/uniset_closure.cpp",
- "third_party/icu/source/common/uniset_props.cpp",
- "third_party/icu/source/common/unisetspan.cpp",
- "third_party/icu/source/common/unistr.cpp",
- "third_party/icu/source/common/unistr_case.cpp",
- "third_party/icu/source/common/unistr_case_locale.cpp",
- "third_party/icu/source/common/unistr_cnv.cpp",
- "third_party/icu/source/common/unistr_props.cpp",
- "third_party/icu/source/common/unistr_titlecase_brkiter.cpp",
- "third_party/icu/source/common/unorm.cpp",
- "third_party/icu/source/common/unormcmp.cpp",
- "third_party/icu/source/common/uobject.cpp",
- "third_party/icu/source/common/uprops.cpp",
- "third_party/icu/source/common/ures_cnv.cpp",
- "third_party/icu/source/common/uresbund.cpp",
- "third_party/icu/source/common/uresdata.cpp",
- "third_party/icu/source/common/usc_impl.cpp",
- "third_party/icu/source/common/uscript.cpp",
- "third_party/icu/source/common/uscript_props.cpp",
- "third_party/icu/source/common/uset.cpp",
- "third_party/icu/source/common/uset_props.cpp",
- "third_party/icu/source/common/usetiter.cpp",
- "third_party/icu/source/common/ushape.cpp",
- "third_party/icu/source/common/usprep.cpp",
- "third_party/icu/source/common/ustack.cpp",
- "third_party/icu/source/common/ustr_cnv.cpp",
- "third_party/icu/source/common/ustr_titlecase_brkiter.cpp",
- "third_party/icu/source/common/ustr_wcs.cpp",
- "third_party/icu/source/common/ustrcase.cpp",
- "third_party/icu/source/common/ustrcase_locale.cpp",
- "third_party/icu/source/common/ustrenum.cpp",
- "third_party/icu/source/common/ustrfmt.cpp",
- "third_party/icu/source/common/ustring.cpp",
- "third_party/icu/source/common/ustrtrns.cpp",
- "third_party/icu/source/common/utext.cpp",
- "third_party/icu/source/common/utf_impl.cpp",
- "third_party/icu/source/common/util.cpp",
- "third_party/icu/source/common/util_props.cpp",
- "third_party/icu/source/common/utrace.cpp",
- "third_party/icu/source/common/utrie.cpp",
- "third_party/icu/source/common/utrie2.cpp",
- "third_party/icu/source/common/utrie2_builder.cpp",
- "third_party/icu/source/common/utrie_swap.cpp",
- "third_party/icu/source/common/uts46.cpp",
- "third_party/icu/source/common/utypes.cpp",
- "third_party/icu/source/common/uvector.cpp",
- "third_party/icu/source/common/uvectr32.cpp",
- "third_party/icu/source/common/uvectr64.cpp",
- "third_party/icu/source/common/wintz.cpp",
- "third_party/icu/source/stubdata/stubdata.cpp",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_DLOPEN=0",
- "-DHAVE_SYS_UIO_H",
- "-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-DUCONFIG_ONLY_HTML_CONVERSION=1",
- "-DUCONFIG_USE_WINDOWS_LCID_MAPPING_API=0",
- "-DUSE_CHROMIUM_ICU=1",
- "-DU_CHARSET_IS_UTF8=1",
- "-DU_COMMON_IMPLEMENTATION",
- "-DU_ENABLE_DYLOAD=0",
- "-DU_ENABLE_RESOURCE_TRACING=0",
- "-DU_ENABLE_TRACING=1",
- "-DU_ICUDATAENTRY_IN_COMMON",
- "-DU_STATIC_IMPLEMENTATION",
- "-DU_USING_ICU_NAMESPACE=0",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/icu/source/common/",
- "third_party/icu/source/i18n/",
- ],
- cpp_std: "c++17",
- rtti: true,
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/libevent:libevent
-cc_library_static {
- name: "cronet_aml_third_party_libevent_libevent",
- srcs: [
- "third_party/libevent/buffer.c",
- "third_party/libevent/epoll.c",
- "third_party/libevent/evbuffer.c",
- "third_party/libevent/evdns.c",
- "third_party/libevent/event.c",
- "third_party/libevent/event_tagging.c",
- "third_party/libevent/evrpc.c",
- "third_party/libevent/evutil.c",
- "third_party/libevent/http.c",
- "third_party/libevent/log.c",
- "third_party/libevent/poll.c",
- "third_party/libevent/select.c",
- "third_party/libevent/signal.c",
- "third_party/libevent/strlcpy.c",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_CONFIG_H",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/libevent/android/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/metrics_proto:metrics_proto
-cc_genrule {
- name: "cronet_aml_third_party_metrics_proto_metrics_proto_gen",
- srcs: [
- "third_party/metrics_proto/call_stack_profile.proto",
- "third_party/metrics_proto/cast_logs.proto",
- "third_party/metrics_proto/chrome_os_app_list_launch_event.proto",
- "third_party/metrics_proto/chrome_searchbox_stats.proto",
- "third_party/metrics_proto/chrome_user_metrics_extension.proto",
- "third_party/metrics_proto/custom_tab_session.proto",
- "third_party/metrics_proto/execution_context.proto",
- "third_party/metrics_proto/extension_install.proto",
- "third_party/metrics_proto/histogram_event.proto",
- "third_party/metrics_proto/omnibox_event.proto",
- "third_party/metrics_proto/omnibox_focus_type.proto",
- "third_party/metrics_proto/omnibox_input_type.proto",
- "third_party/metrics_proto/perf_data.proto",
- "third_party/metrics_proto/perf_stat.proto",
- "third_party/metrics_proto/printer_event.proto",
- "third_party/metrics_proto/reporting_info.proto",
- "third_party/metrics_proto/sampled_profile.proto",
- "third_party/metrics_proto/structured_data.proto",
- "third_party/metrics_proto/system_profile.proto",
- "third_party/metrics_proto/trace_log.proto",
- "third_party/metrics_proto/translate_event.proto",
- "third_party/metrics_proto/ukm/aggregate.proto",
- "third_party/metrics_proto/ukm/entry.proto",
- "third_party/metrics_proto/ukm/report.proto",
- "third_party/metrics_proto/ukm/source.proto",
- "third_party/metrics_proto/user_action_event.proto",
- "third_party/metrics_proto/user_demographics.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/third_party/metrics_proto --cpp_out=lite=true:$(genDir)/external/cronet/third_party/metrics_proto/ $(in)",
- out: [
- "external/cronet/third_party/metrics_proto/call_stack_profile.pb.cc",
- "external/cronet/third_party/metrics_proto/cast_logs.pb.cc",
- "external/cronet/third_party/metrics_proto/chrome_os_app_list_launch_event.pb.cc",
- "external/cronet/third_party/metrics_proto/chrome_searchbox_stats.pb.cc",
- "external/cronet/third_party/metrics_proto/chrome_user_metrics_extension.pb.cc",
- "external/cronet/third_party/metrics_proto/custom_tab_session.pb.cc",
- "external/cronet/third_party/metrics_proto/execution_context.pb.cc",
- "external/cronet/third_party/metrics_proto/extension_install.pb.cc",
- "external/cronet/third_party/metrics_proto/histogram_event.pb.cc",
- "external/cronet/third_party/metrics_proto/omnibox_event.pb.cc",
- "external/cronet/third_party/metrics_proto/omnibox_focus_type.pb.cc",
- "external/cronet/third_party/metrics_proto/omnibox_input_type.pb.cc",
- "external/cronet/third_party/metrics_proto/perf_data.pb.cc",
- "external/cronet/third_party/metrics_proto/perf_stat.pb.cc",
- "external/cronet/third_party/metrics_proto/printer_event.pb.cc",
- "external/cronet/third_party/metrics_proto/reporting_info.pb.cc",
- "external/cronet/third_party/metrics_proto/sampled_profile.pb.cc",
- "external/cronet/third_party/metrics_proto/structured_data.pb.cc",
- "external/cronet/third_party/metrics_proto/system_profile.pb.cc",
- "external/cronet/third_party/metrics_proto/trace_log.pb.cc",
- "external/cronet/third_party/metrics_proto/translate_event.pb.cc",
- "external/cronet/third_party/metrics_proto/ukm/aggregate.pb.cc",
- "external/cronet/third_party/metrics_proto/ukm/entry.pb.cc",
- "external/cronet/third_party/metrics_proto/ukm/report.pb.cc",
- "external/cronet/third_party/metrics_proto/ukm/source.pb.cc",
- "external/cronet/third_party/metrics_proto/user_action_event.pb.cc",
- "external/cronet/third_party/metrics_proto/user_demographics.pb.cc",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //third_party/metrics_proto:metrics_proto
-cc_genrule {
- name: "cronet_aml_third_party_metrics_proto_metrics_proto_gen_headers",
- srcs: [
- "third_party/metrics_proto/call_stack_profile.proto",
- "third_party/metrics_proto/cast_logs.proto",
- "third_party/metrics_proto/chrome_os_app_list_launch_event.proto",
- "third_party/metrics_proto/chrome_searchbox_stats.proto",
- "third_party/metrics_proto/chrome_user_metrics_extension.proto",
- "third_party/metrics_proto/custom_tab_session.proto",
- "third_party/metrics_proto/execution_context.proto",
- "third_party/metrics_proto/extension_install.proto",
- "third_party/metrics_proto/histogram_event.proto",
- "third_party/metrics_proto/omnibox_event.proto",
- "third_party/metrics_proto/omnibox_focus_type.proto",
- "third_party/metrics_proto/omnibox_input_type.proto",
- "third_party/metrics_proto/perf_data.proto",
- "third_party/metrics_proto/perf_stat.proto",
- "third_party/metrics_proto/printer_event.proto",
- "third_party/metrics_proto/reporting_info.proto",
- "third_party/metrics_proto/sampled_profile.proto",
- "third_party/metrics_proto/structured_data.proto",
- "third_party/metrics_proto/system_profile.proto",
- "third_party/metrics_proto/trace_log.proto",
- "third_party/metrics_proto/translate_event.proto",
- "third_party/metrics_proto/ukm/aggregate.proto",
- "third_party/metrics_proto/ukm/entry.proto",
- "third_party/metrics_proto/ukm/report.proto",
- "third_party/metrics_proto/ukm/source.proto",
- "third_party/metrics_proto/user_action_event.proto",
- "third_party/metrics_proto/user_demographics.proto",
- ],
- tools: [
- "cronet_aml_third_party_protobuf_protoc",
- ],
- cmd: "$(location cronet_aml_third_party_protobuf_protoc) --proto_path=external/cronet/third_party/metrics_proto --cpp_out=lite=true:$(genDir)/external/cronet/third_party/metrics_proto/ $(in)",
- out: [
- "external/cronet/third_party/metrics_proto/call_stack_profile.pb.h",
- "external/cronet/third_party/metrics_proto/cast_logs.pb.h",
- "external/cronet/third_party/metrics_proto/chrome_os_app_list_launch_event.pb.h",
- "external/cronet/third_party/metrics_proto/chrome_searchbox_stats.pb.h",
- "external/cronet/third_party/metrics_proto/chrome_user_metrics_extension.pb.h",
- "external/cronet/third_party/metrics_proto/custom_tab_session.pb.h",
- "external/cronet/third_party/metrics_proto/execution_context.pb.h",
- "external/cronet/third_party/metrics_proto/extension_install.pb.h",
- "external/cronet/third_party/metrics_proto/histogram_event.pb.h",
- "external/cronet/third_party/metrics_proto/omnibox_event.pb.h",
- "external/cronet/third_party/metrics_proto/omnibox_focus_type.pb.h",
- "external/cronet/third_party/metrics_proto/omnibox_input_type.pb.h",
- "external/cronet/third_party/metrics_proto/perf_data.pb.h",
- "external/cronet/third_party/metrics_proto/perf_stat.pb.h",
- "external/cronet/third_party/metrics_proto/printer_event.pb.h",
- "external/cronet/third_party/metrics_proto/reporting_info.pb.h",
- "external/cronet/third_party/metrics_proto/sampled_profile.pb.h",
- "external/cronet/third_party/metrics_proto/structured_data.pb.h",
- "external/cronet/third_party/metrics_proto/system_profile.pb.h",
- "external/cronet/third_party/metrics_proto/trace_log.pb.h",
- "external/cronet/third_party/metrics_proto/translate_event.pb.h",
- "external/cronet/third_party/metrics_proto/ukm/aggregate.pb.h",
- "external/cronet/third_party/metrics_proto/ukm/entry.pb.h",
- "external/cronet/third_party/metrics_proto/ukm/report.pb.h",
- "external/cronet/third_party/metrics_proto/ukm/source.pb.h",
- "external/cronet/third_party/metrics_proto/user_action_event.pb.h",
- "external/cronet/third_party/metrics_proto/user_demographics.pb.h",
- ],
- export_include_dirs: [
- ".",
- "protos",
- "third_party/metrics_proto",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //third_party/modp_b64:modp_b64
-cc_library_static {
- name: "cronet_aml_third_party_modp_b64_modp_b64",
- srcs: [
- "third_party/modp_b64/modp_b64.cc",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/protobuf:protobuf_full
-cc_library_static {
- name: "cronet_aml_third_party_protobuf_protobuf_full",
- srcs: [
- "third_party/protobuf/src/google/protobuf/any.cc",
- "third_party/protobuf/src/google/protobuf/any.pb.cc",
- "third_party/protobuf/src/google/protobuf/any_lite.cc",
- "third_party/protobuf/src/google/protobuf/api.pb.cc",
- "third_party/protobuf/src/google/protobuf/arena.cc",
- "third_party/protobuf/src/google/protobuf/arenastring.cc",
- "third_party/protobuf/src/google/protobuf/arenaz_sampler.cc",
- "third_party/protobuf/src/google/protobuf/compiler/importer.cc",
- "third_party/protobuf/src/google/protobuf/compiler/parser.cc",
- "third_party/protobuf/src/google/protobuf/descriptor.cc",
- "third_party/protobuf/src/google/protobuf/descriptor.pb.cc",
- "third_party/protobuf/src/google/protobuf/descriptor_database.cc",
- "third_party/protobuf/src/google/protobuf/duration.pb.cc",
- "third_party/protobuf/src/google/protobuf/dynamic_message.cc",
- "third_party/protobuf/src/google/protobuf/empty.pb.cc",
- "third_party/protobuf/src/google/protobuf/extension_set.cc",
- "third_party/protobuf/src/google/protobuf/extension_set_heavy.cc",
- "third_party/protobuf/src/google/protobuf/field_mask.pb.cc",
- "third_party/protobuf/src/google/protobuf/generated_enum_util.cc",
- "third_party/protobuf/src/google/protobuf/generated_message_bases.cc",
- "third_party/protobuf/src/google/protobuf/generated_message_reflection.cc",
- "third_party/protobuf/src/google/protobuf/generated_message_tctable_full.cc",
- "third_party/protobuf/src/google/protobuf/generated_message_tctable_lite.cc",
- "third_party/protobuf/src/google/protobuf/generated_message_util.cc",
- "third_party/protobuf/src/google/protobuf/implicit_weak_message.cc",
- "third_party/protobuf/src/google/protobuf/inlined_string_field.cc",
- "third_party/protobuf/src/google/protobuf/io/coded_stream.cc",
- "third_party/protobuf/src/google/protobuf/io/gzip_stream.cc",
- "third_party/protobuf/src/google/protobuf/io/io_win32.cc",
- "third_party/protobuf/src/google/protobuf/io/printer.cc",
- "third_party/protobuf/src/google/protobuf/io/strtod.cc",
- "third_party/protobuf/src/google/protobuf/io/tokenizer.cc",
- "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.cc",
- "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc",
- "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
- "third_party/protobuf/src/google/protobuf/map.cc",
- "third_party/protobuf/src/google/protobuf/map_field.cc",
- "third_party/protobuf/src/google/protobuf/message.cc",
- "third_party/protobuf/src/google/protobuf/message_lite.cc",
- "third_party/protobuf/src/google/protobuf/parse_context.cc",
- "third_party/protobuf/src/google/protobuf/reflection_ops.cc",
- "third_party/protobuf/src/google/protobuf/repeated_field.cc",
- "third_party/protobuf/src/google/protobuf/repeated_ptr_field.cc",
- "third_party/protobuf/src/google/protobuf/service.cc",
- "third_party/protobuf/src/google/protobuf/source_context.pb.cc",
- "third_party/protobuf/src/google/protobuf/struct.pb.cc",
- "third_party/protobuf/src/google/protobuf/stubs/bytestream.cc",
- "third_party/protobuf/src/google/protobuf/stubs/common.cc",
- "third_party/protobuf/src/google/protobuf/stubs/int128.cc",
- "third_party/protobuf/src/google/protobuf/stubs/status.cc",
- "third_party/protobuf/src/google/protobuf/stubs/statusor.cc",
- "third_party/protobuf/src/google/protobuf/stubs/stringpiece.cc",
- "third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc",
- "third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc",
- "third_party/protobuf/src/google/protobuf/stubs/strutil.cc",
- "third_party/protobuf/src/google/protobuf/stubs/substitute.cc",
- "third_party/protobuf/src/google/protobuf/stubs/time.cc",
- "third_party/protobuf/src/google/protobuf/text_format.cc",
- "third_party/protobuf/src/google/protobuf/timestamp.pb.cc",
- "third_party/protobuf/src/google/protobuf/type.pb.cc",
- "third_party/protobuf/src/google/protobuf/unknown_field_set.cc",
- "third_party/protobuf/src/google/protobuf/util/delimited_message_util.cc",
- "third_party/protobuf/src/google/protobuf/util/field_comparator.cc",
- "third_party/protobuf/src/google/protobuf/util/field_mask_util.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/datapiece.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/error_listener.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/field_mask_utility.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/json_escaping.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/json_objectwriter.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/json_stream_parser.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/object_writer.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/proto_writer.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/type_info.cc",
- "third_party/protobuf/src/google/protobuf/util/internal/utility.cc",
- "third_party/protobuf/src/google/protobuf/util/json_util.cc",
- "third_party/protobuf/src/google/protobuf/util/message_differencer.cc",
- "third_party/protobuf/src/google/protobuf/util/time_util.cc",
- "third_party/protobuf/src/google/protobuf/util/type_resolver_util.cc",
- "third_party/protobuf/src/google/protobuf/wire_format.cc",
- "third_party/protobuf/src/google/protobuf/wire_format_lite.cc",
- "third_party/protobuf/src/google/protobuf/wrappers.pb.cc",
- ],
- shared_libs: [
- "libz",
- ],
- host_supported: true,
- device_supported: false,
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DCR_SYSROOT_KEY=20220331T153654Z-0",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_ZLIB",
- "-DNDEBUG",
- "-DNO_UNWIND_TABLES",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-DUSE_AURA=1",
- "-DUSE_OZONE=1",
- "-DUSE_UDEV",
- "-D_FILE_OFFSET_BITS=64",
- "-D_GNU_SOURCE",
- "-D_LARGEFILE64_SOURCE",
- "-D_LARGEFILE_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-msse3",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++20",
-}
-
-// GN: //third_party/protobuf:protobuf_lite
-cc_library_static {
- name: "cronet_aml_third_party_protobuf_protobuf_lite",
- srcs: [
- "third_party/protobuf/src/google/protobuf/any_lite.cc",
- "third_party/protobuf/src/google/protobuf/arena.cc",
- "third_party/protobuf/src/google/protobuf/arenastring.cc",
- "third_party/protobuf/src/google/protobuf/arenaz_sampler.cc",
- "third_party/protobuf/src/google/protobuf/extension_set.cc",
- "third_party/protobuf/src/google/protobuf/generated_enum_util.cc",
- "third_party/protobuf/src/google/protobuf/generated_message_tctable_lite.cc",
- "third_party/protobuf/src/google/protobuf/generated_message_util.cc",
- "third_party/protobuf/src/google/protobuf/implicit_weak_message.cc",
- "third_party/protobuf/src/google/protobuf/inlined_string_field.cc",
- "third_party/protobuf/src/google/protobuf/io/coded_stream.cc",
- "third_party/protobuf/src/google/protobuf/io/io_win32.cc",
- "third_party/protobuf/src/google/protobuf/io/strtod.cc",
- "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.cc",
- "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc",
- "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
- "third_party/protobuf/src/google/protobuf/map.cc",
- "third_party/protobuf/src/google/protobuf/message_lite.cc",
- "third_party/protobuf/src/google/protobuf/parse_context.cc",
- "third_party/protobuf/src/google/protobuf/repeated_field.cc",
- "third_party/protobuf/src/google/protobuf/repeated_ptr_field.cc",
- "third_party/protobuf/src/google/protobuf/stubs/bytestream.cc",
- "third_party/protobuf/src/google/protobuf/stubs/common.cc",
- "third_party/protobuf/src/google/protobuf/stubs/int128.cc",
- "third_party/protobuf/src/google/protobuf/stubs/status.cc",
- "third_party/protobuf/src/google/protobuf/stubs/statusor.cc",
- "third_party/protobuf/src/google/protobuf/stubs/stringpiece.cc",
- "third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc",
- "third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc",
- "third_party/protobuf/src/google/protobuf/stubs/strutil.cc",
- "third_party/protobuf/src/google/protobuf/stubs/time.cc",
- "third_party/protobuf/src/google/protobuf/wire_format_lite.cc",
- ],
- shared_libs: [
- "liblog",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DHAVE_SYS_UIO_H",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //third_party/protobuf:protoc
-cc_binary {
- name: "cronet_aml_third_party_protobuf_protoc",
- srcs: [
- ":cronet_aml_buildtools_third_party_libc___libc__",
- ":cronet_aml_buildtools_third_party_libc__abi_libc__abi",
- "third_party/protobuf/src/google/protobuf/compiler/main.cc",
- ],
- shared_libs: [
- "libz",
- ],
- static_libs: [
- "cronet_aml_third_party_protobuf_protobuf_full",
- "cronet_aml_third_party_protobuf_protoc_lib",
- ],
- host_supported: true,
- device_supported: false,
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DCR_SYSROOT_KEY=20220331T153654Z-0",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DNDEBUG",
- "-DNO_UNWIND_TABLES",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-DUSE_AURA=1",
- "-DUSE_OZONE=1",
- "-DUSE_UDEV",
- "-D_FILE_OFFSET_BITS=64",
- "-D_GNU_SOURCE",
- "-D_LARGEFILE64_SOURCE",
- "-D_LARGEFILE_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-msse3",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++20",
-}
-
-// GN: //third_party/protobuf:protoc_lib
-cc_library_static {
- name: "cronet_aml_third_party_protobuf_protoc_lib",
- srcs: [
- "third_party/protobuf/src/google/protobuf/compiler/code_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_parse_function_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc",
- "third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_enum.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_field_base.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_helpers.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_map_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_message.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_message_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
- "third_party/protobuf/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_context.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field_lite.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_enum_lite.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_extension_lite.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_generator_factory.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_kotlin_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_map_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_map_field_lite.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_message_builder.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_message_builder_lite.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_message_field_lite.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_message_lite.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_name_resolver.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_shared_code_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/java/java_string_field_lite.cc",
- "third_party/protobuf/src/google/protobuf/compiler/js/js_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/js/well_known_types_embed.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
- "third_party/protobuf/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
- "third_party/protobuf/src/google/protobuf/compiler/php/php_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/plugin.cc",
- "third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc",
- "third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/python/python_helpers.cc",
- "third_party/protobuf/src/google/protobuf/compiler/python/python_pyi_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/ruby/ruby_generator.cc",
- "third_party/protobuf/src/google/protobuf/compiler/subprocess.cc",
- "third_party/protobuf/src/google/protobuf/compiler/zip_writer.cc",
- ],
- shared_libs: [
- "libz",
- ],
- static_libs: [
- "cronet_aml_third_party_protobuf_protobuf_full",
- ],
- host_supported: true,
- device_supported: false,
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DCR_SYSROOT_KEY=20220331T153654Z-0",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DGOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE=0",
- "-DGOOGLE_PROTOBUF_NO_RTTI",
- "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
- "-DHAVE_PTHREAD",
- "-DNDEBUG",
- "-DNO_UNWIND_TABLES",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-DUSE_AURA=1",
- "-DUSE_OZONE=1",
- "-DUSE_UDEV",
- "-D_FILE_OFFSET_BITS=64",
- "-D_GNU_SOURCE",
- "-D_LARGEFILE64_SOURCE",
- "-D_LARGEFILE_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-msse3",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/protobuf/src/",
- ],
- cpp_std: "c++20",
-}
-
-// GN: //url:buildflags
-cc_genrule {
- name: "cronet_aml_url_buildflags",
- cmd: "echo '--flags USE_PLATFORM_ICU_ALTERNATIVES=\"true\"' | " +
- "$(location build/write_buildflag_header.py) --output " +
- "$(out) " +
- "--rulename " +
- "//url:buildflags " +
- "--gen-dir " +
- ". " +
- "--definitions " +
- "/dev/stdin",
- out: [
- "url/buildflags.h",
- ],
- tool_files: [
- "build/write_buildflag_header.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: //url:url
-cc_library_static {
- name: "cronet_aml_url_url",
- srcs: [
- "url/gurl.cc",
- "url/origin.cc",
- "url/scheme_host_port.cc",
- "url/third_party/mozilla/url_parse.cc",
- "url/url_canon.cc",
- "url/url_canon_etc.cc",
- "url/url_canon_filesystemurl.cc",
- "url/url_canon_fileurl.cc",
- "url/url_canon_host.cc",
- "url/url_canon_internal.cc",
- "url/url_canon_ip.cc",
- "url/url_canon_mailtourl.cc",
- "url/url_canon_path.cc",
- "url/url_canon_pathurl.cc",
- "url/url_canon_query.cc",
- "url/url_canon_relative.cc",
- "url/url_canon_stdstring.cc",
- "url/url_canon_stdurl.cc",
- "url/url_constants.cc",
- "url/url_idna_icu_alternatives_android.cc",
- "url/url_parse_file.cc",
- "url/url_util.cc",
- ],
- shared_libs: [
- "libandroid",
- "liblog",
- ],
- static_libs: [
- "cronet_aml_base_allocator_partition_allocator_partition_alloc",
- "cronet_aml_base_base",
- "cronet_aml_base_base_static",
- "cronet_aml_base_third_party_double_conversion_double_conversion",
- "cronet_aml_base_third_party_dynamic_annotations_dynamic_annotations",
- "cronet_aml_third_party_boringssl_boringssl",
- "cronet_aml_third_party_icu_icui18n",
- "cronet_aml_third_party_icu_icuuc_private",
- "cronet_aml_third_party_libevent_libevent",
- "cronet_aml_third_party_modp_b64_modp_b64",
- ],
- generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_url_buildflags",
- "cronet_aml_url_url_jni_headers",
- ],
- export_generated_headers: [
- "cronet_aml_base_debugging_buildflags",
- "cronet_aml_base_logging_buildflags",
- "cronet_aml_build_chromeos_buildflags",
- "cronet_aml_url_buildflags",
- "cronet_aml_url_url_jni_headers",
- ],
- defaults: [
- "cronet_aml_defaults",
- ],
- cflags: [
- "-DANDROID",
- "-DANDROID_NDK_VERSION_ROLL=r23_1",
- "-DCR_CLANG_REVISION=\"llvmorg-16-init-6578-g0d30e92f-2\"",
- "-DCR_LIBCXX_REVISION=64d36e572d3f9719c5d75011a718f33f11126851",
- "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
- "-DHAVE_SYS_UIO_H",
- "-DIS_URL_IMPL",
- "-DNDEBUG",
- "-DNVALGRIND",
- "-DOFFICIAL_BUILD",
- "-D_FORTIFY_SOURCE=2",
- "-D_GNU_SOURCE",
- "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
- "-D__STDC_CONSTANT_MACROS",
- "-D__STDC_FORMAT_MACROS",
- ],
- local_include_dirs: [
- "./",
- "buildtools/third_party/libc++/",
- "buildtools/third_party/libc++/trunk/include",
- "buildtools/third_party/libc++abi/trunk/include",
- "third_party/abseil-cpp/",
- "third_party/boringssl/src/include/",
- ],
- cpp_std: "c++17",
- target: {
- android_x86: {
- cflags: [
- "-msse3",
- ],
- },
- android_x86_64: {
- cflags: [
- "-msse3",
- ],
- },
- },
-}
-
-// GN: //url:url_jni_headers
-cc_genrule {
- name: "cronet_aml_url_url_jni_headers",
- srcs: [
- "url/android/java/src/org/chromium/url/IDNStringUtil.java",
- "url/android/java/src/org/chromium/url/Origin.java",
- ],
- cmd: "$(location base/android/jni_generator/jni_generator.py) --ptr_type " +
- "long " +
- "--output_dir " +
- "$(genDir)/url/url_jni_headers " +
- "--includes " +
- "base/android/jni_generator/jni_generator_helper.h " +
- "--use_proxy_hash " +
- "--output_name " +
- "IDNStringUtil_jni.h " +
- "--output_name " +
- "Origin_jni.h " +
- "--input_file " +
- "$(location url/android/java/src/org/chromium/url/IDNStringUtil.java) " +
- "--input_file " +
- "$(location url/android/java/src/org/chromium/url/Origin.java) " +
- "--package_prefix " +
- "android.net.http.internal",
- out: [
- "url/url_jni_headers/IDNStringUtil_jni.h",
- "url/url_jni_headers/Origin_jni.h",
- ],
- tool_files: [
- "base/android/jni_generator/android_jar.classes",
- "base/android/jni_generator/jni_generator.py",
- "build/android/gyp/util/__init__.py",
- "build/android/gyp/util/build_utils.py",
- "build/gn_helpers.py",
- ],
- apex_available: [
- "com.android.tethering",
- ],
-}
-
-// GN: LICENSE
-license {
- name: "external_cronet_license",
- license_kinds: [
- "SPDX-license-identifier-AFL-2.0",
- "SPDX-license-identifier-Apache-2.0",
- "SPDX-license-identifier-BSD",
- "SPDX-license-identifier-BSL-1.0",
- "SPDX-license-identifier-GPL",
- "SPDX-license-identifier-GPL-2.0",
- "SPDX-license-identifier-GPL-3.0",
- "SPDX-license-identifier-ICU",
- "SPDX-license-identifier-ISC",
- "SPDX-license-identifier-LGPL",
- "SPDX-license-identifier-LGPL-2.1",
- "SPDX-license-identifier-MIT",
- "SPDX-license-identifier-MPL",
- "SPDX-license-identifier-MPL-2.0",
- "SPDX-license-identifier-NCSA",
- "SPDX-license-identifier-OpenSSL",
- "SPDX-license-identifier-Unicode-DFS",
- "legacy_unencumbered",
- ],
- license_text: [
- "LICENSE",
- "base/third_party/double_conversion/LICENSE",
- "base/third_party/dynamic_annotations/LICENSE",
- "base/third_party/icu/LICENSE",
- "base/third_party/nspr/LICENSE",
- "base/third_party/superfasthash/LICENSE",
- "base/third_party/symbolize/LICENSE",
- "base/third_party/valgrind/LICENSE",
- "base/third_party/xdg_user_dirs/LICENSE",
- "net/third_party/quiche/src/LICENSE",
- "net/third_party/uri_template/LICENSE",
- "third_party/abseil-cpp/LICENSE",
- "third_party/ashmem/LICENSE",
- "third_party/boringssl/src/LICENSE",
- "third_party/boringssl/src/third_party/fiat/LICENSE",
- "third_party/boringssl/src/third_party/googletest/LICENSE",
- "third_party/boringssl/src/third_party/wycheproof_testvectors/LICENSE",
- "third_party/brotli/LICENSE",
- "third_party/icu/LICENSE",
- "third_party/icu/scripts/LICENSE",
- "third_party/libevent/LICENSE",
- "third_party/metrics_proto/LICENSE",
- "third_party/modp_b64/LICENSE",
- "third_party/protobuf/LICENSE",
- "third_party/protobuf/third_party/utf8_range/LICENSE",
- ],
-}
-
diff --git a/tools/gn2bp/desc_arm.json b/tools/gn2bp/desc_arm.json
deleted file mode 100644
index ff1a7e2..0000000
--- a/tools/gn2bp/desc_arm.json
+++ /dev/null
Binary files differ
diff --git a/tools/gn2bp/desc_arm64.json b/tools/gn2bp/desc_arm64.json
deleted file mode 100644
index 20c942f..0000000
--- a/tools/gn2bp/desc_arm64.json
+++ /dev/null
Binary files differ
diff --git a/tools/gn2bp/desc_x64.json b/tools/gn2bp/desc_x64.json
deleted file mode 100644
index b25932b..0000000
--- a/tools/gn2bp/desc_x64.json
+++ /dev/null
Binary files differ
diff --git a/tools/gn2bp/desc_x86.json b/tools/gn2bp/desc_x86.json
deleted file mode 100644
index b4bc6e9..0000000
--- a/tools/gn2bp/desc_x86.json
+++ /dev/null
Binary files differ
diff --git a/tools/gn2bp/gen_android_bp b/tools/gn2bp/gen_android_bp
deleted file mode 100755
index 9d2d858..0000000
--- a/tools/gn2bp/gen_android_bp
+++ /dev/null
@@ -1,1809 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2022 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.
-
-# This tool translates a collection of BUILD.gn files into a mostly equivalent
-# Android.bp file for the Android Soong build system. The input to the tool is a
-# JSON description of the GN build definition generated with the following
-# command:
-#
-# gn desc out --format=json --all-toolchains "//*" > desc.json
-#
-# The tool is then given a list of GN labels for which to generate Android.bp
-# build rules. The dependencies for the GN labels are squashed to the generated
-# Android.bp target, except for actions which get their own genrule. Some
-# libraries are also mapped to their Android equivalents -- see |builtin_deps|.
-
-import argparse
-import json
-import logging as log
-import operator
-import os
-import re
-import sys
-import copy
-from pathlib import Path
-
-import gn_utils
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-# Default targets to translate to the blueprint file.
-default_targets = [
- '//components/cronet/android:cronet',
- '//components/cronet/android:cronet_android_mainline',
-]
-
-# Defines a custom init_rc argument to be applied to the corresponding output
-# blueprint target.
-target_initrc = {
- # TODO: this can probably be removed.
-}
-
-target_host_supported = [
- # TODO: remove if this is not useful for the cronet build.
-]
-
-# Proto target groups which will be made public.
-proto_groups = {
- # TODO: remove if this is not used for the cronet build.
-}
-
-# All module names are prefixed with this string to avoid collisions.
-module_prefix = 'cronet_aml_'
-
-# Shared libraries which are directly translated to Android system equivalents.
-shared_library_allowlist = [
- 'android',
- 'android.hardware.atrace@1.0',
- 'android.hardware.health@2.0',
- 'android.hardware.health-V1-ndk',
- 'android.hardware.power.stats@1.0',
- "android.hardware.power.stats-V1-cpp",
- 'base',
- 'binder',
- 'binder_ndk',
- 'cutils',
- 'hidlbase',
- 'hidltransport',
- 'hwbinder',
- 'incident',
- 'log',
- 'services',
- 'statssocket',
- "tracingproxy",
- 'utils',
-]
-
-# Static libraries which are directly translated to Android system equivalents.
-static_library_allowlist = [
- 'statslog_perfetto',
-]
-
-# Include directories that will be removed from all targets.
-local_include_dirs_denylist = [
- 'third_party/zlib/',
-]
-
-experimental_include_dirs_denylist = [
- 'third_party/brotli/include/',
-]
-
-# Name of the module which settings such as compiler flags for all other
-# modules.
-defaults_module = module_prefix + 'defaults'
-
-# Location of the project in the Android source tree.
-tree_path = 'external/cronet'
-
-# Path for the protobuf sources in the standalone build.
-buildtools_protobuf_src = '//buildtools/protobuf/src'
-
-# Location of the protobuf src dir in the Android source tree.
-android_protobuf_src = 'external/protobuf/src'
-
-# put all args on a new line for better diffs.
-NEWLINE = ' " +\n "'
-
-# Compiler flags which are passed through to the blueprint.
-cflag_allowlist = [
- # needed for zlib:zlib
- "-mpclmul",
- # needed for zlib:zlib
- "-mssse3",
- # needed for zlib:zlib
- "-msse3",
- # needed for zlib:zlib
- "-msse4.2",
-]
-
-def get_linker_script_ldflag(script_path):
- return f'-Wl,--script,{tree_path}/{script_path}'
-
-# Additional arguments to apply to Android.bp rules.
-additional_args = {
- # TODO: remove if not needed.
- 'cronet_aml_components_cronet_android_cronet': [
- # linker_scripts property is not available in tm-mainline-prod.
- # So use ldflags to specify linker script.
- ('ldflags',{
- get_linker_script_ldflag('base/android/library_loader/anchor_functions.lds'),
- }),
- ],
- 'cronet_aml_net_net': [
- ('export_static_lib_headers', {
- 'cronet_aml_net_third_party_quiche_quiche',
- 'cronet_aml_crypto_crypto',
- }),
- ],
- # TODO: fix upstream. Both //base:base and
- # //base/allocator/partition_allocator:partition_alloc do not create a
- # dependency on gtest despite using gtest_prod.h.
- 'cronet_aml_base_base': [
- ('header_libs', {
- 'libgtest_prod_headers',
- }),
- ('export_header_lib_headers', {
- 'libgtest_prod_headers',
- }),
- ],
- 'cronet_aml_base_allocator_partition_allocator_partition_alloc': [
- ('header_libs', {
- 'libgtest_prod_headers',
- }),
- ],
-}
-
-def enable_brotli(module, arch):
- # Requires crrev/c/4111690
- if arch is None:
- module.static_libs.add('libbrotli')
- else:
- module.arch[arch].static_libs.add('libbrotli')
-
-def enable_modp_b64(module, arch):
- # Requires crrev/c/4112845
- # Requires aosp/2359455
- # Requires aosp/2359456
- if not module.is_compiled():
- return
- if arch is None:
- module.static_libs.add('libmodpb64')
- else:
- module.arch[arch].static_libs.add('libmodpb64')
-
-def enable_zlib(module, arch):
- # Requires crrev/c/4109079
- if arch is None:
- module.shared_libs.add('libz')
- else:
- module.arch[arch].shared_libs.add('libz')
-
-# Android equivalents for third-party libraries that the upstream project
-# depends on.
-builtin_deps = {
- '//buildtools/third_party/libunwind:libunwind':
- lambda m, a: None, # disable libunwind
- '//net/data/ssl/chrome_root_store:gen_root_store_inc':
- lambda m, a: None,
- '//net/tools/root_store_tool:root_store_tool':
- lambda m, a: None,
- '//third_party/zlib:zlib':
- enable_zlib,
-}
-
-experimental_android_deps = {
- '//third_party/brotli:common':
- enable_brotli,
- '//third_party/brotli:dec':
- enable_brotli,
- '//third_party/modp_b64:modp_b64':
- enable_modp_b64,
-}
-
-# Uncomment the following lines to use Android deps rather than their Chromium
-# equivalent:
-#builtin_deps.update(experimental_android_deps)
-#local_include_dirs_denylist.extend(experimental_include_dirs_denylist)
-
-# Name of tethering apex module
-tethering_apex = "com.android.tethering"
-
-# Name of cronet api target
-java_api_target_name = "//components/cronet/android:cronet_api_java"
-
-# ----------------------------------------------------------------------------
-# End of configuration.
-# ----------------------------------------------------------------------------
-
-
-class Error(Exception):
- pass
-
-
-class ThrowingArgumentParser(argparse.ArgumentParser):
-
- def __init__(self, context):
- super(ThrowingArgumentParser, self).__init__()
- self.context = context
-
- def error(self, message):
- raise Error('%s: %s' % (self.context, message))
-
-
-def write_blueprint_key_value(output, name, value, sort=True):
- """Writes a Blueprint key-value pair to the output"""
-
- if isinstance(value, bool):
- if value:
- output.append(' %s: true,' % name)
- else:
- output.append(' %s: false,' % name)
- return
- if not value:
- return
- if isinstance(value, set):
- value = sorted(value)
- if isinstance(value, list):
- output.append(' %s: [' % name)
- for item in sorted(value) if sort else value:
- output.append(' "%s",' % item)
- output.append(' ],')
- return
- if isinstance(value, Target):
- value.to_string(output)
- return
- if isinstance(value, dict):
- kv_output = []
- for k, v in value.items():
- write_blueprint_key_value(kv_output, k, v)
-
- output.append(' %s: {' % name)
- for line in kv_output:
- output.append(' %s' % line)
- output.append(' },')
- return
- output.append(' %s: "%s",' % (name, value))
-
-
-class Target(object):
- """A target-scoped part of a module"""
-
- def __init__(self, name):
- self.name = name
- self.srcs = set()
- self.shared_libs = set()
- self.static_libs = set()
- self.whole_static_libs = set()
- self.header_libs = set()
- self.cflags = set()
- self.dist = dict()
- self.strip = dict()
- self.stl = None
- self.cppflags = set()
- self.local_include_dirs = set()
- self.export_system_include_dirs = set()
- self.generated_headers = set()
- self.export_generated_headers = set()
-
- def to_string(self, output):
- nested_out = []
- self._output_field(nested_out, 'srcs')
- self._output_field(nested_out, 'shared_libs')
- self._output_field(nested_out, 'static_libs')
- self._output_field(nested_out, 'whole_static_libs')
- self._output_field(nested_out, 'header_libs')
- self._output_field(nested_out, 'cflags')
- self._output_field(nested_out, 'stl')
- self._output_field(nested_out, 'dist')
- self._output_field(nested_out, 'strip')
- self._output_field(nested_out, 'cppflags')
- self._output_field(nested_out, 'local_include_dirs')
- self._output_field(nested_out, 'export_system_include_dirs')
- self._output_field(nested_out, 'generated_headers')
- self._output_field(nested_out, 'export_generated_headers')
-
- if nested_out:
- output.append(' %s: {' % self.name)
- for line in nested_out:
- output.append(' %s' % line)
- output.append(' },')
-
- def _output_field(self, output, name, sort=True):
- value = getattr(self, name)
- return write_blueprint_key_value(output, name, value, sort)
-
-
-class Module(object):
- """A single module (e.g., cc_binary, cc_test) in a blueprint."""
-
- def __init__(self, mod_type, name, gn_target):
- self.type = mod_type
- self.gn_target = gn_target
- self.name = name
- self.srcs = set()
- self.comment = 'GN: ' + gn_target
- self.shared_libs = set()
- self.static_libs = set()
- self.whole_static_libs = set()
- self.runtime_libs = set()
- self.tools = set()
- self.cmd = None
- self.host_supported = False
- self.device_supported = True
- self.vendor_available = False
- self.init_rc = set()
- self.out = set()
- self.export_include_dirs = set()
- self.generated_headers = set()
- self.export_generated_headers = set()
- self.export_static_lib_headers = set()
- self.export_header_lib_headers = set()
- self.defaults = set()
- self.cflags = set()
- self.include_dirs = set()
- self.local_include_dirs = set()
- self.header_libs = set()
- self.required = set()
- self.tool_files = set()
- # target contains a dict of Targets indexed by os_arch.
- # example: { 'android_x86': Target('android_x86')
- self.target = dict()
- self.target['android'] = Target('android')
- self.target['android_x86'] = Target('android_x86')
- self.target['android_x86_64'] = Target('android_x86_64')
- self.target['android_arm'] = Target('android_arm')
- self.target['android_arm64'] = Target('android_arm64')
- self.target['host'] = Target('host')
- self.stl = None
- self.cpp_std = None
- self.dist = dict()
- self.strip = dict()
- self.data = set()
- self.apex_available = set()
- self.min_sdk_version = None
- self.proto = dict()
- self.linker_scripts = set()
- self.ldflags = set()
- # The genrule_XXX below are properties that must to be propagated back
- # on the module(s) that depend on the genrule.
- self.genrule_headers = set()
- self.genrule_srcs = set()
- self.genrule_shared_libs = set()
- self.genrule_header_libs = set()
- self.version_script = None
- self.test_suites = set()
- self.test_config = None
- self.stubs = {}
- self.cppflags = set()
- self.rtti = False
- # Name of the output. Used for setting .so file name for libcronet
- self.libs = set()
- self.stem = None
- self.compile_multilib = None
- self.aidl = dict()
- self.plugins = set()
- self.processor_class = None
- self.sdk_version = None
- self.javacflags = set()
- self.license_kinds = set()
- self.license_text = set()
- self.default_applicable_licenses = set()
-
- def to_string(self, output):
- if self.comment:
- output.append('// %s' % self.comment)
- output.append('%s {' % self.type)
- self._output_field(output, 'name')
- self._output_field(output, 'srcs')
- self._output_field(output, 'shared_libs')
- self._output_field(output, 'static_libs')
- self._output_field(output, 'whole_static_libs')
- self._output_field(output, 'runtime_libs')
- self._output_field(output, 'tools')
- self._output_field(output, 'cmd', sort=False)
- if self.host_supported:
- self._output_field(output, 'host_supported')
- if not self.device_supported:
- self._output_field(output, 'device_supported')
- if self.vendor_available:
- self._output_field(output, 'vendor_available')
- self._output_field(output, 'init_rc')
- self._output_field(output, 'out')
- self._output_field(output, 'export_include_dirs')
- self._output_field(output, 'generated_headers')
- self._output_field(output, 'export_generated_headers')
- self._output_field(output, 'export_static_lib_headers')
- self._output_field(output, 'export_header_lib_headers')
- self._output_field(output, 'defaults')
- self._output_field(output, 'cflags')
- self._output_field(output, 'include_dirs')
- self._output_field(output, 'local_include_dirs')
- self._output_field(output, 'header_libs')
- self._output_field(output, 'required')
- self._output_field(output, 'dist')
- self._output_field(output, 'strip')
- self._output_field(output, 'tool_files')
- self._output_field(output, 'data')
- self._output_field(output, 'stl')
- self._output_field(output, 'cpp_std')
- self._output_field(output, 'apex_available')
- self._output_field(output, 'min_sdk_version')
- self._output_field(output, 'version_script')
- self._output_field(output, 'test_suites')
- self._output_field(output, 'test_config')
- self._output_field(output, 'stubs')
- self._output_field(output, 'proto')
- self._output_field(output, 'linker_scripts')
- self._output_field(output, 'ldflags')
- self._output_field(output, 'cppflags')
- self._output_field(output, 'libs')
- self._output_field(output, 'stem')
- self._output_field(output, 'compile_multilib')
- self._output_field(output, 'aidl')
- self._output_field(output, 'plugins')
- self._output_field(output, 'processor_class')
- self._output_field(output, 'sdk_version')
- self._output_field(output, 'javacflags')
- self._output_field(output, 'license_kinds')
- self._output_field(output, 'license_text')
- self._output_field(output, 'default_applicable_licenses')
- if self.rtti:
- self._output_field(output, 'rtti')
-
- target_out = []
- for arch, target in sorted(self.target.items()):
- # _output_field calls getattr(self, arch).
- setattr(self, arch, target)
- self._output_field(target_out, arch)
-
- if target_out:
- output.append(' target: {')
- for line in target_out:
- output.append(' %s' % line)
- output.append(' },')
-
- output.append('}')
- output.append('')
-
- def add_android_static_lib(self, lib):
- if self.type == 'cc_binary_host':
- raise Exception('Adding Android static lib for host tool is unsupported')
- elif self.host_supported:
- self.target['android'].static_libs.add(lib)
- else:
- self.static_libs.add(lib)
-
- def add_android_shared_lib(self, lib):
- if self.type == 'cc_binary_host':
- raise Exception('Adding Android shared lib for host tool is unsupported')
- elif self.host_supported:
- self.target['android'].shared_libs.add(lib)
- else:
- self.shared_libs.add(lib)
-
- def _output_field(self, output, name, sort=True):
- value = getattr(self, name)
- return write_blueprint_key_value(output, name, value, sort)
-
- def is_compiled(self):
- return self.type not in ('cc_genrule', 'filegroup', 'java_genrule')
-
- def is_genrule(self):
- return self.type == "cc_genrule"
-
- def has_input_files(self):
- return len(self.srcs) > 0 or any([len(target.srcs) > 0 for target in self.target.values()])
-
- def merge_attribute(self, key, source_module, allowed_archs, source_key = None):
- """
- Merges the value of the attribute `source_key` for the `dep_module` with
- the value of the attribute `key` for this module. If the value of the
- `source_key` is equal to None. Then `key` is used for both modules.
-
- This merges the attribute for both non-arch and archs
- specified in `allowed_archs`.
- :param key: The attribute used for merging in the calling module. Also
- used for `dep_module` if the `source_key` is None.
- :param source_module: The module where data is propagated from.
- :param allowed_archs: A list of archs to merge the attribute on.
- :param source_key: if the attribute merged from the `dep_module`
- is different from the `key`
- """
- if not source_key:
- source_key = key
- self.__dict__[key].update(source_module.__dict__[source_key])
- for arch_name in source_module.target.keys():
- if arch_name in allowed_archs:
- self.target[arch_name].__dict__[key].update(
- source_module.target[arch_name].__dict__[source_key])
-
-class Blueprint(object):
- """In-memory representation of an Android.bp file."""
-
- def __init__(self):
- self.modules = {}
-
- def add_module(self, module):
- """Adds a new module to the blueprint, replacing any existing module
- with the same name.
-
- Args:
- module: Module instance.
- """
- self.modules[module.name] = module
-
- def to_string(self, output):
- for m in sorted(self.modules.values(), key=lambda m: m.name):
- if m.type != "cc_object" or m.has_input_files():
- # Don't print cc_object with empty srcs. These attributes are already
- # propagated up the tree. Printing them messes the presubmits because
- # every module is compiled while those targets are not reachable in
- # a normal compilation path.
- m.to_string(output)
-
-
-def label_to_module_name(label):
- """Turn a GN label (e.g., //:perfetto_tests) into a module name."""
- module = re.sub(r'^//:?', '', label)
- module = re.sub(r'[^a-zA-Z0-9_]', '_', module)
-
- if not module.startswith(module_prefix):
- return module_prefix + module
- return module
-
-
-def is_supported_source_file(name):
- """Returns True if |name| can appear in a 'srcs' list."""
- return os.path.splitext(name)[1] in ['.c', '.cc', '.cpp', '.java', '.proto', '.S']
-
-
-def create_proto_modules(blueprint, gn, target):
- """Generate genrules for a proto GN target.
-
- GN actions are used to dynamically generate files during the build. The
- Soong equivalent is a genrule. This function turns a specific kind of
- genrule which turns .proto files into source and header files into a pair
- equivalent genrules.
-
- Args:
- blueprint: Blueprint instance which is being generated.
- target: gn_utils.Target object.
-
- Returns:
- The source_genrule module.
- """
- assert (target.type == 'proto_library')
-
- protoc_gn_target_name = gn.get_target('//third_party/protobuf:protoc').name
- protoc_module_name = label_to_module_name(protoc_gn_target_name)
- tools = {protoc_module_name}
- cpp_out_dir = '$(genDir)/%s/%s/' % (tree_path, target.proto_in_dir)
- target_module_name = label_to_module_name(target.name)
-
- # In GN builds the proto path is always relative to the output directory
- # (out/tmp.xxx).
- cmd = ['$(location %s)' % protoc_module_name]
- cmd += ['--proto_path=%s/%s' % (tree_path, target.proto_in_dir)]
-
- if buildtools_protobuf_src in target.proto_paths:
- cmd += ['--proto_path=%s' % android_protobuf_src]
-
- # We don't generate any targets for source_set proto modules because
- # they will be inlined into other modules if required.
- if target.proto_plugin == 'source_set':
- return None
-
- # Descriptor targets only generate a single target.
- if target.proto_plugin == 'descriptor':
- out = '{}.bin'.format(target_module_name)
-
- cmd += ['--descriptor_set_out=$(out)']
- cmd += ['$(in)']
-
- descriptor_module = Module('cc_genrule', target_module_name, target.name)
- descriptor_module.cmd = ' '.join(cmd)
- descriptor_module.out = [out]
- descriptor_module.tools = tools
- blueprint.add_module(descriptor_module)
-
- # Recursively extract the .proto files of all the dependencies and
- # add them to srcs.
- descriptor_module.srcs.update(
- gn_utils.label_to_path(src) for src in target.sources)
- for dep in target.transitive_proto_deps:
- current_target = gn.get_target(dep)
- descriptor_module.srcs.update(
- gn_utils.label_to_path(src) for src in current_target.sources)
-
- return descriptor_module
-
- # We create two genrules for each proto target: one for the headers and
- # another for the sources. This is because the module that depends on the
- # generated files needs to declare two different types of dependencies --
- # source files in 'srcs' and headers in 'generated_headers' -- and it's not
- # valid to generate .h files from a source dependency and vice versa.
- source_module_name = target_module_name + '_gen'
- source_module = Module('cc_genrule', source_module_name, target.name)
- blueprint.add_module(source_module)
- source_module.srcs.update(
- gn_utils.label_to_path(src) for src in target.sources)
-
- header_module = Module('cc_genrule', source_module_name + '_headers',
- target.name)
- blueprint.add_module(header_module)
- header_module.srcs = set(source_module.srcs)
-
- # TODO(primiano): at some point we should remove this. This was introduced
- # by aosp/1108421 when adding "protos/" to .proto include paths, in order to
- # avoid doing multi-repo changes and allow old clients in the android tree
- # to still do the old #include "perfetto/..." rather than
- # #include "protos/perfetto/...".
- header_module.export_include_dirs = {'.', 'protos'}
- # Since the .cc file and .h get created by a different gerule target, they
- # are not put in the same intermediate path, so local includes do not work
- # without explictily exporting the include dir.
- header_module.export_include_dirs.add(target.proto_in_dir)
-
- # This function does not return header_module so setting apex_available attribute here.
- header_module.apex_available.add(tethering_apex)
-
- source_module.genrule_srcs.add(':' + source_module.name)
- source_module.genrule_headers.add(header_module.name)
-
- if target.proto_plugin == 'proto':
- suffixes = ['pb']
- source_module.genrule_shared_libs.add('libprotobuf-cpp-lite')
- cmd += ['--cpp_out=lite=true:' + cpp_out_dir]
- elif target.proto_plugin == 'protozero':
- suffixes = ['pbzero']
- plugin = create_modules_from_target(blueprint, gn, protozero_plugin)
- tools.add(plugin.name)
- cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
- cmd += ['--plugin_out=wrapper_namespace=pbzero:' + cpp_out_dir]
- elif target.proto_plugin == 'cppgen':
- suffixes = ['gen']
- plugin = create_modules_from_target(blueprint, gn, cppgen_plugin)
- tools.add(plugin.name)
- cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
- cmd += ['--plugin_out=wrapper_namespace=gen:' + cpp_out_dir]
- elif target.proto_plugin == 'ipc':
- suffixes = ['ipc']
- plugin = create_modules_from_target(blueprint, gn, ipc_plugin)
- tools.add(plugin.name)
- cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
- cmd += ['--plugin_out=wrapper_namespace=gen:' + cpp_out_dir]
- else:
- raise Error('Unsupported proto plugin: %s' % target.proto_plugin)
-
- cmd += ['$(in)']
- source_module.cmd = ' '.join(cmd)
- header_module.cmd = source_module.cmd
- source_module.tools = tools
- header_module.tools = tools
-
- for sfx in suffixes:
- source_module.out.update('%s/%s' %
- (tree_path, src.replace('.proto', '.%s.cc' % sfx))
- for src in source_module.srcs)
- header_module.out.update('%s/%s' %
- (tree_path, src.replace('.proto', '.%s.h' % sfx))
- for src in header_module.srcs)
- return source_module
-
-
-def create_proto_group_modules(blueprint, gn, module_name, target_names):
- # TODO(lalitm): today, we're only adding a Java lite module because that's
- # the only one used in practice. In the future, if we need other target types
- # (e.g. C++, Java full etc.) add them here.
- bp_module_name = label_to_module_name(module_name) + '_java_protos'
- module = Module('java_library', bp_module_name, bp_module_name)
- module.comment = f'''GN: [{', '.join(target_names)}]'''
- module.proto = {'type': 'lite', 'canonical_path_from_root': False}
-
- for name in target_names:
- target = gn.get_target(name)
- module.srcs.update(gn_utils.label_to_path(src) for src in target.sources)
- for dep_label in target.transitive_proto_deps:
- dep = gn.get_target(dep_label)
- module.srcs.update(gn_utils.label_to_path(src) for src in dep.sources)
-
- blueprint.add_module(module)
-
-def create_gcc_preprocess_modules(blueprint, target):
- # gcc_preprocess.py internally execute host gcc which is not allowed in genrule.
- # So, this function create multiple modules and realize equivalent processing
- # TODO: Consider to support gcc_preprocess.py in different way
- # It's not great to have genrule and cc_object in the dependency from java_library
- assert (len(target.sources) == 1)
- source = list(target.sources)[0]
- assert (Path(source).suffix == '.template')
- stem = Path(source).stem
-
- bp_module_name = label_to_module_name(target.name)
-
- # Rename .template to .cc since cc_object does not accept .template file as srcs
- rename_module = Module('genrule', bp_module_name + '_rename', target.name)
- rename_module.srcs.add(gn_utils.label_to_path(source))
- rename_module.out.add(stem + '.cc')
- rename_module.cmd = 'cp $(in) $(out)'
- blueprint.add_module(rename_module)
-
- # Preprocess template file and generates java file
- preprocess_module = Module('cc_object', bp_module_name + '_preprocess', target.name)
- # -E: stop after preprocessing.
- # -P: disable line markers, i.e. '#line 309'
- preprocess_module.cflags.update(['-E', '-P', '-DANDROID'])
- preprocess_module.srcs.add(':' + rename_module.name)
- defines = ['-D' + target.args[i+1] for i, arg in enumerate(target.args) if arg == '--define']
- preprocess_module.cflags.update(defines)
- # HACK: Specifying compile_multilib to build cc_object only once.
- # Without this, soong complain to genrule that depends on cc_object when built for 64bit target.
- # It seems this is because cc object is a module with per-architecture variants and genrule is a
- # module with default variant. For 64bit target, cc_object is built multiple times for 32/64bit
- # modes and genrule doesn't know which one to depend on.
- preprocess_module.compile_multilib = 'first'
- blueprint.add_module(preprocess_module)
-
- # Generates srcjar using soong_zip
- module = Module('genrule', bp_module_name, target.name)
- module.srcs.add(':' + preprocess_module.name)
- module.out.add(stem + '.srcjar')
- module.cmd = NEWLINE.join([
- f'cp $(in) $(genDir)/{stem}.java &&',
- f'$(location soong_zip) -o $(out) -srcjar -C $(genDir) -f $(genDir)/{stem}.java'
- ])
- module.tools.add('soong_zip')
- blueprint.add_module(module)
- return module
-
-
-class BaseActionSanitizer():
- def __init__(self, target, arch):
- # Just to be on the safe side, create a deep-copy.
- self.target = copy.deepcopy(target)
- if arch:
- # Merge arch specific attributes
- self.target.sources |= arch.sources
- self.target.inputs |= arch.inputs
- self.target.outputs |= arch.outputs
- self.target.script = self.target.script or arch.script
- self.target.args = self.target.args or arch.args
- self.target.response_file_contents = \
- self.target.response_file_contents or arch.response_file_contents
- self.target.args = self._normalize_args()
-
- def get_name(self):
- return label_to_module_name(self.target.name)
-
- def _normalize_args(self):
- # Convert ['--param=value'] to ['--param', 'value'] for consistency.
- # Escape quotations.
- normalized_args = []
- for arg in self.target.args:
- arg = arg.replace('"', r'\"')
- if arg.startswith('-'):
- normalized_args.extend(arg.split('='))
- else:
- normalized_args.append(arg)
- return normalized_args
-
- # There are three types of args:
- # - flags (--flag)
- # - value args (--arg value)
- # - list args (--arg value1 --arg value2)
- # value args have exactly one arg value pair and list args have one or more arg value pairs.
- # Note that the set of list args contains the set of value args.
- # This is because list and value args are identical when the list args has only one arg value pair
- # Some functions provide special implementations for each type, while others
- # work on all of them.
- def _has_arg(self, arg):
- return arg in self.target.args
-
- def _get_arg_indices(self, target_arg):
- return [i for i, arg in enumerate(self.target.args) if arg == target_arg]
-
- # Whether an arg value pair appears once or more times
- def _is_list_arg(self, arg):
- indices = self._get_arg_indices(arg)
- return len(indices) > 0 and all([not self.target.args[i + 1].startswith('--') for i in indices])
-
- def _update_list_arg(self, arg, func, throw_if_absent = True):
- if self._should_fail_silently(arg, throw_if_absent):
- return
- assert(self._is_list_arg(arg))
- indices = self._get_arg_indices(arg)
- for i in indices:
- self._set_arg_at(i + 1, func(self.target.args[i + 1]))
-
- # Whether an arg value pair appears exactly once
- def _is_value_arg(self, arg):
- return operator.countOf(self.target.args, arg) == 1 and self._is_list_arg(arg)
-
- def _get_value_arg(self, arg):
- assert(self._is_value_arg(arg))
- i = self.target.args.index(arg)
- return self.target.args[i + 1]
-
- # used to check whether a function call should cause an error when an arg is
- # missing.
- def _should_fail_silently(self, arg, throw_if_absent):
- return not throw_if_absent and not self._has_arg(arg)
-
- def _set_value_arg(self, arg, value, throw_if_absent = True):
- if self._should_fail_silently(arg, throw_if_absent):
- return
- assert(self._is_value_arg(arg))
- i = self.target.args.index(arg)
- self.target.args[i + 1] = value
-
- def _update_value_arg(self, arg, func, throw_if_absent = True):
- if self._should_fail_silently(arg, throw_if_absent):
- return
- self._set_value_arg(arg, func(self._get_value_arg(arg)))
-
- def _set_arg_at(self, position, value):
- self.target.args[position] = value
-
- def _delete_value_arg(self, arg, throw_if_absent = True):
- if self._should_fail_silently(arg, throw_if_absent):
- return
- assert(self._is_value_arg(arg))
- i = self.target.args.index(arg)
- self.target.args.pop(i)
- self.target.args.pop(i)
-
- def _append_arg(self, arg, value):
- self.target.args.append(arg)
- self.target.args.append(value)
-
- def _sanitize_filepath_with_location_tag(self, arg):
- if arg.startswith('../../'):
- arg = self._sanitize_filepath(arg)
- arg = self._add_location_tag(arg)
- return arg
-
- # wrap filename in location tag.
- def _add_location_tag(self, filename):
- return '$(location %s)' % filename
-
- # applies common directory transformation that *should* be universally applicable.
- # TODO: verify if it actually *is* universally applicable.
- def _sanitize_filepath(self, filepath):
- # Careful, order matters!
- # delete all leading ../
- filepath = re.sub('^(\.\./)+', '', filepath)
- filepath = re.sub('^gen/jni_headers', '$(genDir)', filepath)
- filepath = re.sub('^gen', '$(genDir)', filepath)
- return filepath
-
- # Iterate through all the args and apply function
- def _update_all_args(self, func):
- self.target.args = [func(arg) for arg in self.target.args]
-
- def get_cmd(self):
- arg_string = NEWLINE.join(self.target.args)
- cmd = '$(location %s) %s' % (
- gn_utils.label_to_path(self.target.script), arg_string)
-
- if self.use_response_file:
- # Pipe response file contents into script
- cmd = 'echo \'%s\' |%s%s' % (self.target.response_file_contents, NEWLINE, cmd)
- return cmd
-
- def get_outputs(self):
- return self.target.outputs
-
- def get_srcs(self):
- # gn treats inputs and sources for actions equally.
- # soong only supports source files inside srcs, non-source files are added as
- # tool_files dependency.
- files = self.target.sources.union(self.target.inputs)
- return {gn_utils.label_to_path(file) for file in files if is_supported_source_file(file)}
-
- def get_tool_files(self):
- # gn treats inputs and sources for actions equally.
- # soong only supports source files inside srcs, non-source files are added as
- # tool_files dependency.
- files = self.target.sources.union(self.target.inputs)
- tool_files = {gn_utils.label_to_path(file)
- for file in files if not is_supported_source_file(file)}
- tool_files.add(gn_utils.label_to_path(self.target.script))
- return tool_files
-
- def _sanitize_args(self):
- # Handle passing parameters via response file by piping them into the script
- # and reading them from /dev/stdin.
-
- self.use_response_file = gn_utils.RESPONSE_FILE in self.target.args
- if self.use_response_file:
- # Replace {{response_file_contents}} with /dev/stdin
- self.target.args = ['/dev/stdin' if it == gn_utils.RESPONSE_FILE else it
- for it in self.target.args]
-
- def _sanitize_outputs(self):
- pass
-
- def _sanitize_inputs(self):
- pass
-
- def sanitize(self):
- self._sanitize_args()
- self._sanitize_outputs()
- self._sanitize_inputs()
-
- # Whether this target generates header files
- def is_header_generated(self):
- return any(os.path.splitext(it)[1] == '.h' for it in self.target.outputs)
-
-class WriteBuildDateHeaderSanitizer(BaseActionSanitizer):
- def _sanitize_args(self):
- self._set_arg_at(0, '$(out)')
- super()._sanitize_args()
-
-class WriteBuildFlagHeaderSanitizer(BaseActionSanitizer):
- def _sanitize_args(self):
- self._set_value_arg('--gen-dir', '.')
- self._set_value_arg('--output', '$(out)')
- super()._sanitize_args()
-
-class JniGeneratorSanitizer(BaseActionSanitizer):
- def _add_location_tag_to_filepath(self, arg):
- if not arg.endswith('.class'):
- # --input_file supports both .class specifiers or source files as arguments.
- # Only source files need to be wrapped inside a $(location <label>) tag.
- arg = self._add_location_tag(arg)
- return arg
-
- def _sanitize_args(self):
- self._set_value_arg('--jar_file', '$(location :current_android_jar)', False)
- if self._has_arg('--jar_file'):
- self._append_arg('--javap', '$$(find $${OUT_DIR:-out}/.path -name javap)')
- self._update_value_arg('--output_dir', self._sanitize_filepath)
- self._update_value_arg('--includes', self._sanitize_filepath, False)
- self._delete_value_arg('--prev_output_dir', False)
- self._update_list_arg('--input_file', self._sanitize_filepath)
- self._update_list_arg('--input_file', self._add_location_tag_to_filepath)
- self._append_arg('--package_prefix', 'android.net.http.internal')
- super()._sanitize_args()
-
- def _sanitize_outputs(self):
- # fix target.output directory to match #include statements.
- self.target.outputs = {re.sub('^jni_headers/', '', out) for out in self.target.outputs}
- super()._sanitize_outputs()
-
- def get_tool_files(self):
- tool_files = super().get_tool_files()
- # android_jar.classes should be part of the tools as it list implicit classes
- # for the script to generate JNI headers.
- tool_files.add("base/android/jni_generator/android_jar.classes")
-
- # Filter android.jar and add :current_android_jar
- tool_files = {file if not file.endswith('android.jar') else ':current_android_jar'
- for file in tool_files }
- return tool_files
-
-class JniRegistrationGeneratorSanitizer(BaseActionSanitizer):
- def _sanitize_inputs(self):
- self.target.inputs = [file for file in self.target.inputs if not file.startswith('//out/')]
-
- def _sanitize_args(self):
- self._update_value_arg('--depfile', self._sanitize_filepath)
- self._update_value_arg('--srcjar-path', self._sanitize_filepath)
- self._update_value_arg('--header-path', self._sanitize_filepath)
- self._set_value_arg('--sources-files', '$(genDir)/java.sources')
- # update_jni_registration_module removes them from the srcs of the module
- # It might be better to remove sources by '--sources-exclusions'
- self._delete_value_arg('--sources-exclusions')
- self._append_arg('--package_prefix', 'android.net.http.internal')
- super()._sanitize_args()
-
- def get_cmd(self):
- # jni_registration_generator.py doesn't work with python2
- cmd = "python3 " + super().get_cmd()
- # Path in the original sources file does not work in genrule.
- # So creating sources file in cmd based on the srcs of this target.
- # Adding ../$(current_dir)/ to the head because jni_registration_generator.py uses the files
- # whose path startswith(..)
- commands = ["current_dir=`basename \\\`pwd\\\``;",
- "for f in $(in);",
- "do",
- "echo \\\"../$$current_dir/$$f\\\" >> $(genDir)/java.sources;",
- "done;",
- cmd]
-
- # .h file jni_registration_generator.py generates has #define with directory name.
- # With the genrule env that contains "." which is invalid. So replace that at the end of cmd.
- commands.append(";sed -i -e 's/OUT_SOONG_.TEMP_SBOX_.*_OUT/GEN/g' ")
- commands.append("$(genDir)/components/cronet/android/cronet_jni_registration.h")
- return NEWLINE.join(commands)
-
-class JavaJniRegistrationGeneratorSanitizer(JniRegistrationGeneratorSanitizer):
- def get_name(self):
- return label_to_module_name(self.target.name) + "__java"
-
- def _sanitize_outputs(self):
- self.target.outputs = [out for out in self.target.outputs if
- out.endswith(".srcjar")]
- super()._sanitize_outputs()
-
-class VersionSanitizer(BaseActionSanitizer):
- def _sanitize_args(self):
- self._set_value_arg('-o', '$(out)')
- # args for the version.py contain file path without leading --arg key. So apply sanitize
- # function for all the args.
- self._update_all_args(self._sanitize_filepath_with_location_tag)
- self._set_value_arg('-e', "'%s'" % self._get_value_arg('-e'))
- super()._sanitize_args()
-
- def get_tool_files(self):
- tool_files = super().get_tool_files()
- # android_chrome_version.py is not specified in anywhere but version.py imports this file
- tool_files.add('build/util/android_chrome_version.py')
- return tool_files
-
-class JavaCppEnumSanitizer(BaseActionSanitizer):
- def _sanitize_args(self):
- self._update_all_args(self._sanitize_filepath_with_location_tag)
- self._set_value_arg('--srcjar', '$(out)')
- super()._sanitize_args()
-
-class MakeDafsaSanitizer(BaseActionSanitizer):
- def is_header_generated(self):
- # This script generates .cc files but they are #included by other sources
- # (e.g. registry_controlled_domain.cc)
- return True
-
-class JavaCppFeatureSanitizer(BaseActionSanitizer):
- def _sanitize_args(self):
- self._update_all_args(self._sanitize_filepath_with_location_tag)
- self._set_value_arg('--srcjar', '$(out)')
- super()._sanitize_args()
-
-class JavaCppStringSanitizer(BaseActionSanitizer):
- def _sanitize_args(self):
- self._update_all_args(self._sanitize_filepath_with_location_tag)
- self._set_value_arg('--srcjar', '$(out)')
- super()._sanitize_args()
-
-class WriteNativeLibrariesJavaSanitizer(BaseActionSanitizer):
- def _sanitize_args(self):
- self._set_value_arg('--output', '$(out)')
- super()._sanitize_args()
-
-def get_action_sanitizer(target, type, arch):
- if target.script == "//build/write_buildflag_header.py":
- return WriteBuildFlagHeaderSanitizer(target, arch)
- elif target.script == "//build/write_build_date_header.py":
- return WriteBuildDateHeaderSanitizer(target, arch)
- elif target.script == '//base/android/jni_generator/jni_generator.py':
- return JniGeneratorSanitizer(target, arch)
- elif target.script == '//base/android/jni_generator/jni_registration_generator.py':
- if type == 'java_genrule':
- return JavaJniRegistrationGeneratorSanitizer(target, arch)
- else:
- return JniRegistrationGeneratorSanitizer(target, arch)
- elif target.script == "//build/util/version.py":
- return VersionSanitizer(target, arch)
- elif target.script == "//build/android/gyp/java_cpp_enum.py":
- return JavaCppEnumSanitizer(target, arch)
- elif target.script == "//net/tools/dafsa/make_dafsa.py":
- return MakeDafsaSanitizer(target, arch)
- elif target.script == '//build/android/gyp/java_cpp_features.py':
- return JavaCppFeatureSanitizer(target, arch)
- elif target.script == '//build/android/gyp/java_cpp_strings.py':
- return JavaCppStringSanitizer(target, arch)
- elif target.script == '//build/android/gyp/write_native_libraries_java.py':
- return WriteNativeLibrariesJavaSanitizer(target, arch)
- else:
- # TODO: throw exception here once all script hacks have been converted.
- return BaseActionSanitizer(target, arch)
-
-def create_action_foreach_modules(blueprint, target):
- """ The following assumes that rebase_path exists in the args.
- The args of an action_foreach contains hints about which output files are generated
- by which source files.
- This is copied directly from the args
- "gen/net/base/registry_controlled_domains/{{source_name_part}}-reversed-inc.cc"
- So each source file will generate an output whose name is the {source_name-reversed-inc.cc}
- """
- new_args = []
- for i, src in enumerate(sorted(target.sources)):
- # don't add script arg for the first source -- create_action_module
- # already does this.
- if i != 0:
- new_args.append('&& python3 $(location %s)' %
- gn_utils.label_to_path(target.script))
- for arg in target.args:
- if '{{source}}' in arg:
- new_args.append('$(location %s)' % (gn_utils.label_to_path(src)))
- elif '{{source_name_part}}' in arg:
- source_name_part = src.split("/")[-1] # Get the file name only
- source_name_part = source_name_part.split(".")[0] # Remove the extension (Ex: .cc)
- file_name = arg.replace('{{source_name_part}}', source_name_part).split("/")[-1]
- # file_name represent the output file name. But we need the whole path
- # This can be found from target.outputs.
- for out in target.outputs:
- if out.endswith(file_name):
- new_args.append('$(location %s)' % out)
- else:
- new_args.append(arg)
-
- target.args = new_args
- return create_action_module(blueprint, target, 'cc_genrule')
-
-def create_action_module_internal(target, type, arch=None):
- sanitizer = get_action_sanitizer(target, type, arch)
- sanitizer.sanitize()
-
- module = Module(type, sanitizer.get_name(), target.name)
- module.cmd = sanitizer.get_cmd()
- module.out = sanitizer.get_outputs()
- if sanitizer.is_header_generated():
- module.genrule_headers.add(module.name)
- module.srcs = sanitizer.get_srcs()
- module.tool_files = sanitizer.get_tool_files()
-
- return module
-
-def get_cmd_condition(arch):
- '''
- :param arch: archtecture name e.g. android_x86_64, android_arm64
- :return: condition that can be used in cc_genrule cmd to switch the behavior based on arch
- '''
- if arch == "android_x86_64":
- return "( $$CC_ARCH == 'x86_64' && $$CC_OS == 'android' )"
- elif arch == "android_x86":
- return "( $$CC_ARCH == 'x86' && $$CC_OS == 'android' )"
- elif arch == "android_arm":
- return "( $$CC_ARCH == 'arm' && $$CC_OS == 'android' )"
- elif arch == "android_arm64":
- return "( $$CC_ARCH == 'arm64' && $$CC_OS == 'android' )"
- elif arch == "host":
- return "$$CC_OS != 'android'"
- else:
- raise Error(f'Unknown architecture type {arch}')
-
-def merge_cmd(modules, genrule_type):
- '''
- :param modules: dictionary whose key is arch name and value is module
- :param genrule_type: cc_genrule or java_genrule
- :return: merged command or common command if all the archs have the same command.
- '''
- commands = list({module.cmd for module in modules.values()})
- if len(commands) == 1:
- # If all the archs have the same command, return the command
- return commands[0]
-
- if genrule_type != 'cc_genrule':
- raise Error(f'{genrule_type} can not have different cmd between archs')
-
- merged_cmd = []
- for arch, module in modules.items():
- merged_cmd.append(f'if [[ {get_cmd_condition(arch)} ]];')
- merged_cmd.append('then')
- merged_cmd.append(module.cmd + ';')
- merged_cmd.append('fi;')
- return NEWLINE.join(merged_cmd)
-
-def merge_modules(modules, genrule_type):
- '''
- :param modules: dictionary whose key is arch name and value is module
- :param genrule_type: cc_genrule or java_genrule
- :return: merged module of input modules
- '''
- merged_module = list(modules.values())[0]
-
- # Following attributes must be the same between archs
- for key in ('out', 'genrule_headers', 'srcs', 'tool_files'):
- if any([getattr(merged_module, key) != getattr(module, key) for module in modules.values()]):
- raise Error(f'{merged_module.name} has different values for {key} between archs')
-
- merged_module.cmd = merge_cmd(modules, genrule_type)
- return merged_module
-
-def create_action_module(blueprint, target, genrule_type):
- '''
- Create module for action target and add to the blueprint. If target has arch specific attributes
- this function merge them and create a single module.
- :param blueprint:
- :param target: target which is converted to the module.
- :param genrule_type: cc_genrule or java_genrule
- :return: created module
- '''
- # TODO: Handle this target correctly, this target generates java_genrule but this target has
- # different value for cpu-family arg between archs
- if target.name == '//build/android:native_libraries_gen':
- module = create_action_module_internal(target, genrule_type, target.arch['android_arm'])
- blueprint.add_module(module)
- return module
-
- modules = {arch_name: create_action_module_internal(target, genrule_type, arch)
- for arch_name, arch in target.arch.items()}
- module = merge_modules(modules, genrule_type)
- blueprint.add_module(module)
- return module
-
-
-def _get_cflags(cflags, defines):
- cflags = {flag for flag in cflags if flag in cflag_allowlist}
- # Consider proper allowlist or denylist if needed
- cflags |= set("-D%s" % define.replace("\"", "\\\"") for define in defines)
- return cflags
-
-def set_module_flags(module, cflags, defines):
- module.cflags.update(_get_cflags(cflags, defines))
- # TODO: implement proper cflag parsing.
- for flag in cflags:
- if '-std=' in flag:
- module.cpp_std = flag[len('-std='):]
- if '-fexceptions' in flag:
- module.cppflags.add('-fexceptions')
-
-def set_module_include_dirs(module, cflags, include_dirs):
- for flag in cflags:
- if '-isystem' in flag:
- module.local_include_dirs.add(flag[len('-isystem../../'):])
-
- # Adding local_include_dirs is necessary due to source_sets / filegroups
- # which do not properly propagate include directories.
- # Filter any directory inside //out as a) this directory does not exist for
- # aosp / soong builds and b) the include directory should already be
- # configured via library dependency.
- module.local_include_dirs.update([gn_utils.label_to_path(d)
- for d in include_dirs if not d.startswith('//out')])
- # Remove prohibited include directories
- module.local_include_dirs = [d for d in module.local_include_dirs
- if d not in local_include_dirs_denylist]
-
-
-def create_modules_from_target(blueprint, gn, gn_target_name):
- """Generate module(s) for a given GN target.
-
- Given a GN target name, generate one or more corresponding modules into a
- blueprint. The only case when this generates >1 module is proto libraries.
-
- Args:
- blueprint: Blueprint instance which is being generated.
- gn: gn_utils.GnParser object.
- gn_target_name: GN target for module generation.
- """
- bp_module_name = label_to_module_name(gn_target_name)
- if bp_module_name in blueprint.modules:
- return blueprint.modules[bp_module_name]
- target = gn.get_target(gn_target_name)
- log.info('create modules for %s (%s)', target.name, target.type)
-
- if target.type == 'executable':
- if target.testonly:
- module_type = 'cc_test'
- else:
- # Can be used for both host and device targets.
- module_type = 'cc_binary'
- module = Module(module_type, bp_module_name, gn_target_name)
- elif target.type == 'static_library':
- module = Module('cc_library_static', bp_module_name, gn_target_name)
- elif target.type == 'shared_library':
- module = Module('cc_library_shared', bp_module_name, gn_target_name)
- elif target.type == 'source_set':
- module = Module('cc_object', bp_module_name, gn_target_name)
- elif target.type == 'group':
- # "group" targets are resolved recursively by gn_utils.get_target().
- # There's nothing we need to do at this level for them.
- return None
- elif target.type == 'proto_library':
- module = create_proto_modules(blueprint, gn, target)
- if module is None:
- return None
- elif target.type == 'action':
- module = create_action_module(blueprint, target, 'cc_genrule')
- elif target.type == 'action_foreach':
- module = create_action_foreach_modules(blueprint, target)
- elif target.type == 'copy':
- # TODO: careful now! copy targets are not supported yet, but this will stop
- # traversing the dependency tree. For //base:base, this is not a big
- # problem as libicu contains the only copy target which happens to be a
- # leaf node.
- return None
- elif target.type == 'java_group':
- # Java targets are handled outside of create_modules_from_target.
- return None
- else:
- raise Error('Unknown target %s (%s)' % (target.name, target.type))
-
- blueprint.add_module(module)
- module.init_rc = target_initrc.get(target.name, [])
- module.srcs.update(gn_utils.label_to_path(src)
- for src in target.sources if is_supported_source_file(src))
-
- # Add arch-specific properties
- for arch_name, arch in target.arch.items():
- module.target[arch_name].srcs.update(gn_utils.label_to_path(src)
- for src in arch.sources if is_supported_source_file(src))
-
- module.rtti = target.rtti
-
- if target.type in gn_utils.LINKER_UNIT_TYPES:
- set_module_flags(module, target.cflags, target.defines)
- set_module_include_dirs(module, target.cflags, target.include_dirs)
- # TODO: set_module_xxx is confusing, apply similar function to module and target in better way.
- for arch_name, arch in target.arch.items():
- set_module_flags(module.target[arch_name], arch.cflags, arch.defines)
- # -Xclang -target-feature -Xclang +mte are used to enable MTE (Memory Tagging Extensions).
- # Flags which does not start with '-' could not be in the cflags so enabling MTE by
- # -march and -mcpu Feature Modifiers. MTE is only available on arm64. This is needed for
- # building //base/allocator/partition_allocator:partition_alloc for arm64.
- if '+mte' in arch.cflags and arch_name == 'android_arm64':
- module.target[arch_name].cflags.add('-march=armv8-a+memtag')
- set_module_include_dirs(module.target[arch_name], arch.cflags, arch.include_dirs)
-
- module.host_supported = target.host_supported()
- module.device_supported = target.device_supported()
-
- if module.is_genrule():
- module.apex_available.add(tethering_apex)
-
- if module.is_compiled():
- # Don't try to inject library/source dependencies into genrules or
- # filegroups because they are not compiled in the traditional sense.
- module.defaults = [defaults_module]
- for lib in target.libs:
- # Generally library names should be mangled as 'libXXX', unless they
- # are HAL libraries (e.g., android.hardware.health@2.0) or AIDL c++ / NDK
- # libraries (e.g. "android.hardware.power.stats-V1-cpp")
- android_lib = lib if '@' in lib or "-cpp" in lib or "-ndk" in lib \
- else 'lib' + lib
- if lib in shared_library_allowlist:
- module.add_android_shared_lib(android_lib)
- if lib in static_library_allowlist:
- module.add_android_static_lib(android_lib)
-
- # If the module is a static library, export all the generated headers.
- if module.type == 'cc_library_static':
- module.export_generated_headers = module.generated_headers
-
- if module.name == 'cronet_aml_components_cronet_android_cronet':
- if target.output_name is None:
- raise Error('Failed to get output_name for libcronet name')
- # .so file name needs to match with CronetLibraryLoader.java (e.g. libcronet.109.0.5386.0.so)
- # So setting the output name based on the output_name from the desc.json
- module.stem = 'lib' + target.output_name
-
- # dep_name is an unmangled GN target name (e.g. //foo:bar(toolchain)).
- # Currently, only one module is generated from target even target has multiple toolchains.
- # And module is generated based on the first visited target.
- # Sort deps before iteration to make result deterministic.
- all_deps = sorted(target.deps | target.source_set_deps | target.transitive_proto_deps)
- for dep_name in all_deps:
- # |builtin_deps| override GN deps with Android-specific ones. See the
- # config in the top of this file.
- if dep_name in builtin_deps:
- builtin_deps[dep_name](module, None)
- continue
-
- dep_module = create_modules_from_target(blueprint, gn, dep_name)
-
- if dep_module is None:
- continue
- # TODO: Proper dependency check for genrule.
- # Currently, only propagating genrule dependencies.
- # Also, currently, all the dependencies are propagated upwards.
- # in gn, public_deps should be propagated but deps should not.
- # Not sure this information is available in the desc.json.
- # Following rule works for adding android_runtime_jni_headers to base:base.
- # If this doesn't work for other target, hardcoding for specific target
- # might be better.
- if module.is_genrule() and dep_module.is_genrule():
- module.genrule_headers.add(dep_module.name)
- module.genrule_headers.update(dep_module.genrule_headers)
-
- # For filegroups, and genrule, recurse but don't apply the
- # deps.
- if not module.is_compiled() or module.is_genrule():
- continue
-
- if dep_module.type == 'cc_library_shared':
- module.shared_libs.add(dep_module.name)
- elif dep_module.type == 'cc_library_static':
- module.static_libs.add(dep_module.name)
- elif dep_module.type == 'cc_object':
- module.merge_attribute('generated_headers', dep_module, target.arch.keys())
- if module.type != 'cc_object':
- if dep_module.has_input_files():
- # Only add it as part of srcs if the dep_module has input files otherwise
- # this would throw an error.
- module.srcs.add(":" + dep_module.name)
- module.merge_attribute('export_generated_headers', dep_module,
- target.arch.keys(), 'generated_headers')
- elif dep_module.type == 'cc_genrule':
- module.merge_attribute('generated_headers', dep_module, [], 'genrule_headers')
- module.merge_attribute('srcs', dep_module, [], 'genrule_srcs')
- module.merge_attribute('shared_libs', dep_module, [], 'genrule_shared_libs')
- module.merge_attribute('header_libs', dep_module, [], 'genrule_header_libs')
- if module.type not in ["cc_object"]:
- module.merge_attribute('export_generated_headers', dep_module, [],
- 'genrule_headers')
- elif dep_module.type == 'cc_binary':
- continue # Ignore executables deps (used by cmdline integration tests).
- else:
- raise Error('Unknown dep %s (%s) for target %s' %
- (dep_module.name, dep_module.type, module.name))
-
- for arch_name, arch in target.arch.items():
- for dep_name in arch.deps:
- # |builtin_deps| override GN deps with Android-specific ones. See the
- # config in the top of this file.
- if dep_name in builtin_deps:
- builtin_deps[dep_name](module, arch_name)
- continue
- dep_module = create_modules_from_target(blueprint, gn, dep_name)
- # Arch-specific dependencies currently only include cc_library_static.
- # Revisit this approach once we need to support more target types.
- if dep_module.type == 'cc_library_static':
- module.target[arch_name].static_libs.add(dep_module.name)
- elif dep_module.type == 'cc_genrule':
- if dep_module.name.endswith(arch_name):
- module.target[arch_name].generated_headers.update(dep_module.genrule_headers)
- module.target[arch_name].srcs.update(dep_module.genrule_srcs)
- module.target[arch_name].shared_libs.update(dep_module.genrule_shared_libs)
- module.target[arch_name].header_libs.update(dep_module.genrule_header_libs)
- if module.type not in ["cc_object"]:
- module.target[arch_name].export_generated_headers.update(
- dep_module.genrule_headers)
- elif dep_module.type == 'cc_object':
- if dep_module.has_input_files():
- # Only add it as part of srcs if the dep_module has input files otherwise
- # this would throw an error.
- module.target[arch_name].srcs.add(":" + dep_module.name)
- else:
- raise Error('Unsupported arch-specific dependency %s of target %s with type %s' %
- (dep_module.name, target.name, dep_module.type))
- return module
-
-def create_java_jni_preprocessor(blueprint):
- bp_module_name = module_prefix + 'java_jni_annotation_preprocessor'
- module = Module('java_plugin', bp_module_name, '//base/android/jni_generator:jni_processor')
- module.srcs.update(
- [
- "base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java",
- # Avoids a circular dependency with base:base_java. This is okay because
- # no target should ever expect to package an annotation processor.
- "build/android/java/src/org/chromium/build/annotations/CheckDiscard.java",
- "build/android/java/src/org/chromium/build/annotations/MainDex.java",
- "base/android/java/src/org/chromium/base/JniStaticTestMocker.java",
- "base/android/java/src/org/chromium/base/NativeLibraryLoadedStatus.java",
- "base/android/java/src/org/chromium/base/annotations/NativeMethods.java",
- "base/android/java/src/org/chromium/base/JniException.java",
- ":cronet_aml_build_android_build_config_gen",
- ])
- module.static_libs.update({
- "javapoet",
- "guava",
- "auto_service_annotations",
- })
- module.processor_class = "org.chromium.jni_generator.JniProcessor"
- blueprint.add_module(module)
- return module
-
-def get_java_sources(gn, predicate):
- java_sources = set()
- for target_name, sources in gn.java_sources.items():
- if predicate(target_name):
- java_sources.update(sources)
- return java_sources
-
-def get_java_actions(gn, predicate):
- java_actions = set()
- for target_name, actions in gn.java_actions.items():
- if predicate(target_name):
- java_actions.update(actions)
- return java_actions
-
-def get_non_api_java_sources(gn):
- return get_java_sources(gn, lambda name: name != java_api_target_name)
-
-def get_non_api_java_actions(gn):
- return get_java_actions(gn, lambda name: name != java_api_target_name)
-
-def get_api_java_sources(gn):
- return get_java_sources(gn, lambda name: name == java_api_target_name)
-
-def get_api_java_actions(gn):
- return get_java_actions(gn, lambda name: name == java_api_target_name)
-
-def create_java_module(blueprint, gn):
- bp_module_name = module_prefix + 'java'
- module = Module('java_library', bp_module_name, '//gn:java')
- module.srcs.update([gn_utils.label_to_path(source) for source in get_non_api_java_sources(gn)])
- module.libs = {
- "androidx.annotation_annotation",
- "jsr305",
- "androidx.annotation_annotation-experimental-nodeps",
- "framework-connectivity.stubs.module_lib",
- "framework-connectivity-t.stubs.module_lib",
- "framework-tethering.stubs.module_lib",
- "framework-wifi.stubs.module_lib",
- "framework-mediaprovider.stubs.module_lib",
- }
- module.static_libs = {
- "modules-utils-build_system",
- }
- module.aidl["include_dirs"] = {"frameworks/base/core/java/"}
- module.aidl["local_include_dirs"] = {"base/android/java/src/"}
- module.sdk_version = "module_current"
- module.min_sdk_version = 30
- module.apex_available.add(tethering_apex)
- # TODO: support for this flag is removed upstream in crrev/c/4062652.
- # Consider reverting this change upstream, or worst-case downstream. As an
- # alternative hack, we could rename the generated file to not conflict. This
- # would be less likely to conflict with upstream changes if the revert is not
- # accepted.
- module.javacflags.add("-Aorg.chromium.chrome.skipGenJni")
- module.javacflags.add("-Apackage_prefix=android.net.http.internal")
- for dep in get_non_api_java_actions(gn):
- target = gn.get_target(dep)
- if target.script == '//build/android/gyp/gcc_preprocess.py':
- module.srcs.add(':' + create_gcc_preprocess_modules(blueprint, target).name)
- else:
- module.srcs.add(':' + create_action_module(blueprint, target, 'java_genrule').name)
- preprocessor_module = create_java_jni_preprocessor(blueprint)
- module.plugins.add(preprocessor_module.name)
- blueprint.add_module(module)
- return module
-
-def create_java_api_module(blueprint, gn):
- source_module = Module('filegroup', module_prefix + 'api_sources', java_api_target_name)
- # TODO add the API helpers separately after the main API is checked in and thoroughly reviewed
- source_module.srcs.update([gn_utils.label_to_path(source)
- for source in get_api_java_sources(gn)
- if "apihelpers" not in source])
- source_module.comment += "\n// TODO(danstahr): add the API helpers separately after the main" \
- " API is checked in and thoroughly reviewed"
- source_module.srcs.update([
- ':' + create_action_module(blueprint, gn.get_target(dep), 'java_genrule').name
- for dep in get_api_java_actions(gn)])
- blueprint.add_module(source_module)
-
- java_module = Module('java_library', module_prefix + 'api_java', java_api_target_name)
- java_module.srcs.add(":" + source_module.name)
- java_module.sdk_version = "module_current"
- java_module.libs = {
- "androidx.annotation_annotation",
- "framework-annotations-lib",
- }
- blueprint.add_module(java_module)
- return java_module
-
-def update_jni_registration_module(module, gn):
- # TODO: java_sources might not contain all the required java files
- module.srcs.update([gn_utils.label_to_path(source)
- for source in get_non_api_java_sources(gn)
- if source.endswith('.java')])
-
-def create_blueprint_for_targets(gn, targets):
- """Generate a blueprint for a list of GN targets."""
- blueprint = Blueprint()
-
- # Default settings used by all modules.
- defaults = Module('cc_defaults', defaults_module, '//gn:default_deps')
- defaults.cflags = [
- '-DGOOGLE_PROTOBUF_NO_RTTI',
- '-Wno-error=return-type',
- '-Wno-non-virtual-dtor',
- '-Wno-macro-redefined',
- '-Wno-missing-field-initializers',
- '-Wno-sign-compare',
- '-Wno-sign-promo',
- '-Wno-unused-parameter',
- '-Wno-null-pointer-subtraction', # Needed to libevent
- '-fvisibility=hidden',
- '-Wno-ambiguous-reversed-operator', # needed for icui18n
- '-Wno-unreachable-code-loop-increment', # needed for icui18n
- '-O2',
- '-fPIC',
- ]
- # Chromium builds do not add a dependency for headers found inside the
- # sysroot, so they are added globally via defaults.
- defaults.target['android'].header_libs = [
- 'jni_headers',
- ]
- defaults.target['android'].shared_libs = [
- 'libmediandk'
- ]
- defaults.target['host'].cflags = [
- # -DANDROID is added by default but target.defines contain -DANDROID if
- # it's required. So adding -UANDROID to cancel default -DANDROID if it's
- # not specified.
- # Note: -DANDROID is not consistently applied across the chromium code
- # base, so it is removed unconditionally for host targets.
- '-UANDROID',
- ]
- defaults.stl = 'none'
- defaults.min_sdk_version = 29
- defaults.apex_available.add(tethering_apex)
- blueprint.add_module(defaults)
-
- for target in targets:
- create_modules_from_target(blueprint, gn, target)
-
- java_api_module = create_java_api_module(blueprint, gn)
- java_module = create_java_module(blueprint, gn)
- java_module.libs.add(java_api_module.name)
- for module in blueprint.modules.values():
- if 'cronet_jni_registration' in module.name:
- update_jni_registration_module(module, gn)
-
- # Merge in additional hardcoded arguments.
- for module in blueprint.modules.values():
- for key, add_val in additional_args.get(module.name, []):
- curr = getattr(module, key)
- if add_val and isinstance(add_val, set) and isinstance(curr, set):
- curr.update(add_val)
- elif isinstance(add_val, str) and (not curr or isinstance(curr, str)):
- setattr(module, key, add_val)
- elif isinstance(add_val, bool) and (not curr or isinstance(curr, bool)):
- setattr(module, key, add_val)
- elif isinstance(add_val, dict) and isinstance(curr, dict):
- curr.update(add_val)
- elif isinstance(add_val, dict) and isinstance(curr, Target):
- curr.__dict__.update(add_val)
- else:
- raise Error('Unimplemented type %r of additional_args: %r' %
- (type(add_val), key))
-
- return blueprint
-
-def create_license_module(blueprint):
- module = Module("license", "external_cronet_license", "LICENSE")
- module.license_kinds.update({
- 'SPDX-license-identifier-LGPL-2.1',
- 'SPDX-license-identifier-GPL-2.0',
- 'SPDX-license-identifier-MPL',
- 'SPDX-license-identifier-ISC',
- 'SPDX-license-identifier-GPL',
- 'SPDX-license-identifier-AFL-2.0',
- 'SPDX-license-identifier-MPL-2.0',
- 'SPDX-license-identifier-BSD',
- 'SPDX-license-identifier-Apache-2.0',
- 'SPDX-license-identifier-BSL-1.0',
- 'SPDX-license-identifier-LGPL',
- 'SPDX-license-identifier-GPL-3.0',
- 'SPDX-license-identifier-Unicode-DFS',
- 'SPDX-license-identifier-NCSA',
- 'SPDX-license-identifier-OpenSSL',
- 'SPDX-license-identifier-MIT',
- "SPDX-license-identifier-ICU",
- 'legacy_unencumbered', # public domain
- })
- module.license_text.update({
- "LICENSE",
- "net/third_party/uri_template/LICENSE",
- "net/third_party/quiche/src/LICENSE",
- "base/third_party/symbolize/LICENSE",
- "base/third_party/superfasthash/LICENSE",
- "base/third_party/xdg_user_dirs/LICENSE",
- "base/third_party/double_conversion/LICENSE",
- "base/third_party/nspr/LICENSE",
- "base/third_party/dynamic_annotations/LICENSE",
- "base/third_party/icu/LICENSE",
- "base/third_party/valgrind/LICENSE",
- "third_party/brotli/LICENSE",
- "third_party/protobuf/LICENSE",
- "third_party/protobuf/third_party/utf8_range/LICENSE",
- "third_party/metrics_proto/LICENSE",
- "third_party/boringssl/src/LICENSE",
- "third_party/boringssl/src/third_party/googletest/LICENSE",
- "third_party/boringssl/src/third_party/wycheproof_testvectors/LICENSE",
- "third_party/boringssl/src/third_party/fiat/LICENSE",
- "third_party/libevent/LICENSE",
- "third_party/ashmem/LICENSE",
- "third_party/icu/LICENSE",
- "third_party/icu/scripts/LICENSE",
- "third_party/abseil-cpp/LICENSE",
- "third_party/modp_b64/LICENSE",
- })
- default_license = Module("package", "", "PACKAGE")
- default_license.default_applicable_licenses.add(module.name)
- blueprint.add_module(module)
- blueprint.add_module(default_license)
-
-def main():
- parser = argparse.ArgumentParser(
- description='Generate Android.bp from a GN description.')
- parser.add_argument(
- '--desc',
- help='GN description (e.g., gn desc out --format=json --all-toolchains "//*".' +
- 'You can specify multiple --desc options for different target_cpu',
- required=True,
- action='append'
- )
- parser.add_argument(
- '--extras',
- help='Extra targets to include at the end of the Blueprint file',
- default=os.path.join(gn_utils.repo_root(), 'Android.bp.extras'),
- )
- parser.add_argument(
- '--output',
- help='Blueprint file to create',
- default=os.path.join(gn_utils.repo_root(), 'Android.bp'),
- )
- parser.add_argument(
- '-v',
- '--verbose',
- help='Print debug logs.',
- action='store_true',
- )
- parser.add_argument(
- 'targets',
- nargs=argparse.REMAINDER,
- help='Targets to include in the blueprint (e.g., "//:perfetto_tests")'
- )
- args = parser.parse_args()
-
- if args.verbose:
- log.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s', level=log.DEBUG)
-
- targets = args.targets or default_targets
- gn = gn_utils.GnParser(builtin_deps)
- for desc_file in args.desc:
- with open(desc_file) as f:
- desc = json.load(f)
- for target in targets:
- gn.parse_gn_desc(desc, target)
- blueprint = create_blueprint_for_targets(gn, targets)
- project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
- tool_name = os.path.relpath(os.path.abspath(__file__), project_root)
-
- # Add any proto groups to the blueprint.
- for l_name, t_names in proto_groups.items():
- create_proto_group_modules(blueprint, gn, l_name, t_names)
- create_license_module(blueprint)
- output = [
- """// Copyright (C) 2022 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.
-//
-// This file is automatically generated by %s. Do not edit.
-""" % (tool_name)
- ]
- blueprint.to_string(output)
- if os.path.exists(args.extras):
- with open(args.extras, 'r') as r:
- for line in r:
- output.append(line.rstrip("\n\r"))
-
- out_files = []
-
- # Generate the Android.bp file.
- out_files.append(args.output + '.swp')
- with open(out_files[-1], 'w') as f:
- f.write('\n'.join(output))
- # Text files should have a trailing EOL.
- f.write('\n')
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/tools/gn2bp/gen_desc_json.sh b/tools/gn2bp/gen_desc_json.sh
deleted file mode 100755
index 1f60eb9..0000000
--- a/tools/gn2bp/gen_desc_json.sh
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/bin/bash
-set -x
-
-# Run this script inside a full chromium checkout.
-
-OUT_PATH="out/cronet"
-
-#######################################
-# Apply patches in external/cronet.
-# Globals:
-# ANDROID_BUILD_TOP
-# Arguments:
-# None
-#######################################
-function apply_patches() {
- local -r patch_root="${ANDROID_BUILD_TOP}/external/cronet/patches"
-
- local upstream_patches
- upstream_patches=$(ls "${patch_root}/upstream-next")
- local patch
- for patch in ${upstream_patches}; do
- git am --3way "${patch_root}/upstream-next/${patch}"
- done
-
- local local_patches
- local_patches=$(ls "${patch_root}/local")
- for patch in ${local_patches}; do
- git am --3way "${patch_root}/local/${patch}"
- done
-}
-
-#######################################
-# Generate desc.json for a specified architecture.
-# Globals:
-# OUT_PATH
-# Arguments:
-# target_cpu, string
-#######################################
-function gn_desc() {
- local -a gn_args=(
- "target_os = \"android\""
- "enable_websockets = false"
- "disable_file_support = true"
- "disable_brotli_filter = false"
- "is_component_build = false"
- "use_crash_key_stubs = true"
- "use_partition_alloc = false"
- "include_transport_security_state_preload_list = false"
- "use_platform_icu_alternatives = true"
- "default_min_sdk_version = 19"
- "use_errorprone_java_compiler = true"
- "enable_reporting = true"
- "use_hashed_jni_names = true"
- "treat_warnings_as_errors = false"
- "enable_base_tracing = false"
- "is_cronet_build = true"
- "is_debug = false"
- "is_official_build = true"
- )
- gn_args+=("target_cpu = \"${1}\"")
-
- # Only set arm_use_neon on arm architectures to prevent warning from being
- # written to json output.
- if [[ "$1" =~ ^arm ]]; then
- gn_args+=("arm_use_neon = false")
- fi
-
- # Configure gn args.
- gn gen "${OUT_PATH}" --args="${gn_args[*]}"
-
- # Generate desc.json.
- local -r out_file="desc_${1}.json"
- gn desc "${OUT_PATH}" --format=json --all-toolchains "//*" > "${out_file}"
-}
-
-apply_patches
-gn_desc x86
-gn_desc x64
-gn_desc arm
-gn_desc arm64
-
diff --git a/tools/gn2bp/gn_utils.py b/tools/gn2bp/gn_utils.py
deleted file mode 100644
index 3d709e5..0000000
--- a/tools/gn2bp/gn_utils.py
+++ /dev/null
@@ -1,521 +0,0 @@
-# Copyright (C) 2022 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.
-
-# A collection of utilities for extracting build rule information from GN
-# projects.
-
-import copy
-import json
-import logging as log
-import os
-import re
-import collections
-
-BUILDFLAGS_TARGET = '//gn:gen_buildflags'
-GEN_VERSION_TARGET = '//src/base:version_gen_h'
-LINKER_UNIT_TYPES = ('executable', 'shared_library', 'static_library', 'source_set')
-JAVA_BANNED_SCRIPTS = [
- "//build/android/gyp/turbine.py",
- "//build/android/gyp/compile_java.py",
- "//build/android/gyp/filter_zip.py",
- "//build/android/gyp/dex.py",
- "//build/android/gyp/write_build_config.py",
- "//build/android/gyp/create_r_java.py",
- "//build/android/gyp/ijar.py",
- "//build/android/gyp/create_r_java.py",
- "//build/android/gyp/bytecode_processor.py",
- "//build/android/gyp/prepare_resources.py",
- "//build/android/gyp/aar.py",
- "//build/android/gyp/zip.py",
-]
-# TODO(primiano): investigate these, they require further componentization.
-ODR_VIOLATION_IGNORE_TARGETS = {
- '//test/cts:perfetto_cts_deps',
- '//:perfetto_integrationtests',
-}
-ARCH_REGEX = r'(android_x86_64|android_x86|android_arm|android_arm64|host)'
-RESPONSE_FILE = '{{response_file_name}}'
-
-def repo_root():
- """Returns an absolute path to the repository root."""
- return os.path.join(
- os.path.realpath(os.path.dirname(__file__)), os.path.pardir)
-
-
-def label_to_path(label):
- """Turn a GN output label (e.g., //some_dir/file.cc) into a path."""
- assert label.startswith('//')
- return label[2:] or "./"
-
-
-def label_without_toolchain(label):
- """Strips the toolchain from a GN label.
-
- Return a GN label (e.g //buildtools:protobuf(//gn/standalone/toolchain:
- gcc_like_host) without the parenthesised toolchain part.
- """
- return label.split('(')[0]
-
-
-def label_to_target_name_with_path(label):
- """
- Turn a GN label into a target name involving the full path.
- e.g., //src/perfetto:tests -> src_perfetto_tests
- """
- name = re.sub(r'^//:?', '', label)
- name = re.sub(r'[^a-zA-Z0-9_]', '_', name)
- return name
-
-def _is_java_source(src):
- return os.path.splitext(src)[1] == '.java' and not src.startswith("//out/")
-
-def is_java_action(script, outputs):
- return (script != "" and script not in JAVA_BANNED_SCRIPTS) and any(
- [file.endswith(".srcjar") or file.endswith(".java")
- for file in outputs])
-
-class GnParser(object):
- """A parser with some cleverness for GN json desc files
-
- The main goals of this parser are:
- 1) Deal with the fact that other build systems don't have an equivalent
- notion to GN's source_set. Conversely to Bazel's and Soong's filegroups,
- GN source_sets expect that dependencies, cflags and other source_set
- properties propagate up to the linker unit (static_library, executable or
- shared_library). This parser simulates the same behavior: when a
- source_set is encountered, some of its variables (cflags and such) are
- copied up to the dependent targets. This is to allow gen_xxx to create
- one filegroup for each source_set and then squash all the other flags
- onto the linker unit.
- 2) Detect and special-case protobuf targets, figuring out the protoc-plugin
- being used.
- """
-
- class Target(object):
- """Reperesents A GN target.
-
- Maked properties are propagated up the dependency chain when a
- source_set dependency is encountered.
- """
- class Arch():
- """Architecture-dependent properties
- """
- def __init__(self):
- self.sources = set()
- self.cflags = set()
- self.defines = set()
- self.include_dirs = set()
- self.deps = set()
- self.transitive_static_libs_deps = set()
- self.source_set_deps = set()
-
- # These are valid only for type == 'action'
- self.inputs = set()
- self.outputs = set()
- self.args = []
- self.script = ''
- self.response_file_contents = ''
-
- def __init__(self, name, type):
- self.name = name # e.g. //src/ipc:ipc
-
- VALID_TYPES = ('static_library', 'shared_library', 'executable', 'group',
- 'action', 'source_set', 'proto_library', 'copy', 'action_foreach')
- assert (type in VALID_TYPES)
- self.type = type
- self.testonly = False
- self.toolchain = None
-
- # These are valid only for type == proto_library.
- # This is typically: 'proto', 'protozero', 'ipc'.
- self.proto_plugin = None
- self.proto_paths = set()
- self.proto_exports = set()
- self.proto_in_dir = ""
-
- self.sources = set()
- # TODO(primiano): consider whether the public section should be part of
- # bubbled-up sources.
- self.public_headers = set() # 'public'
-
- # These are valid only for type == 'action'
- self.inputs = set()
- self.outputs = set()
- self.script = ''
- self.args = []
- self.response_file_contents = ''
-
- # These variables are propagated up when encountering a dependency
- # on a source_set target.
- self.cflags = set()
- self.defines = set()
- self.deps = set()
- self.libs = set()
- self.include_dirs = set()
- self.ldflags = set()
- self.source_set_deps = set() # Transitive set of source_set deps.
- self.proto_deps = set()
- self.transitive_proto_deps = set()
- self.rtti = False
-
- # TODO: come up with a better way to only run this once.
- # is_finalized tracks whether finalize() was called on this target.
- self.is_finalized = False
- self.arch = dict()
-
- # This is used to get the name/version of libcronet
- self.output_name = None
-
- def host_supported(self):
- return 'host' in self.arch
-
- def device_supported(self):
- return any([name.startswith('android') for name in self.arch.keys()])
-
- def is_linker_unit_type(self):
- return self.type in LINKER_UNIT_TYPES
-
- def __lt__(self, other):
- if isinstance(other, self.__class__):
- return self.name < other.name
- raise TypeError(
- '\'<\' not supported between instances of \'%s\' and \'%s\'' %
- (type(self).__name__, type(other).__name__))
-
- def __repr__(self):
- return json.dumps({
- k: (list(sorted(v)) if isinstance(v, set) else v)
- for (k, v) in self.__dict__.items()
- },
- indent=4,
- sort_keys=True)
-
- def update(self, other, arch):
- for key in ('cflags', 'defines', 'deps', 'include_dirs', 'ldflags',
- 'source_set_deps', 'proto_deps', 'transitive_proto_deps',
- 'libs', 'proto_paths'):
- self.__dict__[key].update(other.__dict__.get(key, []))
-
- for key_in_arch in ('cflags', 'defines', 'include_dirs', 'source_set_deps'):
- self.arch[arch].__dict__[key_in_arch].update(
- other.arch[arch].__dict__.get(key_in_arch, []))
-
- def _finalize_set_attribute(self, key):
- # Target contains the intersection of arch-dependent properties
- getattr(self, key)\
- .update(set.intersection(*[getattr(arch, key) for arch in self.arch.values()]))
-
- # Deduplicate arch-dependent properties
- for arch in self.arch.values():
- getattr(arch, key).difference_update(getattr(self, key))
-
- def _finalize_non_set_attribute(self, key):
- # Only when all the arch has the same non empty value, move the value to the target common
- val = getattr(list(self.arch.values())[0], key)
- if val and all([val == getattr(arch, key) for arch in self.arch.values()]):
- setattr(self, key, copy.deepcopy(val))
- for arch in self.arch.values():
- getattr(arch, key, None)
-
- def _finalize_attribute(self, key):
- val = getattr(self, key)
- if isinstance(val, set):
- self._finalize_set_attribute(key)
- elif isinstance(val, (list, str)):
- self._finalize_non_set_attribute(key)
- else:
- raise TypeError(f'Unsupported type: {type(val)}')
-
- def finalize(self):
- """Move common properties out of arch-dependent subobjects to Target object.
-
- TODO: find a better name for this function.
- """
- if self.is_finalized:
- return
- self.is_finalized = True
-
- if len(self.arch) == 0:
- return
-
- for key in ('sources', 'cflags', 'defines', 'include_dirs', 'deps', 'source_set_deps',
- 'inputs', 'outputs', 'args', 'script', 'response_file_contents'):
- self._finalize_attribute(key)
-
-
- def __init__(self, builtin_deps):
- self.builtin_deps = builtin_deps
- self.all_targets = {}
- self.linker_units = {} # Executables, shared or static libraries.
- self.source_sets = {}
- self.actions = {}
- self.proto_libs = {}
- self.java_sources = collections.defaultdict(set)
- self.java_actions = collections.defaultdict(set)
-
- def _get_response_file_contents(self, action_desc):
- # response_file_contents are formatted as:
- # ['--flags', '--flag=true && false'] and need to be formatted as:
- # '--flags --flag=\"true && false\"'
- flags = action_desc.get('response_file_contents', [])
- formatted_flags = []
- for flag in flags:
- if '=' in flag:
- key, val = flag.split('=')
- formatted_flags.append('%s=\\"%s\\"' % (key, val))
- else:
- formatted_flags.append(flag)
-
- return ' '.join(formatted_flags)
-
- def _is_java_group(self, type_, target_name):
- # Per https://chromium.googlesource.com/chromium/src/build/+/HEAD/android/docs/java_toolchain.md
- # java target names must end in "_java".
- # TODO: There are some other possible variations we might need to support.
- return type_ == 'group' and target_name.endswith('_java')
-
- def _get_arch(self, toolchain):
- if toolchain == '//build/toolchain/android:android_clang_x86':
- return 'android_x86'
- elif toolchain == '//build/toolchain/android:android_clang_x64':
- return 'android_x86_64'
- elif toolchain == '//build/toolchain/android:android_clang_arm':
- return 'android_arm'
- elif toolchain == '//build/toolchain/android:android_clang_arm64':
- return 'android_arm64'
- else:
- return 'host'
-
- def get_target(self, gn_target_name):
- """Returns a Target object from the fully qualified GN target name.
-
- get_target() requires that parse_gn_desc() has already been called.
- """
- # Run this every time as parse_gn_desc can be called at any time.
- for target in self.all_targets.values():
- target.finalize()
-
- return self.all_targets[label_without_toolchain(gn_target_name)]
-
- def parse_gn_desc(self, gn_desc, gn_target_name, java_group_name=None):
- """Parses a gn desc tree and resolves all target dependencies.
-
- It bubbles up variables from source_set dependencies as described in the
- class-level comments.
- """
- # Use name without toolchain for targets to support targets built for
- # multiple archs.
- target_name = label_without_toolchain(gn_target_name)
- desc = gn_desc[gn_target_name]
- type_ = desc['type']
- arch = self._get_arch(desc['toolchain'])
-
- if self._is_java_group(type_, target_name):
- java_group_name = target_name
-
- target = self.all_targets.get(target_name)
- if target is None:
- target = GnParser.Target(target_name, type_)
- self.all_targets[target_name] = target
-
- if arch not in target.arch:
- target.arch[arch] = GnParser.Target.Arch()
- else:
- return target # Target already processed.
-
- if target.name in self.builtin_deps:
- # return early, no need to parse any further as the module is a builtin.
- return target
-
- target.testonly = desc.get('testonly', False)
-
- proto_target_type, proto_desc = self.get_proto_target_type(gn_desc, gn_target_name)
- if proto_target_type is not None:
- self.proto_libs[target.name] = target
- target.type = 'proto_library'
- target.proto_plugin = proto_target_type
- target.proto_paths.update(self.get_proto_paths(proto_desc))
- target.proto_exports.update(self.get_proto_exports(proto_desc))
- target.proto_in_dir = self.get_proto_in_dir(proto_desc)
- for gn_proto_deps_name in proto_desc.get('deps', []):
- dep = self.parse_gn_desc(gn_desc, gn_proto_deps_name)
- target.deps.add(dep.name)
- target.arch[arch].sources.update(proto_desc.get('sources', []))
- assert (all(x.endswith('.proto') for x in target.arch[arch].sources))
- elif target.type == 'source_set':
- self.source_sets[gn_target_name] = target
- target.arch[arch].sources.update(desc.get('sources', []))
- elif target.is_linker_unit_type():
- self.linker_units[gn_target_name] = target
- target.arch[arch].sources.update(desc.get('sources', []))
- elif (desc.get("script", "") in JAVA_BANNED_SCRIPTS
- or self._is_java_group(target.type, target.name)):
- # java_group identifies the group target generated by the android_library
- # or java_library template. A java_group must not be added as a
- # dependency, but sources are collected.
- log.debug('Found java target %s', target.name)
- if target.type == "action":
- # Convert java actions into java_group and keep the inputs for collection.
- target.inputs.update(desc.get('inputs', []))
- target.type = 'java_group'
- elif target.type in ['action', 'action_foreach']:
- self.actions[gn_target_name] = target
- target.arch[arch].inputs.update(desc.get('inputs', []))
- target.arch[arch].sources.update(desc.get('sources', []))
- outs = [re.sub('^//out/.+?/gen/', '', x) for x in desc['outputs']]
- target.arch[arch].outputs.update(outs)
- target.arch[arch].script = desc['script']
- target.arch[arch].args = desc['args']
- target.arch[arch].response_file_contents = self._get_response_file_contents(desc)
- elif target.type == 'copy':
- # TODO: copy rules are not currently implemented.
- self.actions[gn_target_name] = target
-
- # Default for 'public' is //* - all headers in 'sources' are public.
- # TODO(primiano): if a 'public' section is specified (even if empty), then
- # the rest of 'sources' is considered inaccessible by gn. Consider
- # emulating that, so that generated build files don't end up with overly
- # accessible headers.
- public_headers = [x for x in desc.get('public', []) if x != '*']
- target.public_headers.update(public_headers)
-
- target.arch[arch].cflags.update(desc.get('cflags', []) + desc.get('cflags_cc', []))
- target.libs.update(desc.get('libs', []))
- target.ldflags.update(desc.get('ldflags', []))
- target.arch[arch].defines.update(desc.get('defines', []))
- target.arch[arch].include_dirs.update(desc.get('include_dirs', []))
- target.output_name = desc.get('output_name', None)
- if "-frtti" in target.arch[arch].cflags:
- target.rtti = True
-
- # Recurse in dependencies.
- for gn_dep_name in desc.get('deps', []):
- dep = self.parse_gn_desc(gn_desc, gn_dep_name, java_group_name)
- if dep.type == 'proto_library':
- target.proto_deps.add(dep.name)
- target.transitive_proto_deps.add(dep.name)
- target.proto_paths.update(dep.proto_paths)
- target.transitive_proto_deps.update(dep.transitive_proto_deps)
- elif dep.type == 'source_set':
- target.arch[arch].source_set_deps.add(dep.name)
- target.arch[arch].source_set_deps.update(dep.arch[arch].source_set_deps)
- # flatten source_set deps
- if target.is_linker_unit_type():
- # This ensure that all transitive source set dependencies are
- # propagated upward to the linker units.
- target.arch[arch].deps.update(target.arch[arch].source_set_deps)
- elif dep.type == 'group':
- target.update(dep, arch) # Bubble up groups's cflags/ldflags etc.
- elif dep.type in ['action', 'action_foreach', 'copy']:
- if proto_target_type is None:
- target.arch[arch].deps.add(dep.name)
- elif dep.is_linker_unit_type():
- target.arch[arch].deps.add(dep.name)
- elif dep.type == 'java_group':
- # Explicitly break dependency chain when a java_group is added.
- # Java sources are collected and eventually compiled as one large
- # java_library.
- pass
-
- # Source set bubble up transitive source sets but can't be combined with this
- # if they are combined then source sets will bubble up static libraries
- # while we only want to have source sets bubble up only source sets.
- if dep.type == 'static_library':
- # Bubble up static_libs. Necessary, since soong does not propagate
- # static_libs up the build tree.
- target.arch[arch].transitive_static_libs_deps.add(dep.name)
-
- if arch in dep.arch:
- target.arch[arch].transitive_static_libs_deps.update(
- dep.arch[arch].transitive_static_libs_deps)
- target.arch[arch].deps.update(target.arch[arch].transitive_static_libs_deps)
-
- # Collect java sources. Java sources are kept inside the __compile_java target.
- # This target can be used for both host and target compilation; only add
- # the sources if they are destined for the target (i.e. they are a
- # dependency of the __dex target)
- # Note: this skips prebuilt java dependencies. These will have to be
- # added manually when building the jar.
- if target.name.endswith('__dex'):
- if dep.name.endswith('__compile_java'):
- log.debug('Adding java sources for %s', dep.name)
- java_srcs = [src for src in dep.inputs if _is_java_source(src)]
- self.java_sources[java_group_name].update(java_srcs)
- if dep.type in ["action"] and target.type == "java_group":
- # //base:base_java_aidl generates srcjar from .aidl files. But java_library in soong can
- # directly have .aidl files in srcs. So adding .aidl files to the java_sources.
- # TODO: Find a better way/place to do this.
- if dep.name == '//base:base_java_aidl':
- self.java_sources[java_group_name].update(dep.arch[arch].sources)
- else:
- self.java_actions[java_group_name].add(dep.name)
- return target
-
- def get_proto_exports(self, proto_desc):
- # exports in metadata will be available for source_set targets.
- metadata = proto_desc.get('metadata', {})
- return metadata.get('exports', [])
-
- def get_proto_paths(self, proto_desc):
- # import_dirs in metadata will be available for source_set targets.
- metadata = proto_desc.get('metadata', {})
- return metadata.get('import_dirs', [])
-
-
- def get_proto_in_dir(self, proto_desc):
- args = proto_desc.get('args')
- return re.sub('^\.\./\.\./', '', args[args.index('--proto-in-dir') + 1])
-
- def get_proto_target_type(self, gn_desc, gn_target_name):
- """ Checks if the target is a proto library and return the plugin.
-
- Returns:
- (None, None): if the target is not a proto library.
- (plugin, proto_desc) where |plugin| is 'proto' in the default (lite)
- case or 'protozero' or 'ipc' or 'descriptor'; |proto_desc| is the GN
- json desc of the target with the .proto sources (_gen target for
- non-descriptor types or the target itself for descriptor type).
- """
- parts = gn_target_name.split('(', 1)
- name = parts[0]
- toolchain = '(' + parts[1] if len(parts) > 1 else ''
-
- # Descriptor targets don't have a _gen target; instead we look for the
- # characteristic flag in the args of the target itself.
- desc = gn_desc.get(gn_target_name)
- if '--descriptor_set_out' in desc.get('args', []):
- return 'descriptor', desc
-
- # Source set proto targets have a non-empty proto_library_sources in the
- # metadata of the description.
- metadata = desc.get('metadata', {})
- if 'proto_library_sources' in metadata:
- return 'source_set', desc
-
- # In all other cases, we want to look at the _gen target as that has the
- # important information.
- gen_desc = gn_desc.get('%s_gen%s' % (name, toolchain))
- if gen_desc is None or gen_desc['type'] != 'action':
- return None, None
- if gen_desc['script'] != '//tools/protoc_wrapper/protoc_wrapper.py':
- return None, None
- plugin = 'proto'
- args = gen_desc.get('args', [])
- for arg in (arg for arg in args if arg.startswith('--plugin=')):
- # |arg| at this point looks like:
- # --plugin=protoc-gen-plugin=gcc_like_host/protozero_plugin
- # or
- # --plugin=protoc-gen-plugin=protozero_plugin
- plugin = arg.split('=')[-1].split('/')[-1].replace('_plugin', '')
- return plugin, gen_desc
diff --git a/tools/gn2bp/update_results.sh b/tools/gn2bp/update_results.sh
deleted file mode 100755
index a464604..0000000
--- a/tools/gn2bp/update_results.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-
-# This script is expected to run after gen_android_bp is modified.
-#
-# ./update_result.sh
-#
-# TARGETS contains targets which are supported by gen_android_bp and
-# this script generates Android.bp.swp from TARGETS.
-# This makes it easy to realize unintended impact/degression on
-# previously supported targets.
-
-set -eux
-
-BASEDIR=$(dirname "$0")
-$BASEDIR/gen_android_bp --desc $BASEDIR/desc_x64.json --desc $BASEDIR/desc_x86.json \
---desc $BASEDIR/desc_arm.json --desc $BASEDIR/desc_arm64.json --out $BASEDIR/Android.bp