Merge "[Offload] Add DataElement to filter CHRE only scan request" into tm-mainline-prod
diff --git a/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp b/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp
index 6f9c8c2..ff62c0b 100644
--- a/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp
+++ b/service-t/native/libs/libnetworkstats/BpfNetworkStatsTest.cpp
@@ -326,7 +326,8 @@
             .txPackets = TEST_PACKET1,
             .txBytes = TEST_BYTES1,
     };
-    populateFakeStats(0, 0, 0, OVERFLOW_COUNTERSET, value1, mFakeStatsMap);
+    // next stats entry will be ignored due to ifindex 0 not being present in mFakeIfaceIndexNameMap
+    populateFakeStats(0, 0, 0, TEST_COUNTERSET1, value1, mFakeStatsMap);
     populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET0, value1, mFakeStatsMap);
     populateFakeStats(TEST_UID1, 0, IFACE_INDEX2, TEST_COUNTERSET0, value1, mFakeStatsMap);
     populateFakeStats(TEST_UID1, 0, IFACE_INDEX1, TEST_COUNTERSET1, value1, mFakeStatsMap);
diff --git a/service/src/com/android/server/connectivity/DscpPolicyTracker.java b/service/src/com/android/server/connectivity/DscpPolicyTracker.java
index 2bfad10..8d566b6 100644
--- a/service/src/com/android/server/connectivity/DscpPolicyTracker.java
+++ b/service/src/com/android/server/connectivity/DscpPolicyTracker.java
@@ -66,8 +66,8 @@
 
     private Set<String> mAttachedIfaces;
 
-    private final BpfMap<Struct.U32, DscpPolicyValue> mBpfDscpIpv4Policies;
-    private final BpfMap<Struct.U32, DscpPolicyValue> mBpfDscpIpv6Policies;
+    private final BpfMap<Struct.S32, DscpPolicyValue> mBpfDscpIpv4Policies;
+    private final BpfMap<Struct.S32, DscpPolicyValue> mBpfDscpIpv6Policies;
 
     // The actual policy rules used by the BPF code to process packets
     // are in mBpfDscpIpv4Policies and mBpfDscpIpv4Policies. Both of
@@ -85,10 +85,10 @@
     public DscpPolicyTracker() throws ErrnoException {
         mAttachedIfaces = new HashSet<String>();
         mIfaceIndexToPolicyIdBpfMapIndex = new HashMap<Integer, SparseIntArray>();
-        mBpfDscpIpv4Policies = new BpfMap<Struct.U32, DscpPolicyValue>(IPV4_POLICY_MAP_PATH,
-                BpfMap.BPF_F_RDWR, Struct.U32.class, DscpPolicyValue.class);
-        mBpfDscpIpv6Policies = new BpfMap<Struct.U32, DscpPolicyValue>(IPV6_POLICY_MAP_PATH,
-                BpfMap.BPF_F_RDWR, Struct.U32.class, DscpPolicyValue.class);
+        mBpfDscpIpv4Policies = new BpfMap<Struct.S32, DscpPolicyValue>(IPV4_POLICY_MAP_PATH,
+                BpfMap.BPF_F_RDWR, Struct.S32.class, DscpPolicyValue.class);
+        mBpfDscpIpv6Policies = new BpfMap<Struct.S32, DscpPolicyValue>(IPV6_POLICY_MAP_PATH,
+                BpfMap.BPF_F_RDWR, Struct.S32.class, DscpPolicyValue.class);
     }
 
     private boolean isUnusedIndex(int index) {
@@ -181,7 +181,7 @@
             // are both null or if they are both instances of Inet4Address.
             if (matchesIpv4(policy)) {
                 mBpfDscpIpv4Policies.insertOrReplaceEntry(
-                        new Struct.U32(addIndex),
+                        new Struct.S32(addIndex),
                         new DscpPolicyValue(policy.getSourceAddress(),
                             policy.getDestinationAddress(), ifIndex,
                             policy.getSourcePort(), policy.getDestinationPortRange(),
@@ -192,7 +192,7 @@
             // are both null or if they are both instances of Inet6Address.
             if (matchesIpv6(policy)) {
                 mBpfDscpIpv6Policies.insertOrReplaceEntry(
-                        new Struct.U32(addIndex),
+                        new Struct.S32(addIndex),
                         new DscpPolicyValue(policy.getSourceAddress(),
                                 policy.getDestinationAddress(), ifIndex,
                                 policy.getSourcePort(), policy.getDestinationPortRange(),
@@ -258,8 +258,8 @@
             boolean sendCallback) {
         int status = DSCP_POLICY_STATUS_POLICY_NOT_FOUND;
         try {
-            mBpfDscpIpv4Policies.replaceEntry(new Struct.U32(index), DscpPolicyValue.NONE);
-            mBpfDscpIpv6Policies.replaceEntry(new Struct.U32(index), DscpPolicyValue.NONE);
+            mBpfDscpIpv4Policies.replaceEntry(new Struct.S32(index), DscpPolicyValue.NONE);
+            mBpfDscpIpv6Policies.replaceEntry(new Struct.S32(index), DscpPolicyValue.NONE);
             status = DSCP_POLICY_STATUS_DELETED;
         } catch (ErrnoException e) {
             Log.e(TAG, "Failed to delete policy from map: ", e);
diff --git a/tests/mts/bpf_existence_test.cpp b/tests/mts/bpf_existence_test.cpp
index aa5654a..c294e7b 100644
--- a/tests/mts/bpf_existence_test.cpp
+++ b/tests/mts/bpf_existence_test.cpp
@@ -20,8 +20,6 @@
 #include <set>
 #include <string>
 
-#include <android/api-level.h>
-#include <android-base/properties.h>
 #include <android-modules-utils/sdk_level.h>
 #include <bpf/BpfUtils.h>
 
@@ -45,7 +43,7 @@
 class BpfExistenceTest : public ::testing::Test {
 };
 
-// Part of Android R platform, but mainlined in S
+// Part of Android R platform (for 4.9+), but mainlined in S
 static const set<string> PLATFORM_ONLY_IN_R = {
     PLATFORM "map_offload_tether_ingress_map",
     PLATFORM "map_offload_tether_limit_map",
@@ -128,17 +126,18 @@
     SHARED "prog_dscpPolicy_schedcls_set_dscp_ether",
 };
 
-void addAll(set<string>* a, const set<string>& b) {
-    a->insert(b.begin(), b.end());
+static void addAll(set<string>& a, const set<string>& b) {
+    a.insert(b.begin(), b.end());
 }
 
-#define DO_EXPECT(B, V) do { \
-    if (B) addAll(expected, (V)); else addAll(unexpected, (V)); \
-} while (0)
+#define DO_EXPECT(B, V) addAll((B) ? mustExist : mustNotExist, (V))
 
-void getFileLists(set<string>* expected, set<string>* unexpected) {
-    unexpected->clear();
-    expected->clear();
+TEST_F(BpfExistenceTest, TestPrograms) {
+    // Only unconfined root is guaranteed to be able to access everything in /sys/fs/bpf.
+    ASSERT_EQ(0, getuid()) << "This test must run as root.";
+
+    set<string> mustExist;
+    set<string> mustNotExist;
 
     // We do not actually check the platform P/Q (netd) and Q (clatd) things
     // and only verify the mainline module relevant R+ offload maps & progs.
@@ -147,24 +146,23 @@
     // and not to test the platform itself, which may have been modified by vendor or oems,
     // so we should only test for the removal of stuff that was mainline'd,
     // and for the presence of mainline stuff.
-    DO_EXPECT(IsAtLeastR() && !IsAtLeastS(), PLATFORM_ONLY_IN_R);
 
+    // R can potentially run on pre-4.9 kernel non-eBPF capable devices.
+    DO_EXPECT(IsAtLeastR() && !IsAtLeastS() && isAtLeastKernelVersion(4, 9, 0), PLATFORM_ONLY_IN_R);
+
+    // S requires Linux Kernel 4.9+ and thus requires eBPF support.
     DO_EXPECT(IsAtLeastS(), MAINLINE_FOR_S_PLUS);
     DO_EXPECT(IsAtLeastS() && isAtLeastKernelVersion(5, 10, 0), MAINLINE_FOR_S_5_10_PLUS);
 
     // Nothing added or removed in SCv2.
 
+    // T still only requires Linux Kernel 4.9+.
     DO_EXPECT(IsAtLeastT(), MAINLINE_FOR_T_PLUS);
     DO_EXPECT(IsAtLeastT() && isAtLeastKernelVersion(4, 14, 0), MAINLINE_FOR_T_4_14_PLUS);
     DO_EXPECT(IsAtLeastT() && isAtLeastKernelVersion(5, 4, 0), MAINLINE_FOR_T_5_4_PLUS);
     DO_EXPECT(IsAtLeastT() && isAtLeastKernelVersion(5, 15, 0), MAINLINE_FOR_T_5_15_PLUS);
-}
 
-void checkFiles() {
-    set<string> mustExist;
-    set<string> mustNotExist;
-
-    getFileLists(&mustExist, &mustNotExist);
+    // U requires Linux Kernel 4.14+, but nothing (as yet) added or removed in U.
 
     for (const auto& file : mustExist) {
         EXPECT_EQ(0, access(file.c_str(), R_OK)) << file << " does not exist";
@@ -178,19 +176,3 @@
         }
     }
 }
-
-TEST_F(BpfExistenceTest, TestPrograms) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
-
-    // Pre-flight check to ensure test has been updated.
-    uint64_t buildVersionSdk = android_get_device_api_level();
-    ASSERT_NE(0, buildVersionSdk) << "Unable to determine device SDK version";
-    if (buildVersionSdk > __ANDROID_API_T__ && buildVersionSdk != __ANDROID_API_FUTURE__) {
-            FAIL() << "Unknown OS version " << buildVersionSdk << ", please update this test";
-    }
-
-    // Only unconfined root is guaranteed to be able to access everything in /sys/fs/bpf.
-    ASSERT_EQ(0, getuid()) << "This test must run as root.";
-
-    checkFiles();
-}