Merge "Flush the bucket when creating the metric producer. Use int64 for value field. E2e test for gauge/value metric." into pi-dev
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 85f4efc..0b21196 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -35,6 +35,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
+import android.util.DataUnit;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -95,6 +96,15 @@
     /** @hide */
     public static final int CALLBACK_RELEASED = 1;
 
+    /**
+     * Minimum data usage threshold for registering usage callbacks.
+     *
+     * Requests registered with a threshold lower than this will only be triggered once this minimum
+     * is reached.
+     * @hide
+     */
+    public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2);
+
     private final Context mContext;
     private final INetworkStatsService mService;
 
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 6f812ac..bd4a27c 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -168,11 +168,6 @@
          * the requested network's required capabilities.  Note that when searching
          * for a network to satisfy a request, all capabilities requested must be
          * satisfied.
-         * <p>
-         * If the given capability was previously added to the list of unwanted capabilities
-         * then the capability will also be removed from the list of unwanted capabilities.
-         *
-         * @see #addUnwantedCapability(int)
          *
          * @param capability The capability to add.
          * @return The builder to facilitate chaining
@@ -184,8 +179,7 @@
         }
 
         /**
-         * Removes (if found) the given capability from this builder instance from both required
-         * and unwanted capabilities lists.
+         * Removes (if found) the given capability from this builder instance.
          *
          * @param capability The capability to remove.
          * @return The builder to facilitate chaining.
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 4bad5aa..6fa999c 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -56,6 +56,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
+import android.util.DataUnit;
 import android.util.DebugUtils;
 import android.util.Pair;
 import android.util.Range;
@@ -333,11 +334,11 @@
                 if (DBG) Slog.d(TAG, "Setting quota: " + quota + " bytes");
             }
 
+            // TODO: re-register if day changed: budget may have run out but should be refreshed.
             if (haveMultipathBudget() && quota == mQuota) {
-                // If we already have a usage callback pending , there's no need to re-register it
+                // If there is already a usage callback pending , there's no need to re-register it
                 // if the quota hasn't changed. The callback will simply fire as expected when the
-                // budget is spent. Also: if we re-register the callback when we're below the
-                // UsageCallback's minimum value of 2MB, we'll overshoot the budget.
+                // budget is spent.
                 if (DBG) Slog.d(TAG, "Quota still " + quota + ", not updating.");
                 return;
             }
@@ -347,7 +348,17 @@
             // ourselves any budget to work with.
             final long usage = getDailyNonDefaultDataUsage();
             final long budget = (usage == -1) ? 0 : Math.max(0, quota - usage);
-            if (budget > 0) {
+
+            // Only consider budgets greater than MIN_THRESHOLD_BYTES, otherwise the callback will
+            // fire late, after data usage went over budget. Also budget should be 0 if remaining
+            // data is close to 0.
+            // This is necessary because the usage callback does not accept smaller thresholds.
+            // Because it snaps everything to MIN_THRESHOLD_BYTES, the lesser of the two evils is
+            // to snap to 0 here.
+            // This will only be called if the total quota for the day changed, not if usage changed
+            // since last time, so even if this is called very often the budget will not snap to 0
+            // as soon as there are less than 2MB left for today.
+            if (budget > NetworkStatsManager.MIN_THRESHOLD_BYTES) {
                 if (DBG) Slog.d(TAG, "Setting callback for " + budget +
                         " bytes on network " + network);
                 registerUsageCallback(budget);
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index 741c206..d840873 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java
@@ -16,7 +16,7 @@
 
 package com.android.server.net;
 
-import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
 
 import static com.android.internal.util.Preconditions.checkArgument;
 
@@ -52,8 +52,6 @@
     private static final String TAG = "NetworkStatsObservers";
     private static final boolean LOGV = false;
 
-    private static final long MIN_THRESHOLD_BYTES = 2 * MB_IN_BYTES;
-
     private static final int MSG_REGISTER = 1;
     private static final int MSG_UNREGISTER = 2;
     private static final int MSG_UPDATE_STATS = 3;