[SP34] Adapt onSetWarningAndLimit

This is a no-op change that just adapt new API from
NetworkStatsProvider to get warning and limit bytes at the same
time. This change also stores them locally for subsequent
patches to set warning bytes to hardware.

Test: Will be included in the subsequent patch.
Bug: 149467454
Ignore-AOSP-First: avoid long automerger delay
Change-Id: Iec01cb01fd1ce481ce0bd736762baddde1e38084
diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadController.java b/Tethering/src/com/android/networkstack/tethering/OffloadController.java
index 44e3916..c612271e 100644
--- a/Tethering/src/com/android/networkstack/tethering/OffloadController.java
+++ b/Tethering/src/com/android/networkstack/tethering/OffloadController.java
@@ -114,11 +114,42 @@
     private ConcurrentHashMap<String, ForwardedStats> mForwardedStats =
             new ConcurrentHashMap<>(16, 0.75F, 1);
 
+    private static class InterfaceQuota {
+        public final long warningBytes;
+        public final long limitBytes;
+
+        public static InterfaceQuota MAX_VALUE = new InterfaceQuota(Long.MAX_VALUE, Long.MAX_VALUE);
+
+        InterfaceQuota(long warningBytes, long limitBytes) {
+            this.warningBytes = warningBytes;
+            this.limitBytes = limitBytes;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof InterfaceQuota)) return false;
+            InterfaceQuota that = (InterfaceQuota) o;
+            return warningBytes == that.warningBytes
+                    && limitBytes == that.limitBytes;
+        }
+
+        @Override
+        public int hashCode() {
+            return (int) (warningBytes * 3 + limitBytes * 5);
+        }
+
+        @Override
+        public String toString() {
+            return "InterfaceQuota{" + "warning=" + warningBytes + ", limit=" + limitBytes + '}';
+        }
+    }
+
     // Maps upstream interface names to interface quotas.
     // Always contains the latest value received from the framework for each interface, regardless
     // of whether offload is currently running (or is even supported) on that interface. Only
     // includes upstream interfaces that have a quota set.
-    private HashMap<String, Long> mInterfaceQuotas = new HashMap<>();
+    private HashMap<String, InterfaceQuota> mInterfaceQuotas = new HashMap<>();
 
     // Tracking remaining alert quota. Unlike limit quota is subject to interface, the alert
     // quota is interface independent and global for tether offload. Note that this is only
@@ -263,7 +294,8 @@
             mLog.i("tethering offload control not supported");
             stop();
         } else {
-            mLog.log("tethering offload started");
+            mLog.log("tethering offload started, version: "
+                    + OffloadHardwareInterface.halVerToString(mControlHalVersion));
             mNatUpdateCallbacksReceived = 0;
             mNatUpdateNetlinkErrors = 0;
             maybeSchedulePollingStats();
@@ -322,24 +354,35 @@
 
         @Override
         public void onSetLimit(String iface, long quotaBytes) {
+            onSetWarningAndLimit(iface, QUOTA_UNLIMITED, quotaBytes);
+        }
+
+        @Override
+        public void onSetWarningAndLimit(@NonNull String iface,
+                long warningBytes, long limitBytes) {
             // Listen for all iface is necessary since upstream might be changed after limit
             // is set.
             mHandler.post(() -> {
-                final Long curIfaceQuota = mInterfaceQuotas.get(iface);
+                final InterfaceQuota curIfaceQuota = mInterfaceQuotas.get(iface);
+                final InterfaceQuota newIfaceQuota = new InterfaceQuota(
+                        warningBytes == QUOTA_UNLIMITED ? Long.MAX_VALUE : warningBytes,
+                        limitBytes == QUOTA_UNLIMITED ? Long.MAX_VALUE : limitBytes);
 
                 // If the quota is set to unlimited, the value set to HAL is Long.MAX_VALUE,
                 // which is ~8.4 x 10^6 TiB, no one can actually reach it. Thus, it is not
                 // useful to set it multiple times.
                 // Otherwise, the quota needs to be updated to tell HAL to re-count from now even
                 // if the quota is the same as the existing one.
-                if (null == curIfaceQuota && QUOTA_UNLIMITED == quotaBytes) return;
+                if (null == curIfaceQuota && InterfaceQuota.MAX_VALUE.equals(newIfaceQuota)) {
+                    return;
+                }
 
-                if (quotaBytes == QUOTA_UNLIMITED) {
+                if (InterfaceQuota.MAX_VALUE.equals(newIfaceQuota)) {
                     mInterfaceQuotas.remove(iface);
                 } else {
-                    mInterfaceQuotas.put(iface, quotaBytes);
+                    mInterfaceQuotas.put(iface, newIfaceQuota);
                 }
-                maybeUpdateDataLimit(iface);
+                maybeUpdateDataWarningAndLimit(iface);
             });
         }
 
@@ -465,18 +508,15 @@
                 >= DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
     }
 
-    private boolean maybeUpdateDataLimit(String iface) {
-        // setDataLimit may only be called while offload is occurring on this upstream.
+    private boolean maybeUpdateDataWarningAndLimit(String iface) {
+        // setDataLimit or setDataWarningAndLimit may only be called while offload is occurring
+        // on this upstream.
         if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) {
             return true;
         }
 
-        Long limit = mInterfaceQuotas.get(iface);
-        if (limit == null) {
-            limit = Long.MAX_VALUE;
-        }
-
-        return mHwInterface.setDataLimit(iface, limit);
+        final InterfaceQuota quota = mInterfaceQuotas.getOrDefault(iface, InterfaceQuota.MAX_VALUE);
+        return mHwInterface.setDataLimit(iface, quota.limitBytes);
     }
 
     private void updateStatsForCurrentUpstream() {
@@ -630,7 +670,7 @@
         maybeUpdateStats(prevUpstream);
 
         // Data limits can only be set once offload is running on the upstream.
-        success = maybeUpdateDataLimit(iface);
+        success = maybeUpdateDataWarningAndLimit(iface);
         if (!success) {
             // If we failed to set a data limit, don't use this upstream, because we don't want to
             // blow through the data limit that we were told to apply.
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
index 88f2054..14c34f0 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
@@ -58,7 +58,6 @@
 import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
-import android.net.ITetheringStatsProvider;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
@@ -503,8 +502,12 @@
                 expectedUidStatsDiff);
     }
 
+    /**
+     * Test OffloadController that uses V1.0 HAL setDataLimit with NetworkStatsProvider#onSetLimit
+     * which is called by R framework.
+     */
     @Test
-    public void testSetInterfaceQuota() throws Exception {
+    public void testSetDataLimit() throws Exception {
         enableOffload();
         final OffloadController offload =
                 startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
@@ -540,9 +543,9 @@
         waitForIdle();
         inOrder.verify(mHardware).setDataLimit(mobileIface, mobileLimit);
 
-        // Setting a limit of ITetheringStatsProvider.QUOTA_UNLIMITED causes the limit to be set
+        // Setting a limit of NetworkStatsProvider.QUOTA_UNLIMITED causes the limit to be set
         // to Long.MAX_VALUE.
-        mTetherStatsProvider.onSetLimit(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED);
+        mTetherStatsProvider.onSetLimit(mobileIface, NetworkStatsProvider.QUOTA_UNLIMITED);
         waitForIdle();
         inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE);