Merge "Gracefully handle integer overflows." into r-keystone-qcom-dev
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index a229692..c075486 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import static android.net.NetworkStatsHistory.multiplySafe;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1552,32 +1554,37 @@
                 // processes this every time device has transmitted/received amount equivalent to
                 // global threshold alert (~ 2MB) across all interfaces.
                 final long rxBytesAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
+                        multiplySafe(underlyingIfacesTotal.rxBytes,
+                                rxBytes[i], tunIfaceTotal.rxBytes);
                 // app must not be blamed for more than it consumed on tunIface
                 totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces);
             }
             long totalRxPackets = 0;
             if (tunIfaceTotal.rxPackets > 0) {
                 final long rxPacketsAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
+                        multiplySafe(underlyingIfacesTotal.rxPackets,
+                                rxPackets[i], tunIfaceTotal.rxPackets);
                 totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
             }
             long totalTxBytes = 0;
             if (tunIfaceTotal.txBytes > 0) {
                 final long txBytesAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
+                        multiplySafe(underlyingIfacesTotal.txBytes,
+                                txBytes[i], tunIfaceTotal.txBytes);
                 totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
             }
             long totalTxPackets = 0;
             if (tunIfaceTotal.txPackets > 0) {
                 final long txPacketsAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
+                        multiplySafe(underlyingIfacesTotal.txPackets,
+                                txPackets[i], tunIfaceTotal.txPackets);
                 totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
             }
             long totalOperations = 0;
             if (tunIfaceTotal.operations > 0) {
                 final long operationsAcrossUnderlyingIfaces =
-                        underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations;
+                        multiplySafe(underlyingIfacesTotal.operations,
+                                operations[i], tunIfaceTotal.operations);
                 totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces);
             }
             // In a second pass, distribute these values across interfaces in the proportion that
@@ -1589,37 +1596,37 @@
                 tmpEntry.set = set[i];
                 if (underlyingIfacesTotal.rxBytes > 0) {
                     tmpEntry.rxBytes =
-                            totalRxBytes
-                                    * perInterfaceTotal[j].rxBytes
-                                    / underlyingIfacesTotal.rxBytes;
+                            multiplySafe(totalRxBytes,
+                                    perInterfaceTotal[j].rxBytes,
+                                    underlyingIfacesTotal.rxBytes);
                 }
                 tmpEntry.rxPackets = 0;
                 if (underlyingIfacesTotal.rxPackets > 0) {
                     tmpEntry.rxPackets =
-                            totalRxPackets
-                                    * perInterfaceTotal[j].rxPackets
-                                    / underlyingIfacesTotal.rxPackets;
+                            multiplySafe(totalRxPackets,
+                                    perInterfaceTotal[j].rxPackets,
+                                    underlyingIfacesTotal.rxPackets);
                 }
                 tmpEntry.txBytes = 0;
                 if (underlyingIfacesTotal.txBytes > 0) {
                     tmpEntry.txBytes =
-                            totalTxBytes
-                                    * perInterfaceTotal[j].txBytes
-                                    / underlyingIfacesTotal.txBytes;
+                            multiplySafe(totalTxBytes,
+                                    perInterfaceTotal[j].txBytes,
+                                    underlyingIfacesTotal.txBytes);
                 }
                 tmpEntry.txPackets = 0;
                 if (underlyingIfacesTotal.txPackets > 0) {
                     tmpEntry.txPackets =
-                            totalTxPackets
-                                    * perInterfaceTotal[j].txPackets
-                                    / underlyingIfacesTotal.txPackets;
+                            multiplySafe(totalTxPackets,
+                                    perInterfaceTotal[j].txPackets,
+                                    underlyingIfacesTotal.txPackets);
                 }
                 tmpEntry.operations = 0;
                 if (underlyingIfacesTotal.operations > 0) {
                     tmpEntry.operations =
-                            totalOperations
-                                    * perInterfaceTotal[j].operations
-                                    / underlyingIfacesTotal.operations;
+                            multiplySafe(totalOperations,
+                                    perInterfaceTotal[j].operations,
+                                    underlyingIfacesTotal.operations);
                 }
                 // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying
                 // interface. Add that data usage to this object.
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 4d0e6e6..1ed80e4 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -282,8 +282,8 @@
             }
 
             final long rawBytes = entry.rxBytes + entry.txBytes;
-            final long rawRxBytes = entry.rxBytes;
-            final long rawTxBytes = entry.txBytes;
+            final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes;
+            final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes;
             final long targetBytes = augmentPlan.getDataUsageBytes();
             final long targetRxBytes = combined.multiplySafe(targetBytes, rawRxBytes, rawBytes);
             final long targetTxBytes = combined.multiplySafe(targetBytes, rawTxBytes, rawBytes);