Merge "Add CTS for ConnectionMigrationOptions API"
diff --git a/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt b/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
index 65cf8fb..b96e931 100644
--- a/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
+++ b/Cronet/tests/cts/src/android/net/http/cts/DnsOptionsTest.kt
@@ -22,6 +22,7 @@
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
+import kotlin.test.assertNull
import kotlin.test.assertTrue
import org.junit.runner.RunWith
@@ -29,6 +30,18 @@
class DnsOptionsTest {
@Test
+ fun testDnsOptions_defaultValues() {
+ val options = DnsOptions.Builder().build()
+
+ assertNull(options.persistHostCache)
+ assertNull(options.persistHostCachePeriod)
+ assertNull(options.enableStaleDns)
+ assertNull(options.staleDnsOptions)
+ assertNull(options.useHttpStackDnsResolver)
+ assertNull(options.preestablishConnectionsToStaleDnsResults)
+ }
+
+ @Test
fun testDnsOptions_persistHostCache_returnSetValue() {
val options = DnsOptions.Builder().setPersistHostCache(true).build()
@@ -38,9 +51,78 @@
@Test
fun testDnsOptions_persistHostCachePeriod_returnSetValue() {
- val period = Duration.ZERO
+ 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().setEnableStaleDns(true).build()
+
+ assertNotNull(options.enableStaleDns)
+ assertTrue(options.enableStaleDns!!)
+ }
+
+ @Test
+ fun testDnsOptions_useHttpStackDnsResolver_returnsSetValue() {
+ val options = DnsOptions.Builder().setUseHttpStackDnsResolver(true).build()
+
+ assertNotNull(options.useHttpStackDnsResolver)
+ assertTrue(options.useHttpStackDnsResolver!!)
+ }
+
+ @Test
+ fun testDnsOptions_preestablishConnectionsToStaleDnsResults_returnsSetValue() {
+ val options = DnsOptions.Builder().setPreestablishConnectionsToStaleDnsResults(true).build()
+
+ assertNotNull(options.preestablishConnectionsToStaleDnsResults)
+ assertTrue(options.preestablishConnectionsToStaleDnsResults!!)
+ }
+
+ @Test
+ fun testStaleDnsOptions_defaultValues() {
+ val options = DnsOptions.StaleDnsOptions.Builder().build()
+
+ assertNull(options.allowCrossNetworkUsage)
+ assertNull(options.freshLookupTimeoutMillis)
+ assertNull(options.maxExpiredDelayMillis)
+ assertNull(options.useStaleOnNameNotResolved)
+ }
+
+ @Test
+ fun testStaleDnsOptions_allowCrossNetworkUsage_returnsSetValue() {
+ val options = DnsOptions.StaleDnsOptions.Builder().setAllowCrossNetworkUsage(true).build()
+
+ assertNotNull(options.allowCrossNetworkUsage)
+ assertTrue(options.allowCrossNetworkUsage!!)
+ }
+
+ @Test
+ fun testStaleDnsOptions_freshLookupTimeout_returnsSetValue() {
+ val duration = Duration.ofMillis(12345)
+ val options = DnsOptions.StaleDnsOptions.Builder().setFreshLookupTimeout(duration).build()
+
+ assertNotNull(options.freshLookupTimeoutMillis)
+ assertEquals(duration.toMillis(), options.freshLookupTimeoutMillis!!)
+ }
+
+ @Test
+ fun testStaleDnsOptions_useStaleOnNameNotResolved_returnsSetValue() {
+ val options =
+ DnsOptions.StaleDnsOptions.Builder().setUseStaleOnNameNotResolved(true).build()
+
+ assertNotNull(options.useStaleOnNameNotResolved)
+ assertTrue(options.useStaleOnNameNotResolved!!)
+ }
+
+ @Test
+ fun testStaleDnsOptions_maxExpiredDelayMillis_returnsSetValue() {
+ val duration = Duration.ofMillis(12345)
+ val options = DnsOptions.StaleDnsOptions.Builder().setMaxExpiredDelay(duration).build()
+
+ assertNotNull(options.maxExpiredDelayMillis)
+ assertEquals(duration.toMillis(), options.maxExpiredDelayMillis!!)
+ }
}
diff --git a/Cronet/tools/import/copy.bara.sky b/Cronet/tools/import/copy.bara.sky
new file mode 100644
index 0000000..64256a0
--- /dev/null
+++ b/Cronet/tools/import/copy.bara.sky
@@ -0,0 +1,110 @@
+# 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",
+]
+
+cronet_origin_files = glob(
+ include = [
+ "base/**",
+ "build/**",
+ "build/buildflag.h",
+ "chrome/VERSION",
+ "components/cronet/**",
+ "components/grpc_suport/**",
+ "components/metrics/**",
+ "components/nacl/**",
+ "components/prefs/**",
+ "crypto/**",
+ "ipc/**",
+ "net/**",
+ "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/**",
+
+
+ # 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/**",
+ # TODO: we should be able to remove this dependency.
+ "base/third_party/symbolize/**",
+ "base/third_party/valgrind/**",
+ "base/third_party/xdg_user_dirs/**",
+ # Not present in source repo; requires gclient sync.
+ "buildtools/third_party/libc++/**",
+ # Not present in source repo; requires gclient sync.
+ "buildtools/third_party/libc++abi/**",
+ "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/**",
+ # Not present in source repo; requires gclient sync.
+ "third_party/icu/**",
+ "third_party/libevent/**",
+ "third_party/metrics_proto/**",
+ "third_party/modp_b64/**",
+ "third_party/protobuf/**",
+ "third_party/zlib/**",
+ ],
+ exclude = common_excludes,
+)
+
+core.workflow(
+ name = "import_cronet",
+ authoring = authoring.overwrite("Cronet Mainline Eng <cronet-mainline-eng+copybara@google.com>"),
+ origin = git.origin(
+ url = "rpc://chromium/chromium/src",
+ # Source ref is set by the invoking script.
+ ref = "overwritten-by-script",
+ partial_fetch = True,
+ ),
+ 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..7642914
--- /dev/null
+++ b/Cronet/tools/import/import_cronet.sh
@@ -0,0 +1,76 @@
+#!/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: The last revision that was imported.
+# -n: The new revision to import.
+
+OPTSTRING=l:n:
+
+usage() {
+ cat <<EOF
+Usage: import_cronet.sh -l last-rev -n new-rev
+EOF
+ exit 1
+}
+
+#######################################
+# Runs the copybara import of Chromium
+# Globals:
+# ANDROID_BUILD_TOP
+# Arguments:
+# last_rev, string
+# new_rev, string
+#######################################
+do_run_copybara() {
+ local _last_rev=$1
+ local _new_rev=$2
+
+ /google/bin/releases/copybara/public/copybara/copybara \
+ --git-destination-url="file://${ANDROID_BUILD_TOP}/external/cronet" \
+ --last-rev "${_last_rev}" \
+ --repo-timeout 3h \
+ "${ANDROID_BUILD_TOP}/packages/modules/Connectivity/Cronet/tools/import/copy.bara.sky" \
+ import_cronet "${_new_rev}"
+}
+
+while getopts $OPTSTRING opt; do
+ case "${opt}" in
+ l) last_rev="${OPTARG}" ;;
+ n) new_rev="${OPTARG}" ;;
+ ?) usage ;;
+ *) echo "'${opt}' '${OPTARG}'"
+ esac
+done
+
+# TODO: Get last-rev from METADATA file.
+# Setting last-rev may only be required for the first commit.
+if [ -z "${last_rev}" ]; then
+ echo "-l argument required"
+ usage
+fi
+
+if [ -z "${new_rev}" ]; then
+ echo "-n argument required"
+ usage
+fi
+
+do_run_copybara "${last_rev}" "${new_rev}"
+
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 34646e2..4d3ecdf 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -58,6 +58,17 @@
]
},
{
+ "name": "CtsNetTestCasesMaxTargetSdk33",
+ "options": [
+ {
+ "exclude-annotation": "com.android.testutils.SkipPresubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "bpf_existence_test"
},
{
@@ -143,6 +154,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
{
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/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
index 748b1ba..b26aeaa 100644
--- a/framework-t/src/android/net/NetworkTemplate.java
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -48,6 +48,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.CollectionUtils;
@@ -70,6 +71,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 = {
@@ -270,12 +273,17 @@
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)) {
+ }
+ // fall through
+ case MATCH_MOBILE:
+ if (CollectionUtils.contains(matchSubscriberIds, null)) {
throw new IllegalArgumentException("checkValidMatchSubscriberIds list of ids"
+ " may not contain null for rule " + getMatchRuleName(matchRule));
}
@@ -296,12 +304,36 @@
// 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 */
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 394292e..e32ea8f 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -8854,6 +8854,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)
@@ -8884,8 +8887,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);
}
}
diff --git a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
index cd7a842..9f9b496 100644
--- a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
@@ -34,18 +34,13 @@
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.InvalidSocketException;
-import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
@@ -61,7 +56,6 @@
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;
@@ -94,8 +88,6 @@
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_BINDER_TOKEN = "token";
private static final long DEFAULT_TCP_POLLING_INTERVAL_MS = 120_000L;
private static final long LOW_TCP_POLLING_INTERVAL_MS = 1_000L;
@@ -160,19 +152,6 @@
// 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 IBinder token = intent.getBundleExtra(EXTRA_BINDER_TOKEN).getBinder(
- EXTRA_BINDER_TOKEN);
- mConnectivityServiceHandler.obtainMessage(
- NetworkAgent.CMD_MONITOR_AUTOMATIC_KEEPALIVE, token).sendToTarget();
- }
- }
- };
-
/**
* Information about a managed keepalive.
*
@@ -193,7 +172,7 @@
@Nullable
private final FileDescriptor mFd;
@Nullable
- private final PendingIntent mTcpPollingAlarm;
+ private final AlarmManager.OnAlarmListener mAlarmListener;
@AutomaticOnOffState
private int mAutomaticOnOffState;
@Nullable
@@ -219,17 +198,24 @@
Log.e(TAG, "Cannot dup fd: ", e);
throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
}
- mTcpPollingAlarm = createTcpPollingAlarmIntent(context, mCallback.asBinder());
+ mAlarmListener = () -> mConnectivityServiceHandler.obtainMessage(
+ NetworkAgent.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;
- mTcpPollingAlarm = null;
+ mAlarmListener = null;
}
}
+ @VisibleForTesting
+ public ISocketKeepaliveCallback getCallback() {
+ return mCallback;
+ }
+
public Network getNetwork() {
return mKi.getNai().network;
}
@@ -243,17 +229,6 @@
return mKi.getNai().network().equals(network) && mKi.getSlot() == slot;
}
- private PendingIntent createTcpPollingAlarmIntent(@NonNull Context context,
- @NonNull IBinder token) {
- final Intent intent = new Intent(ACTION_TCP_POLLING_ALARM);
- // Intent doesn't expose methods to put extra Binders, but Bundle does.
- final Bundle b = new Bundle();
- b.putBinder(EXTRA_BINDER_TOKEN, token);
- intent.putExtra(EXTRA_BINDER_TOKEN, b);
- return BinderUtils.withCleanCallingIdentity(() -> PendingIntent.getBroadcast(
- context, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE));
- }
-
@Override
public void binderDied() {
mConnectivityServiceHandler.post(() -> cleanupAutoOnOffKeepalive(this));
@@ -303,18 +278,15 @@
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 final AlarmManager.OnAlarmListener listener) {
final long triggerAtMillis =
SystemClock.elapsedRealtime() + getTcpPollingInterval();
// Setup a non-wake up alarm.
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, triggerAtMillis, alarm);
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, triggerAtMillis, null /* tag */,
+ listener, mConnectivityServiceHandler);
}
/**
@@ -351,7 +323,7 @@
handleMaybeResumeKeepalive(ki);
}
// TODO: listen to socket status instead of periodically check.
- startTcpPollingAlarm(ki.mTcpPollingAlarm);
+ startTcpPollingAlarm(ki.mAlarmListener);
}
/**
@@ -431,7 +403,7 @@
}
mAutomaticOnOffKeepalives.add(autoKi);
if (STATE_ALWAYS_ON != autoKi.mAutomaticOnOffState) {
- startTcpPollingAlarm(autoKi.mTcpPollingAlarm);
+ startTcpPollingAlarm(autoKi.mAlarmListener);
}
}
@@ -463,7 +435,7 @@
private void cleanupAutoOnOffKeepalive(@NonNull final AutomaticOnOffKeepalive autoKi) {
ensureRunningOnHandlerThread();
autoKi.close();
- if (null != autoKi.mTcpPollingAlarm) mAlarmManager.cancel(autoKi.mTcpPollingAlarm);
+ 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
@@ -769,6 +741,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.
diff --git a/service/src/com/android/server/connectivity/KeepaliveTracker.java b/service/src/com/android/server/connectivity/KeepaliveTracker.java
index 5572361..06294db 100644
--- a/service/src/com/android/server/connectivity/KeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/KeepaliveTracker.java
@@ -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,7 +126,8 @@
* 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 {
+ @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.
diff --git a/tests/common/java/android/net/netstats/NetworkTemplateTest.kt b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
index 99f1e0b..c2eacbc 100644
--- a/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
+++ b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
@@ -95,6 +95,13 @@
NetworkTemplate.Builder(MATCH_CARRIER).build()
}
+ // Verify carrier and mobile template cannot contain one of subscriber Id is null.
+ listOf(MATCH_MOBILE, MATCH_CARRIER).forEach {
+ assertFailsWith<IllegalArgumentException> {
+ NetworkTemplate.Builder(it).setSubscriberIds(setOf(null)).build()
+ }
+ }
+
// Verify template which matches metered cellular networks,
// regardless of IMSI. See buildTemplateMobileWildcard.
NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build().let {
@@ -158,6 +165,23 @@
}
@Test
+ fun testUnsupportedAppUsageConstructor() {
+ val templateMobile = NetworkTemplate(MATCH_MOBILE, null /* subscriberId */,
+ null /* wifiNetworkKey */)
+ val templateMobileWildcard = NetworkTemplate(6 /* MATCH_MOBILE_WILDCARD */,
+ null /* subscriberId */, null /* wifiNetworkKey */)
+ val templateWifiWildcard = NetworkTemplate(7 /* MATCH_WIFI_WILDCARD */,
+ null /* subscriberId */,
+ null /* wifiNetworkKey */)
+
+ assertEquals(NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build(),
+ templateMobile)
+ assertEquals(NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build(),
+ templateMobileWildcard)
+ assertEquals(NetworkTemplate.Builder(MATCH_WIFI).build(), templateWifiWildcard)
+ }
+
+ @Test
fun testBuilderWifiNetworkKeys() {
// Verify template builder which generates same template with the given different
// sequence keys.
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
index 47ea53e..ff9bd31 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,6 @@
data: [
":CtsHostsideNetworkTestsApp",
":CtsHostsideNetworkTestsApp2",
- ":CtsHostsideNetworkTestsAppNext",
- ],
+ ] + next_app_data,
per_testcase_directory: true,
}
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/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index d2a3f91..7985dc4 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -2388,6 +2388,7 @@
(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() {
@@ -2408,7 +2409,11 @@
}
}
- private void doTestBlockedStatusCallback() throws Exception {
+ @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
@@ -2426,7 +2431,8 @@
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 List<DetailedBlockedStatusCallback> allCallbacks =
@@ -2438,23 +2444,27 @@
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);
@@ -2463,14 +2473,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();
@@ -3372,7 +3374,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);
@@ -3385,11 +3387,17 @@
if (expectBlock) {
return;
}
- fail("Expect not to be blocked by firewall but sending packet was 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()));
}
if (expectBlock) {
- fail("Expect to be blocked by firewall but sending packet was not blocked");
+ 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()));
}
dstSock.receive(pkt);
@@ -3422,25 +3430,27 @@
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();
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index 093c7f8..77afe4f 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -20,6 +20,8 @@
import android.net.ConnectivityManager
import android.net.ConnectivityManager.NetworkCallback
import android.net.LinkProperties
+import android.net.LocalSocket
+import android.net.LocalSocketAddress
import android.net.Network
import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities
@@ -63,6 +65,8 @@
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.net.module.util.ArrayTrackRecord
import com.android.net.module.util.TrackRecord
import com.android.networkstack.apishim.NsdShimImpl
@@ -72,14 +76,17 @@
import com.android.testutils.TestableNetworkAgent
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.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
@@ -763,6 +770,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()
+ },
+ { isSocketExist ->
+ isSocketExist
+ },
+ )
+
+ // 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.UPSIDE_DOWN_CAKE)
+ 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.UPSIDE_DOWN_CAKE)
+ 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
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/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index e487295..5b98237 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -10478,7 +10478,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);
@@ -10519,7 +10523,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);
@@ -15830,7 +15838,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());
@@ -15844,7 +15856,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
@@ -15871,8 +15887,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(
@@ -15886,9 +15906,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();
@@ -15916,24 +15940,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
@@ -15953,7 +15989,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.
@@ -15977,8 +16017,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(
@@ -15997,19 +16041,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());
+ }
}
/**
diff --git a/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java b/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java
index ddf1d4d..4f0b9c4 100644
--- a/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/AutomaticOnOffKeepaliveTrackerTest.java
@@ -16,32 +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.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
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.NetworkAgent;
+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.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;
@@ -49,17 +87,22 @@
@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 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 =
@@ -158,11 +201,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);
@@ -170,11 +248,34 @@
mHandlerThread = new HandlerThread("KeepaliveTrackerTest");
mHandlerThread.start();
- doReturn(mKeepaliveTracker).when(mDependencies).newKeepaliveTracker(
- mCtx, mHandlerThread.getThreadHandler());
+ 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, mHandlerThread.getThreadHandler(), mDependencies);
+ 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 NetworkAgent.CMD_START_SOCKET_KEEPALIVE:
+ Log.d(TAG, "Test handler received CMD_START_SOCKET_KEEPALIVE : " + msg);
+ mAOOKeepaliveTracker.handleStartKeepalive(msg);
+ break;
+ case NetworkAgent.CMD_MONITOR_AUTOMATIC_KEEPALIVE:
+ Log.d(TAG, "Test handler received CMD_MONITOR_AUTOMATIC_KEEPALIVE : " + msg);
+ mLastAutoKi = mAOOKeepaliveTracker.getKeepaliveForBinder((IBinder) msg.obj);
+ break;
+ }
+ }
}
@Test
@@ -187,24 +288,79 @@
@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,
+ 10 /* interval */, KeepaliveInfo.TYPE_NATT, fd);
+ mKeepaliveTracker.setReturnedKeepaliveInfo(ki);
+
+ 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);
+ verify(mAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
+ any(), 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/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 3f87ffd..2d87728 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -27,11 +27,19 @@
import static android.net.INetd.IF_STATE_UP;
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_IP_VERSION_AUTO;
import static android.os.Build.VERSION_CODES.S_V2;
import static android.os.UserHandle.PER_USER_RANGE;
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_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
import static com.android.testutils.Cleanup.testAndCleanup;
import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import static com.android.testutils.MiscAsserts.assertThrows;
@@ -106,10 +114,13 @@
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;
@@ -252,7 +263,8 @@
"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);
-
+ // Same as IkeSessionParams#IKE_NATT_KEEPALIVE_DELAY_SEC_DEFAULT
+ private static final int IKE_NATT_KEEPALIVE_DELAY_SEC_DEFAULT = 10;
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
@Mock private UserManager mUserManager;
@Mock private PackageManager mPackageManager;
@@ -1812,6 +1824,11 @@
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 {
if (!mtuSupportsIpv6) {
doReturn(IPV6_MIN_MTU - 1).when(mTestDeps).calculateVpnMtu(any(), anyInt(), anyInt(),
anyBoolean());
@@ -1820,10 +1837,11 @@
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);
when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
- .thenReturn(mVpnProfile.encode());
+ .thenReturn(vpnProfile.encode());
vpn.startVpnProfile(TEST_VPN_PKG);
final NetworkCallback nwCb = triggerOnAvailableAndGetCallback();
@@ -1850,7 +1868,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 =
@@ -1906,6 +1924,109 @@
}
@Test
+ public void testMigrateIkeSessionFromIkeTunnConnParams_AutoTimerNoTimer()
+ throws Exception {
+ doTestMigrateIkeSession_FromIkeTunnConnParams(
+ false /* isAutomaticIpVersionSelectionEnabled */,
+ true /* isAutomaticNattKeepaliveTimerEnabled */,
+ TEST_KEEPALIVE_TIMEOUT_UNSET);
+ }
+
+ @Test
+ public void testMigrateIkeSessionFromIkeTunnConnParams_AutoTimerTimerSet()
+ throws Exception {
+ doTestMigrateIkeSession_FromIkeTunnConnParams(
+ false /* isAutomaticIpVersionSelectionEnabled */,
+ true /* isAutomaticNattKeepaliveTimerEnabled */,
+ 800 /* keepaliveTimeout */);
+ }
+
+ @Test
+ public void testMigrateIkeSessionFromIkeTunnConnParams_AutoIp()
+ throws Exception {
+ doTestMigrateIkeSession_FromIkeTunnConnParams(
+ true /* isAutomaticIpVersionSelectionEnabled */,
+ false /* isAutomaticNattKeepaliveTimerEnabled */,
+ TEST_KEEPALIVE_TIMEOUT_UNSET /* keepaliveTimeout */);
+ }
+
+ @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,
+ isAutomaticIpVersionSelectionEnabled);
+ }
+
+ private void doTestMigrateIkeSession_FromIkeTunnConnParams(
+ boolean isAutomaticIpVersionSelectionEnabled,
+ boolean isAutomaticNattKeepaliveTimerEnabled,
+ int keepaliveInProfile) throws Exception {
+ final IkeSessionParams ikeSessionParams = getTestIkeSessionParams(true /* testIpv6 */,
+ new IkeFqdnIdentification(TEST_IDENTITY), keepaliveInProfile);
+ 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();
+ doTestMigrateIkeSession(ikeProfile.toVpnProfile(), expectedKeepalive,
+ isAutomaticIpVersionSelectionEnabled);
+ }
+
+ private void doTestMigrateIkeSession(VpnProfile profile, int expectedKeepalive,
+ boolean isAutomaticIpVersionSelectionEnabled) throws Exception {
+ final int expectedIpVersion = isAutomaticIpVersionSelectionEnabled
+ ? ESP_IP_VERSION_AUTO : ESP_IP_VERSION_AUTO;
+ final int expectedEncapType = isAutomaticIpVersionSelectionEnabled
+ ? ESP_ENCAP_TYPE_AUTO : ESP_IP_VERSION_AUTO;
+
+ final PlatformVpnSnapshot vpnSnapShot =
+ verifySetupPlatformVpn(profile,
+ createIkeConfig(createIkeConnectInfo(), true /* isMobikeEnabled */),
+ false /* mtuSupportsIpv6 */);
+ // Mock new network comes up and the cleanup task is cancelled
+ vpnSnapShot.nwCb.onAvailable(TEST_NETWORK_2);
+
+ // Verify MOBIKE is triggered
+ verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2,
+ expectedIpVersion, expectedEncapType, expectedKeepalive);
+
+ vpnSnapShot.vpn.mVpnRunner.exitVpnRunner();
+ }
+
+ @Test
public void testStartPlatformVpn_mtuDoesNotSupportIpv6() throws Exception {
final PlatformVpnSnapshot vpnSnapShot =
verifySetupPlatformVpn(
@@ -1932,7 +2053,10 @@
verify(mScheduledFuture).cancel(anyBoolean());
// Verify MOBIKE is triggered
- verify(mIkeSessionWrapper).setNetwork(TEST_NETWORK_2);
+ verify(mIkeSessionWrapper).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());
@@ -2112,7 +2236,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 +2253,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 +2274,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);
diff --git a/tools/gn2bp/Android.bp.swp b/tools/gn2bp/Android.bp.swp
index 93443f5..b463052 100644
--- a/tools/gn2bp/Android.bp.swp
+++ b/tools/gn2bp/Android.bp.swp
@@ -14,6 +14,8 @@
//
// This file is automatically generated by gen_android_bp. Do not edit.
+build = ["Android.extras.bp"]
+
// GN: PACKAGE
package {
default_applicable_licenses: [
@@ -1036,6 +1038,22 @@
"-Wl,--as-needed",
"-Wl,--gc-sections",
"-Wl,--icf=all",
+ "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+ "-Wl,-wrap,asprintf",
+ "-Wl,-wrap,calloc",
+ "-Wl,-wrap,free",
+ "-Wl,-wrap,getcwd",
+ "-Wl,-wrap,malloc",
+ "-Wl,-wrap,malloc_usable_size",
+ "-Wl,-wrap,memalign",
+ "-Wl,-wrap,posix_memalign",
+ "-Wl,-wrap,pvalloc",
+ "-Wl,-wrap,realloc",
+ "-Wl,-wrap,realpath",
+ "-Wl,-wrap,strdup",
+ "-Wl,-wrap,strndup",
+ "-Wl,-wrap,valloc",
+ "-Wl,-wrap,vasprintf",
],
target: {
android_arm: {
@@ -2723,6 +2741,21 @@
"-Wl,--gc-sections",
"-Wl,--icf=all",
"-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+ "-Wl,-wrap,asprintf",
+ "-Wl,-wrap,calloc",
+ "-Wl,-wrap,free",
+ "-Wl,-wrap,getcwd",
+ "-Wl,-wrap,malloc",
+ "-Wl,-wrap,malloc_usable_size",
+ "-Wl,-wrap,memalign",
+ "-Wl,-wrap,posix_memalign",
+ "-Wl,-wrap,pvalloc",
+ "-Wl,-wrap,realloc",
+ "-Wl,-wrap,realpath",
+ "-Wl,-wrap,strdup",
+ "-Wl,-wrap,strndup",
+ "-Wl,-wrap,valloc",
+ "-Wl,-wrap,vasprintf",
],
stem: "libcronet.108.0.5359.128",
target: {
@@ -4167,6 +4200,22 @@
"-Wl,--as-needed",
"-Wl,--gc-sections",
"-Wl,--icf=all",
+ "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+ "-Wl,-wrap,asprintf",
+ "-Wl,-wrap,calloc",
+ "-Wl,-wrap,free",
+ "-Wl,-wrap,getcwd",
+ "-Wl,-wrap,malloc",
+ "-Wl,-wrap,malloc_usable_size",
+ "-Wl,-wrap,memalign",
+ "-Wl,-wrap,posix_memalign",
+ "-Wl,-wrap,pvalloc",
+ "-Wl,-wrap,realloc",
+ "-Wl,-wrap,realpath",
+ "-Wl,-wrap,strdup",
+ "-Wl,-wrap,strndup",
+ "-Wl,-wrap,valloc",
+ "-Wl,-wrap,vasprintf",
],
target: {
android_arm: {
@@ -4307,6 +4356,22 @@
"-Wl,--as-needed",
"-Wl,--gc-sections",
"-Wl,--icf=all",
+ "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+ "-Wl,-wrap,asprintf",
+ "-Wl,-wrap,calloc",
+ "-Wl,-wrap,free",
+ "-Wl,-wrap,getcwd",
+ "-Wl,-wrap,malloc",
+ "-Wl,-wrap,malloc_usable_size",
+ "-Wl,-wrap,memalign",
+ "-Wl,-wrap,posix_memalign",
+ "-Wl,-wrap,pvalloc",
+ "-Wl,-wrap,realloc",
+ "-Wl,-wrap,realpath",
+ "-Wl,-wrap,strdup",
+ "-Wl,-wrap,strndup",
+ "-Wl,-wrap,valloc",
+ "-Wl,-wrap,vasprintf",
],
target: {
android_arm: {
@@ -4341,6 +4406,7 @@
cflags: [
"-DGOOGLE_PROTOBUF_NO_RTTI",
"-Wno-ambiguous-reversed-operator",
+ "-Wno-c++11-narrowing",
"-Wno-error=return-type",
"-Wno-macro-redefined",
"-Wno-missing-field-initializers",
@@ -4632,9 +4698,6 @@
include_dirs: [
"frameworks/base/core/java/",
],
- local_include_dirs: [
- "base/android/java/src/",
- ],
},
plugins: [
"cronet_aml_java_jni_annotation_preprocessor",
@@ -5943,6 +6006,22 @@
"-Wl,--as-needed",
"-Wl,--gc-sections",
"-Wl,--icf=all",
+ "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+ "-Wl,-wrap,asprintf",
+ "-Wl,-wrap,calloc",
+ "-Wl,-wrap,free",
+ "-Wl,-wrap,getcwd",
+ "-Wl,-wrap,malloc",
+ "-Wl,-wrap,malloc_usable_size",
+ "-Wl,-wrap,memalign",
+ "-Wl,-wrap,posix_memalign",
+ "-Wl,-wrap,pvalloc",
+ "-Wl,-wrap,realloc",
+ "-Wl,-wrap,realpath",
+ "-Wl,-wrap,strdup",
+ "-Wl,-wrap,strndup",
+ "-Wl,-wrap,valloc",
+ "-Wl,-wrap,vasprintf",
],
target: {
android_arm: {
@@ -6413,6 +6492,22 @@
"-Wl,--as-needed",
"-Wl,--gc-sections",
"-Wl,--icf=all",
+ "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+ "-Wl,-wrap,asprintf",
+ "-Wl,-wrap,calloc",
+ "-Wl,-wrap,free",
+ "-Wl,-wrap,getcwd",
+ "-Wl,-wrap,malloc",
+ "-Wl,-wrap,malloc_usable_size",
+ "-Wl,-wrap,memalign",
+ "-Wl,-wrap,posix_memalign",
+ "-Wl,-wrap,pvalloc",
+ "-Wl,-wrap,realloc",
+ "-Wl,-wrap,realpath",
+ "-Wl,-wrap,strdup",
+ "-Wl,-wrap,strndup",
+ "-Wl,-wrap,valloc",
+ "-Wl,-wrap,vasprintf",
],
target: {
android_arm: {
@@ -6944,6 +7039,22 @@
"-Wl,--as-needed",
"-Wl,--gc-sections",
"-Wl,--icf=all",
+ "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+ "-Wl,-wrap,asprintf",
+ "-Wl,-wrap,calloc",
+ "-Wl,-wrap,free",
+ "-Wl,-wrap,getcwd",
+ "-Wl,-wrap,malloc",
+ "-Wl,-wrap,malloc_usable_size",
+ "-Wl,-wrap,memalign",
+ "-Wl,-wrap,posix_memalign",
+ "-Wl,-wrap,pvalloc",
+ "-Wl,-wrap,realloc",
+ "-Wl,-wrap,realpath",
+ "-Wl,-wrap,strdup",
+ "-Wl,-wrap,strndup",
+ "-Wl,-wrap,valloc",
+ "-Wl,-wrap,vasprintf",
],
target: {
android_arm: {
@@ -7127,6 +7238,22 @@
"-Wl,--as-needed",
"-Wl,--gc-sections",
"-Wl,--icf=all",
+ "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+ "-Wl,-wrap,asprintf",
+ "-Wl,-wrap,calloc",
+ "-Wl,-wrap,free",
+ "-Wl,-wrap,getcwd",
+ "-Wl,-wrap,malloc",
+ "-Wl,-wrap,malloc_usable_size",
+ "-Wl,-wrap,memalign",
+ "-Wl,-wrap,posix_memalign",
+ "-Wl,-wrap,pvalloc",
+ "-Wl,-wrap,realloc",
+ "-Wl,-wrap,realpath",
+ "-Wl,-wrap,strdup",
+ "-Wl,-wrap,strndup",
+ "-Wl,-wrap,valloc",
+ "-Wl,-wrap,vasprintf",
],
target: {
android_arm: {
@@ -12710,6 +12837,22 @@
"-Wl,--as-needed",
"-Wl,--gc-sections",
"-Wl,--icf=all",
+ "-Wl,--script,external/cronet/base/android/library_loader/anchor_functions.lds",
+ "-Wl,-wrap,asprintf",
+ "-Wl,-wrap,calloc",
+ "-Wl,-wrap,free",
+ "-Wl,-wrap,getcwd",
+ "-Wl,-wrap,malloc",
+ "-Wl,-wrap,malloc_usable_size",
+ "-Wl,-wrap,memalign",
+ "-Wl,-wrap,posix_memalign",
+ "-Wl,-wrap,pvalloc",
+ "-Wl,-wrap,realloc",
+ "-Wl,-wrap,realpath",
+ "-Wl,-wrap,strdup",
+ "-Wl,-wrap,strndup",
+ "-Wl,-wrap,valloc",
+ "-Wl,-wrap,vasprintf",
],
target: {
android_arm: {
diff --git a/tools/gn2bp/gen_android_bp b/tools/gn2bp/gen_android_bp
index 592c070..9172fb4 100755
--- a/tools/gn2bp/gen_android_bp
+++ b/tools/gn2bp/gen_android_bp
@@ -45,6 +45,8 @@
'//components/cronet/android:cronet_android_mainline',
]
+EXTRAS_ANDROID_BP_FILE = "Android.extras.bp"
+
# Defines a custom init_rc argument to be applied to the corresponding output
# blueprint target.
target_initrc = {
@@ -157,14 +159,6 @@
# 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',
@@ -938,6 +932,9 @@
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_tools(self):
+ return set()
+
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
@@ -984,6 +981,35 @@
self._set_value_arg('--output', '$(out)')
super()._sanitize_args()
+class GnRunBinary(BaseActionSanitizer):
+ def __init__(self, target, arch):
+ super().__init__(target, arch)
+ self.binary_to_target = {
+ "clang_x64/transport_security_state_generator":
+ "cronet_aml_net_tools_transport_security_state_generator_transport_security_state_generator__testing",
+ }
+ self.binary = self.binary_to_target[self.target.args[0]]
+
+ def _replace_gen_with_location_tag(self, arg):
+ if arg.startswith("gen/"):
+ return "$(location %s)" % arg.replace("gen/", "")
+ return arg
+
+ def _sanitize_args(self):
+ self._update_all_args(self._sanitize_filepath_with_location_tag)
+ self._update_all_args(self._replace_gen_with_location_tag)
+ self._set_arg_at(0, '$(location %s)' % self.binary)
+ super()._sanitize_args()
+
+ def get_tools(self):
+ tools = super().get_tools()
+ tools.add(self.binary)
+ return tools
+
+ def get_cmd(self):
+ # Remove the script and use the binary right away
+ return NEWLINE.join(self.target.args)
+
class JniGeneratorSanitizer(BaseActionSanitizer):
def _add_location_tag_to_filepath(self, arg):
if not arg.endswith('.class'):
@@ -1132,6 +1158,8 @@
return JavaCppStringSanitizer(target, arch)
elif target.script == '//build/android/gyp/write_native_libraries_java.py':
return WriteNativeLibrariesJavaSanitizer(target, arch)
+ elif target.script == '//build/gn_run_binary.py':
+ return GnRunBinary(target, arch)
else:
# TODO: throw exception here once all script hacks have been converted.
return BaseActionSanitizer(target, arch)
@@ -1180,6 +1208,7 @@
module.genrule_headers.add(module.name)
module.srcs = sanitizer.get_srcs()
module.tool_files = sanitizer.get_tool_files()
+ module.tools = sanitizer.get_tools()
return module
@@ -1268,10 +1297,17 @@
cflags |= set("-D%s" % define.replace("\"", "\\\"") for define in defines)
return cflags
-def set_module_flags(module, module_type, cflags, defines, ldflags):
+def _set_linker_script(module, libs):
+ for lib in libs:
+ if lib.endswith(".lds"):
+ module.ldflags.add(get_linker_script_ldflag(gn_utils.label_to_path(lib)))
+
+def set_module_flags(module, module_type, cflags, defines, ldflags, libs):
module.cflags.update(_get_cflags(cflags, defines))
if module_type != 'cc_object':
- module.ldflags.update({flag for flag in ldflags if flag in ldflag_allowlist})
+ module.ldflags.update({flag for flag in ldflags
+ if flag in ldflag_allowlist or flag.startswith("-Wl,-wrap,")})
+ _set_linker_script(module, libs)
# TODO: implement proper cflag parsing.
for flag in cflags:
if '-std=' in flag:
@@ -1363,12 +1399,13 @@
module.rtti = target.rtti
if target.type in gn_utils.LINKER_UNIT_TYPES:
- set_module_flags(module, module.type, target.cflags, target.defines, target.ldflags)
+ set_module_flags(module, module.type, target.cflags, target.defines, target.ldflags, target.libs)
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():
+ # TODO(aymanm): Make libs arch-specific.
set_module_flags(module.target[arch_name], module.type,
- arch.cflags, arch.defines, arch.ldflags)
+ arch.cflags, arch.defines, arch.ldflags, [])
# -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
@@ -1482,14 +1519,13 @@
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)
+ 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
@@ -1569,7 +1605,7 @@
"modules-utils-build_system",
}
module.aidl["include_dirs"] = {"frameworks/base/core/java/"}
- module.aidl["local_include_dirs"] = {"base/android/java/src/"}
+ module.aidl["local_include_dirs"] = gn.aidl_local_include_dirs
module.sdk_version = "module_current"
module.min_sdk_version = 30
module.apex_available.add(tethering_apex)
@@ -1639,6 +1675,7 @@
'-Wno-ambiguous-reversed-operator', # needed for icui18n
'-Wno-unreachable-code-loop-increment', # needed for icui18n
'-fPIC',
+ '-Wno-c++11-narrowing',
]
# Chromium builds do not add a dependency for headers found inside the
# sysroot, so they are added globally via defaults.
@@ -1808,6 +1845,8 @@
// limitations under the License.
//
// This file is automatically generated by %s. Do not edit.
+
+build = ["Android.extras.bp"]
""" % (tool_name)
]
blueprint.to_string(output)
diff --git a/tools/gn2bp/gn_utils.py b/tools/gn2bp/gn_utils.py
index 6095455..e5e714e 100644
--- a/tools/gn2bp/gn_utils.py
+++ b/tools/gn2bp/gn_utils.py
@@ -46,6 +46,7 @@
}
ARCH_REGEX = r'(android_x86_64|android_x86|android_arm|android_arm64|host)'
RESPONSE_FILE = '{{response_file_name}}'
+AIDL_INCLUDE_DIRS_REGEX = r'--includes=\[(.*)\]'
def repo_root():
"""Returns an absolute path to the repository root."""
@@ -53,6 +54,18 @@
os.path.realpath(os.path.dirname(__file__)), os.path.pardir)
+def _clean_string(str):
+ return str.replace('\\', '').replace('../../', '').replace('"', '').strip()
+
+
+def _extract_includes_from_aidl_args(args):
+ for arg in args:
+ is_match = re.match(AIDL_INCLUDE_DIRS_REGEX, arg)
+ if is_match:
+ local_includes = is_match.group(1).split(",")
+ return [_clean_string(local_include) for local_include in local_includes]
+ return []
+
def label_to_path(label):
"""Turn a GN output label (e.g., //some_dir/file.cc) into a path."""
assert label.startswith('//')
@@ -263,6 +276,7 @@
self.actions = {}
self.proto_libs = {}
self.java_sources = collections.defaultdict(set)
+ self.aidl_local_include_dirs = set()
self.java_actions = collections.defaultdict(set)
def _get_response_file_contents(self, action_desc):
@@ -454,11 +468,12 @@
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.
+ # GN uses an action to compile aidl files. However, this is not needed in soong
+ # as 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':
+ if '_aidl' in dep.name:
self.java_sources[java_group_name].update(dep.arch[arch].sources)
+ self.aidl_local_include_dirs.update(_extract_includes_from_aidl_args(dep.arch[arch].args))
else:
self.java_actions[java_group_name].add(dep.name)
return target