Merge "Add version control for packet address translation design" into main
diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java
index 8719960..4f816c5 100644
--- a/framework-t/src/android/net/NetworkStats.java
+++ b/framework-t/src/android/net/NetworkStats.java
@@ -46,6 +46,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.function.Function;
import java.util.function.Predicate;
/**
@@ -455,6 +456,41 @@
return operations;
}
+ /**
+ * Set Key fields for this entry.
+ *
+ * @return this object.
+ * @hide
+ */
+ private Entry setKeys(@Nullable String iface, int uid, @State int set,
+ int tag, @Meteredness int metered, @Roaming int roaming,
+ @DefaultNetwork int defaultNetwork) {
+ this.iface = iface;
+ this.uid = uid;
+ this.set = set;
+ this.tag = tag;
+ this.metered = metered;
+ this.roaming = roaming;
+ this.defaultNetwork = defaultNetwork;
+ return this;
+ }
+
+ /**
+ * Set Value fields for this entry.
+ *
+ * @return this object.
+ * @hide
+ */
+ private Entry setValues(long rxBytes, long rxPackets, long txBytes, long txPackets,
+ long operations) {
+ this.rxBytes = rxBytes;
+ this.rxPackets = rxPackets;
+ this.txBytes = txBytes;
+ this.txPackets = txPackets;
+ this.operations = operations;
+ return this;
+ }
+
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
@@ -1111,7 +1147,8 @@
entry.txPackets = left.txPackets[i];
entry.operations = left.operations[i];
- // find remote row that matches, and subtract
+ // Find the remote row that matches and subtract.
+ // The returned row must be uniquely matched.
final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
entry.metered, entry.roaming, entry.defaultNetwork, i);
if (j != -1) {
@@ -1210,30 +1247,21 @@
* @hide
*/
public NetworkStats groupedByIface() {
- final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
+ // Keep backward compatibility where the method filtered out tagged stats and keep the
+ // operation counts as 0. The method used to deal with uid snapshot where tagged and
+ // non-tagged stats were mixed. And this method was also in Android O API list,
+ // so it is possible OEM can access it.
+ final NetworkStats copiedStats = this.clone();
+ copiedStats.filter(e -> e.getTag() == TAG_NONE);
- final Entry entry = new Entry();
- entry.uid = UID_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
- entry.metered = METERED_ALL;
- entry.roaming = ROAMING_ALL;
- entry.defaultNetwork = DEFAULT_NETWORK_ALL;
- entry.operations = 0L;
+ final Entry temp = new Entry();
+ final NetworkStats mappedStats = copiedStats.map(entry -> temp.setKeys(entry.getIface(),
+ UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL));
- for (int i = 0; i < size; i++) {
- // skip specific tags, since already counted in TAG_NONE
- if (tag[i] != TAG_NONE) continue;
-
- entry.iface = iface[i];
- entry.rxBytes = rxBytes[i];
- entry.rxPackets = rxPackets[i];
- entry.txBytes = txBytes[i];
- entry.txPackets = txPackets[i];
- stats.combineValues(entry);
+ for (int i = 0; i < mappedStats.size; i++) {
+ mappedStats.operations[i] = 0L;
}
-
- return stats;
+ return mappedStats;
}
/**
@@ -1242,30 +1270,15 @@
* @hide
*/
public NetworkStats groupedByUid() {
- final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
+ // Keep backward compatibility where the method filtered out tagged stats. The method used
+ // to deal with uid snapshot where tagged and non-tagged stats were mixed. And
+ // this method is also in Android O API list, so it is possible OEM can access it.
+ final NetworkStats copiedStats = this.clone();
+ copiedStats.filter(e -> e.getTag() == TAG_NONE);
- final Entry entry = new Entry();
- entry.iface = IFACE_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
- entry.metered = METERED_ALL;
- entry.roaming = ROAMING_ALL;
- entry.defaultNetwork = DEFAULT_NETWORK_ALL;
-
- for (int i = 0; i < size; i++) {
- // skip specific tags, since already counted in TAG_NONE
- if (tag[i] != TAG_NONE) continue;
-
- entry.uid = uid[i];
- entry.rxBytes = rxBytes[i];
- entry.rxPackets = rxPackets[i];
- entry.txBytes = txBytes[i];
- entry.txPackets = txPackets[i];
- entry.operations = operations[i];
- stats.combineValues(entry);
- }
-
- return stats;
+ final Entry temp = new Entry();
+ return copiedStats.map(entry -> temp.setKeys(IFACE_ALL,
+ entry.getUid(), SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL));
}
/**
@@ -1292,13 +1305,37 @@
/**
* Removes the interface name from all entries.
- * This mutates the original structure in place.
+ * This returns a newly constructed object instead of mutating the original structure.
* @hide
*/
- public void clearInterfaces() {
- for (int i = 0; i < size; i++) {
- iface[i] = null;
+ @NonNull
+ public NetworkStats clearInterfaces() {
+ final Entry temp = new Entry();
+ return map(entry -> temp.setKeys(IFACE_ALL, entry.getUid(), entry.getSet(),
+ entry.getTag(), entry.getMetered(), entry.getRoaming(), entry.getDefaultNetwork()));
+ }
+
+ /**
+ * Returns a new NetworkStats object where entries are transformed.
+ *
+ * Note that because NetworkStats is more akin to a map than to a list,
+ * the entries will be grouped after they are mapped by the key fields,
+ * e.g. uid, set, tag, defaultNetwork.
+ * Value fields with the same keys will be added together.
+ */
+ @NonNull
+ private NetworkStats map(@NonNull Function<Entry, Entry> f) {
+ final NetworkStats ret = new NetworkStats(0, 1);
+ for (Entry e : this) {
+ final NetworkStats.Entry transformed = f.apply(e);
+ if (transformed == e) {
+ throw new IllegalStateException("A new entry must be created.");
+ }
+ transformed.setValues(e.getRxBytes(), e.getRxPackets(), e.getTxBytes(),
+ e.getTxPackets(), e.getOperations());
+ ret.combineValues(transformed);
}
+ return ret;
}
/**
diff --git a/framework/Android.bp b/framework/Android.bp
index cab11ae..7897492 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -62,6 +62,7 @@
":framework-connectivity-sources",
":net-utils-framework-common-srcs",
":framework-connectivity-api-shared-srcs",
+ ":framework-remoteauth-java-sources",
],
aidl: {
generate_get_transaction_name: true,
@@ -150,6 +151,7 @@
"//packages/modules/Connectivity/framework-t",
"//packages/modules/Connectivity/service",
"//packages/modules/Connectivity/service-t",
+ "//packages/modules/Connectivity/remoteauth:__subpackages__",
"//frameworks/base/packages/Connectivity/service",
"//frameworks/base",
diff --git a/nearby/service/Android.bp b/nearby/service/Android.bp
index ef07bb9..684b133 100644
--- a/nearby/service/Android.bp
+++ b/nearby/service/Android.bp
@@ -104,7 +104,7 @@
],
sdk_version: "system_server_current",
// This is included in service-connectivity which is 30+
- // TODO: allow APEXes to have service jars with higher min_sdk than the APEX
+ // TODO (b/293613362): allow APEXes to have service jars with higher min_sdk than the APEX
// (service-connectivity is only used on 31+) and use 31 here
min_sdk_version: "30",
diff --git a/remote_auth/OWNERS b/remoteauth/OWNERS
similarity index 100%
rename from remote_auth/OWNERS
rename to remoteauth/OWNERS
diff --git a/remote_auth/README.md b/remoteauth/README.md
similarity index 100%
rename from remote_auth/README.md
rename to remoteauth/README.md
diff --git a/remoteauth/TEST_MAPPING b/remoteauth/TEST_MAPPING
new file mode 100644
index 0000000..5ad8da6
--- /dev/null
+++ b/remoteauth/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+ "presubmit": [
+ {
+ "name": "RemoteAuthUnitTests"
+ }
+ ]
+ // TODO(b/193602229): uncomment once it's supported.
+ //"mainline-presubmit": [
+ // {
+ // "name": "RemoteAuthUnitTests[com.google.android.tethering.apex]"
+ // }
+ //]
+}
diff --git a/remoteauth/framework/Android.bp b/remoteauth/framework/Android.bp
new file mode 100644
index 0000000..48d10b6
--- /dev/null
+++ b/remoteauth/framework/Android.bp
@@ -0,0 +1,49 @@
+// 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"],
+}
+
+// Sources included in the framework-connectivity jar
+filegroup {
+ name: "framework-remoteauth-java-sources",
+ srcs: [
+ "java/**/*.java",
+ "java/**/*.aidl",
+ ],
+ path: "java",
+ visibility: [
+ "//packages/modules/Connectivity/framework:__subpackages__",
+ ],
+}
+
+filegroup {
+ name: "framework-remoteauth-sources",
+ defaults: ["framework-sources-module-defaults"],
+ srcs: [
+ ":framework-remoteauth-java-sources",
+ ],
+}
+
+// Build of only framework-remoteauth (not as part of connectivity) for
+// unit tests
+java_library {
+ name: "framework-remoteauth-static",
+ srcs: [":framework-remoteauth-java-sources"],
+ sdk_version: "module_current",
+ libs: [],
+ static_libs: [],
+ visibility: ["//packages/modules/Connectivity/remoteauth/tests:__subpackages__"],
+}
diff --git a/remoteauth/framework/java/android/remoteauth/README.md b/remoteauth/framework/java/android/remoteauth/README.md
new file mode 100644
index 0000000..13fefee
--- /dev/null
+++ b/remoteauth/framework/java/android/remoteauth/README.md
@@ -0,0 +1 @@
+This is the source root for the RemoteAuth framework
\ No newline at end of file
diff --git a/remoteauth/framework/java/android/remoteauth/aidl/README.md b/remoteauth/framework/java/android/remoteauth/aidl/README.md
new file mode 100644
index 0000000..1e9422e
--- /dev/null
+++ b/remoteauth/framework/java/android/remoteauth/aidl/README.md
@@ -0,0 +1 @@
+This is where the RemoteAuth AIDL files will go
\ No newline at end of file
diff --git a/remoteauth/service/Android.bp b/remoteauth/service/Android.bp
new file mode 100644
index 0000000..5c5a2fb
--- /dev/null
+++ b/remoteauth/service/Android.bp
@@ -0,0 +1,59 @@
+// 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"],
+}
+
+filegroup {
+ name: "remoteauth-service-srcs",
+ srcs: ["java/**/*.java"],
+}
+
+// Main lib for remoteauth services.
+java_library {
+ name: "service-remoteauth-pre-jarjar",
+ srcs: [":remoteauth-service-srcs"],
+
+ defaults: [
+ "framework-system-server-module-defaults"
+ ],
+ libs: [],
+ static_libs: [],
+ sdk_version: "system_server_current",
+ // This is included in service-connectivity which is 30+
+ // TODO (b/293613362): allow APEXes to have service jars with higher min_sdk than the APEX
+ // (service-connectivity is only used on 31+) and use 31 here
+ min_sdk_version: "30",
+
+ dex_preopt: {
+ enabled: false,
+ app_image: false,
+ },
+ visibility: [
+ "//packages/modules/RemoteAuth/apex",
+ ],
+ apex_available: [
+ "com.android.tethering",
+ ],
+}
+
+genrule {
+ name: "statslog-remoteauth-java-gen",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --java $(out) --module remoteauth " +
+ " --javaPackage com.android.server.remoteauth.proto --javaClass RemoteAuthStatsLog" +
+ " --minApiLevel 33",
+ out: ["com/android/server/remoteauth/proto/RemoteAuthStatsLog.java"],
+}
diff --git a/remoteauth/service/java/com/android/server/remoteauth/README.md b/remoteauth/service/java/com/android/server/remoteauth/README.md
new file mode 100644
index 0000000..423ab45
--- /dev/null
+++ b/remoteauth/service/java/com/android/server/remoteauth/README.md
@@ -0,0 +1 @@
+This is the source root for the RemoteAuthService
\ No newline at end of file
diff --git a/remoteauth/tests/unit/Android.bp b/remoteauth/tests/unit/Android.bp
new file mode 100644
index 0000000..8c08a1b
--- /dev/null
+++ b/remoteauth/tests/unit/Android.bp
@@ -0,0 +1,48 @@
+// 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"],
+}
+
+android_test {
+ name: "RemoteAuthUnitTests",
+ defaults: ["mts-target-sdk-version-current"],
+ sdk_version: "test_current",
+ min_sdk_version: "31",
+
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+
+ libs: [
+ "android.test.base",
+ "android.test.mock",
+ "android.test.runner",
+ ],
+ compile_multilib: "both",
+
+ static_libs: [
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "framework-remoteauth-static",
+ "junit",
+ "platform-test-annotations",
+ "service-remoteauth-pre-jarjar",
+ "truth-prebuilt",
+ ],
+ test_suites: [
+ "general-tests",
+ "mts-tethering",
+ ],
+}
diff --git a/remoteauth/tests/unit/AndroidManifest.xml b/remoteauth/tests/unit/AndroidManifest.xml
new file mode 100644
index 0000000..0449409
--- /dev/null
+++ b/remoteauth/tests/unit/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?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.remoteauth.test">
+
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.BLUETOOTH" />
+ <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
+ <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
+
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.remoteauth.test"
+ android:label="RemoteAuth Mainline Module Tests" />
+</manifest>
diff --git a/remoteauth/tests/unit/AndroidTest.xml b/remoteauth/tests/unit/AndroidTest.xml
new file mode 100644
index 0000000..325fdc6
--- /dev/null
+++ b/remoteauth/tests/unit/AndroidTest.xml
@@ -0,0 +1,40 @@
+<?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 RemoteAuth Mainline API Tests.">
+ <!-- Only run tests if the device under test is SDK version 33 (Android 13) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk33ModuleController" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="RemoteAuthUnitTests.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-tag" value="RemoteAuthUnitTests" />
+ <option name="config-descriptor:metadata" key="mainline-param"
+ value="com.google.android.tethering.apex" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.remoteauth.test" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+
+ <!-- Only run RemoteAuthUnitTests in MTS if the RemoteAuth 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>
diff --git a/remoteauth/tests/unit/src/android/remoteauth/RemoteAuthManagerTest.java b/remoteauth/tests/unit/src/android/remoteauth/RemoteAuthManagerTest.java
new file mode 100644
index 0000000..5cf3e6b
--- /dev/null
+++ b/remoteauth/tests/unit/src/android/remoteauth/RemoteAuthManagerTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.remoteauth;
+
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit tests for {@link RemoteAuth}. */
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RemoteAuthManagerTest {
+ @Test
+ public void testStub() {
+ assertTrue(true);
+ }
+}
diff --git a/remoteauth/tests/unit/src/com/android/server/remoteauth/RemoteAuthServiceTest.java b/remoteauth/tests/unit/src/com/android/server/remoteauth/RemoteAuthServiceTest.java
new file mode 100644
index 0000000..c6199ff
--- /dev/null
+++ b/remoteauth/tests/unit/src/com/android/server/remoteauth/RemoteAuthServiceTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.remoteauth;
+
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit tests for {@link RemoteAuthServer}. */
+@RunWith(AndroidJUnit4.class)
+public class RemoteAuthServiceTest {
+ @Test
+ public void testStub() {
+ assertTrue(true);
+ }
+}
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index e7ef510..6635fd3 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -1744,8 +1744,7 @@
// 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
// recorder.
- stats.clearInterfaces();
- return stats;
+ return stats.clearInterfaces();
} catch (RemoteException e) {
Log.wtf(TAG, "Error compiling UID stats", e);
return new NetworkStats(0L, 0);
diff --git a/service/Android.bp b/service/Android.bp
index e1376a1..a65d664 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -236,6 +236,7 @@
"service-connectivity-pre-jarjar",
"service-connectivity-tiramisu-pre-jarjar",
"service-nearby-pre-jarjar",
+ "service-remoteauth-pre-jarjar",
],
// The below libraries are not actually needed to build since no source is compiled
// (only combining prebuilt static_libs), but they are necessary so that R8 has the right
@@ -303,6 +304,7 @@
":framework-connectivity-jarjar-rules",
":service-connectivity-jarjar-gen",
":service-nearby-jarjar-gen",
+ ":service-remoteauth-jarjar-gen",
],
out: ["connectivity-jarjar-rules.txt"],
visibility: ["//packages/modules/Connectivity:__subpackages__"],
@@ -354,6 +356,24 @@
visibility: ["//visibility:private"],
}
+java_genrule {
+ name: "service-remoteauth-jarjar-gen",
+ tool_files: [
+ ":service-remoteauth-pre-jarjar{.jar}",
+ "jarjar-excludes.txt",
+ ],
+ tools: [
+ "jarjar-rules-generator",
+ ],
+ out: ["service_remoteauth_jarjar_rules.txt"],
+ cmd: "$(location jarjar-rules-generator) " +
+ "$(location :service-remoteauth-pre-jarjar{.jar}) " +
+ "--prefix com.android.server.remoteauth " +
+ "--excludes $(location jarjar-excludes.txt) " +
+ "--output $(out)",
+ visibility: ["//visibility:private"],
+}
+
genrule {
name: "statslog-connectivity-java-gen",
tools: ["stats-log-api-gen"],
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 83afa83..bc703a9 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -1704,8 +1704,7 @@
mUserAllContext.registerReceiver(mPackageIntentReceiver, packageIntentFilter,
null /* broadcastPermission */, mHandler);
- mNetworkActivityTracker =
- new LegacyNetworkActivityTracker(mContext, mNetd, mHandler, mDeps.isAtLeastU());
+ mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mNetd, mHandler);
final NetdCallback netdCallback = new NetdCallback();
try {
@@ -11139,9 +11138,10 @@
new RemoteCallbackList<>();
// Indicate the current system default network activity is active or not.
// This needs to be volatile to allow non handler threads to read this value without lock.
- private volatile boolean mIsDefaultNetworkActive;
+ // If there is no default network, default network is considered active to keep the existing
+ // behavior. Initial value is used until first connect to the default network.
+ private volatile boolean mIsDefaultNetworkActive = true;
private final ArrayMap<String, IdleTimerParams> mActiveIdleTimers = new ArrayMap<>();
- private final boolean mIsAtLeastU;
private static class IdleTimerParams {
public final int timeout;
@@ -11154,11 +11154,10 @@
}
LegacyNetworkActivityTracker(@NonNull Context context, @NonNull INetd netd,
- @NonNull Handler handler, boolean isAtLeastU) {
+ @NonNull Handler handler) {
mContext = context;
mNetd = netd;
mHandler = handler;
- mIsAtLeastU = isAtLeastU;
}
private void ensureRunningOnConnectivityServiceThread() {
@@ -11319,13 +11318,14 @@
boolean hasIdleTimer) {
if (defaultNetwork != null) {
mIsDefaultNetworkActive = true;
- // On T-, callbacks are called only when the network has the idle timer.
- if (mIsAtLeastU || hasIdleTimer) {
+ // Callbacks are called only when the network has the idle timer.
+ if (hasIdleTimer) {
reportNetworkActive();
}
} else {
- // If there is no default network, default network is considered inactive.
- mIsDefaultNetworkActive = false;
+ // If there is no default network, default network is considered active to keep the
+ // existing behavior.
+ mIsDefaultNetworkActive = true;
}
}
diff --git a/tests/benchmark/src/android/net/netstats/benchmarktests/NetworkStatsTest.kt b/tests/benchmark/src/android/net/netstats/benchmarktests/NetworkStatsTest.kt
index 8492268..e80548b 100644
--- a/tests/benchmark/src/android/net/netstats/benchmarktests/NetworkStatsTest.kt
+++ b/tests/benchmark/src/android/net/netstats/benchmarktests/NetworkStatsTest.kt
@@ -28,7 +28,6 @@
import java.io.BufferedInputStream
import java.io.DataInputStream
import java.io.File
-import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.file.Files
import java.util.concurrent.TimeUnit
@@ -44,6 +43,8 @@
class NetworkStatsTest {
companion object {
private val DEFAULT_BUFFER_SIZE = 8192
+ private val FILE_CACHE_WARM_UP_REPEAT_COUNT = 10
+ private val TEST_REPEAT_COUNT = 10
private val UID_COLLECTION_BUCKET_DURATION_MS = TimeUnit.HOURS.toMillis(2)
private val UID_RECORDER_ROTATE_AGE_MS = TimeUnit.DAYS.toMillis(15)
private val UID_RECORDER_DELETE_AGE_MS = TimeUnit.DAYS.toMillis(90)
@@ -63,14 +64,14 @@
}
// Test results shows the test cases who read the file first will take longer time to
- // execute, and reading time getting shorter each time. Read files several times prior to
- // tests to minimize the impact. This cannot live in setUp() since the time
- // spent on the file reading will be attributed to the time spent on the individual
- // test case.
+ // execute, and reading time getting shorter each time due to file caching mechanism.
+ // Read files several times prior to tests to minimize the impact.
+ // This cannot live in setUp() since the time spent on the file reading will be
+ // attributed to the time spent on the individual test case.
@JvmStatic
@BeforeClass
fun setUpOnce() {
- for (i in 1..10) {
+ repeat(FILE_CACHE_WARM_UP_REPEAT_COUNT) {
val collection = NetworkStatsCollection(UID_COLLECTION_BUCKET_DURATION_MS)
for (file in uidTestFiles) {
readFile(file, collection)
@@ -78,20 +79,19 @@
}
}
- private fun getInputStreamForResource(resourceId: Int): DataInputStream {
- return DataInputStream(
+ private fun getInputStreamForResource(resourceId: Int): DataInputStream =
+ DataInputStream(
InstrumentationRegistry.getContext()
.getResources().openRawResource(resourceId)
)
- }
private fun unzipToTempDir(zis: ZipInputStream): File {
val statsDir =
Files.createTempDirectory(NetworkStatsTest::class.simpleName).toFile()
- while (true) {
- val entryName = zis.nextEntry?.name ?: break
- val file = File(statsDir, entryName)
- FileOutputStream(file).use { zis.copyTo(it, DEFAULT_BUFFER_SIZE) }
+ generateSequence { zis.nextEntry }.forEach { entry ->
+ FileOutputStream(File(statsDir, entry.name)).use {
+ zis.copyTo(it, DEFAULT_BUFFER_SIZE)
+ }
}
return statsDir
}
@@ -99,20 +99,23 @@
// List [xt|uid|uid_tag].<start>-<end> files under the given directory.
private fun getSortedListForPrefix(statsDir: File, prefix: String): List<File> {
assertTrue(statsDir.exists())
- return (statsDir.list() ?: arrayOf()).mapNotNull {
- if (it.startsWith("$prefix.")) File(statsDir, it) else null
- }.sorted()
+ return statsDir.list() { dir, name -> name.startsWith("$prefix.") }
+ .orEmpty()
+ .map { it -> File(statsDir, it) }
+ .sorted()
}
private fun readFile(file: File, reader: Reader) =
- BufferedInputStream(FileInputStream(file)).use {
+ BufferedInputStream(file.inputStream()).use {
reader.read(it)
}
}
@Test
fun testReadCollection_manyUids() {
- for (i in 1..10) {
+ // The file cache is warmed up by the @BeforeClass method, so now the test can repeat
+ // this a number of time to have a stable number.
+ repeat(TEST_REPEAT_COUNT) {
val collection = NetworkStatsCollection(UID_COLLECTION_BUCKET_DURATION_MS)
for (file in uidTestFiles) {
readFile(file, collection)
@@ -122,13 +125,15 @@
@Test
fun testReadFromRecorder_manyUids() {
- for (i in 1..10) {
+ val mockObserver = mock<NonMonotonicObserver<String>>()
+ val mockDropBox = mock<DropBoxManager>()
+ repeat(TEST_REPEAT_COUNT) {
val recorder = NetworkStatsRecorder(
FileRotator(
testFilesDir, PREFIX_UID, UID_RECORDER_ROTATE_AGE_MS, UID_RECORDER_DELETE_AGE_MS
),
- mock<NonMonotonicObserver<String>>(),
- mock(DropBoxManager::class.java),
+ mockObserver,
+ mockDropBox,
PREFIX_UID,
UID_COLLECTION_BUCKET_DURATION_MS,
false /* includeTags */,
@@ -138,5 +143,5 @@
}
}
- inline fun <reified T : Any> mock(): T = mock(T::class.java)
+ inline fun <reified T> mock(): T = mock(T::class.java)
}
diff --git a/tests/unit/java/android/net/NetworkStatsTest.java b/tests/unit/java/android/net/NetworkStatsTest.java
index 126ad55..4ff131b 100644
--- a/tests/unit/java/android/net/NetworkStatsTest.java
+++ b/tests/unit/java/android/net/NetworkStatsTest.java
@@ -1073,30 +1073,35 @@
final NetworkStats.Entry entry1 = new NetworkStats.Entry(
"test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L);
-
final NetworkStats.Entry entry2 = new NetworkStats.Entry(
"test2", 10101, SET_DEFAULT, 0xF0DD, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 51200, 25L, 101010L, 50L, 0L);
+ final NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ "test3", 10101, SET_DEFAULT, 0xF0DD, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 1, 2L, 3L, 4L, 5L);
stats.insertEntry(entry1);
stats.insertEntry(entry2);
+ stats.insertEntry(entry3);
// Verify that the interfaces have indeed been recorded.
- assertEquals(2, stats.size());
+ assertEquals(3, stats.size());
assertValues(stats, 0, "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L);
assertValues(stats, 1, "test2", 10101, SET_DEFAULT, 0xF0DD, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, 51200, 25L, 101010L, 50L, 0L);
+ assertValues(stats, 2, "test3", 10101, SET_DEFAULT, 0xF0DD, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 1, 2L, 3L, 4L, 5L);
// Clear interfaces.
- stats.clearInterfaces();
+ final NetworkStats ifaceClearedStats = stats.clearInterfaces();
- // Verify that the interfaces are cleared.
- assertEquals(2, stats.size());
- assertValues(stats, 0, null /* iface */, 10100, SET_DEFAULT, TAG_NONE, METERED_NO,
- ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L);
- assertValues(stats, 1, null /* iface */, 10101, SET_DEFAULT, 0xF0DD, METERED_NO,
- ROAMING_NO, DEFAULT_NETWORK_NO, 51200, 25L, 101010L, 50L, 0L);
+ // Verify that the interfaces are cleared, and key-duplicated items are merged.
+ assertEquals(2, ifaceClearedStats.size());
+ assertValues(ifaceClearedStats, 0, null /* iface */, 10100, SET_DEFAULT, TAG_NONE,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L);
+ assertValues(ifaceClearedStats, 1, null /* iface */, 10101, SET_DEFAULT, 0xF0DD,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 51201, 27L, 101013L, 54L, 5L);
}
private static void assertContains(NetworkStats stats, String iface, int uid, int set,
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 931670a..4dadfee 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -11335,17 +11335,18 @@
}
@Test
- public void testOnNetworkActive_NewEthernetConnects_Callback() throws Exception {
- // On T-, LegacyNetworkActivityTracker calls onNetworkActive callback only for networks that
+ public void testOnNetworkActive_NewEthernetConnects_CallbackNotCalled() throws Exception {
+ // LegacyNetworkActivityTracker calls onNetworkActive callback only for networks that
// tracker adds the idle timer to. And the tracker does not set the idle timer for the
// ethernet network.
// So onNetworkActive is not called when the ethernet becomes the default network
- doTestOnNetworkActive_NewNetworkConnects(TRANSPORT_ETHERNET, mDeps.isAtLeastU());
+ doTestOnNetworkActive_NewNetworkConnects(TRANSPORT_ETHERNET, false /* expectCallback */);
}
@Test
public void testIsDefaultNetworkActiveNoDefaultNetwork() throws Exception {
- assertFalse(mCm.isDefaultNetworkActive());
+ // isDefaultNetworkActive returns true if there is no default network, which is known issue.
+ assertTrue(mCm.isDefaultNetworkActive());
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -11357,7 +11358,7 @@
mCellAgent.disconnect();
waitForIdle();
- assertFalse(mCm.isDefaultNetworkActive());
+ assertTrue(mCm.isDefaultNetworkActive());
}
@Test
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 2726267..ad178c0 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -1346,7 +1346,8 @@
final ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
final int verifyTimes = profileState.length;
- verify(userContext, times(verifyTimes)).startService(intentArgumentCaptor.capture());
+ verify(userContext, timeout(TEST_TIMEOUT_MS).times(verifyTimes))
+ .startService(intentArgumentCaptor.capture());
for (int i = 0; i < verifyTimes; i++) {
final Intent intent = intentArgumentCaptor.getAllValues().get(i);
@@ -1658,7 +1659,7 @@
verify(mExecutor, atLeastOnce()).schedule(any(Runnable.class), anyLong(), any());
} else {
final IkeSessionCallback ikeCb = captor.getValue();
- ikeCb.onClosedWithException(exception);
+ mExecutor.execute(() -> ikeCb.onClosedWithException(exception));
}
verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG);
@@ -1677,7 +1678,7 @@
int retryIndex = 0;
final IkeSessionCallback ikeCb2 = verifyRetryAndGetNewIkeCb(retryIndex++);
- ikeCb2.onClosedWithException(exception);
+ mExecutor.execute(() -> ikeCb2.onClosedWithException(exception));
verifyRetryAndGetNewIkeCb(retryIndex++);
}
}
@@ -1688,11 +1689,8 @@
// Verify retry is scheduled
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));
+ verify(mExecutor, timeout(TEST_TIMEOUT_MS)).schedule(any(Runnable.class),
+ eq(expectedDelayMs), eq(TimeUnit.MILLISECONDS));
verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS + expectedDelayMs))
.createIkeSession(any(), any(), any(), any(), ikeCbCaptor.capture(), any());
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsBaseTest.java b/tests/unit/java/com/android/server/net/NetworkStatsBaseTest.java
index a058a46..2c9f212 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsBaseTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsBaseTest.java
@@ -41,6 +41,7 @@
abstract class NetworkStatsBaseTest {
static final String TEST_IFACE = "test0";
static final String TEST_IFACE2 = "test1";
+ static final String TEST_IFACE3 = "test2";
static final String TUN_IFACE = "test_nss_tun0";
static final String TUN_IFACE2 = "test_nss_tun1";
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index b8b0289..6292d45 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -1250,8 +1250,9 @@
TEST_IFACE2, IMSI_1, null /* wifiNetworkKey */,
false /* isTemporarilyNotMetered */, false /* isRoaming */);
- final NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {
- mobileState, buildWifiState()};
+ final NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{
+ mobileState, buildWifiState(false, TEST_IFACE, null),
+ buildWifiState(false, TEST_IFACE3, null)};
mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]);
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_LTE);
@@ -1266,16 +1267,22 @@
final NetworkStats.Entry entry3 = new NetworkStats.Entry(
TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xBEEF, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 8L, 512L, 4L, 2L);
+ // Add an entry that with different wifi interface, but expected to be merged into entry3
+ // after clearing interface information.
+ final NetworkStats.Entry entry4 = new NetworkStats.Entry(
+ TEST_IFACE3, UID_BLUE, SET_DEFAULT, 0xBEEF, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 1L, 2L, 3L, 4L, 5L);
final TetherStatsParcel[] emptyTetherStats = {};
// The interfaces that expect to be used to query the stats.
- final String[] wifiIfaces = {TEST_IFACE};
+ final String[] wifiIfaces = {TEST_IFACE, TEST_IFACE3};
incrementCurrentTime(HOUR_IN_MILLIS);
mockDefaultSettings();
- mockNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
+ mockNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 4)
.insertEntry(entry1)
.insertEntry(entry2)
- .insertEntry(entry3), emptyTetherStats, wifiIfaces);
+ .insertEntry(entry3)
+ .insertEntry(entry4), emptyTetherStats, wifiIfaces);
// getUidStatsForTransport (through getNetworkStatsUidDetail) adds all operation counts
// with active interface, and the interface here is mobile interface, so this test makes
@@ -1293,7 +1300,7 @@
assertValues(wifiStats, null /* iface */, UID_RED, SET_DEFAULT, 0xF00D,
METERED_NO, ROAMING_NO, METERED_NO, 50L, 5L, 50L, 5L, 1L);
assertValues(wifiStats, null /* iface */, UID_BLUE, SET_DEFAULT, 0xBEEF,
- METERED_NO, ROAMING_NO, METERED_NO, 1024L, 8L, 512L, 4L, 2L);
+ METERED_NO, ROAMING_NO, METERED_NO, 1025L, 10L, 515L, 8L, 7L);
final String[] mobileIfaces = {TEST_IFACE2};
mockNetworkStatsUidDetail(buildEmptyStats(), emptyTetherStats, mobileIfaces);