Merge "wifi data usage: replaced Wi-Fi SSID with a Wi-Fi network key"
diff --git a/framework-t/src/android/app/usage/NetworkStats.java b/framework-t/src/android/app/usage/NetworkStats.java
index 216a4a0..f684a4d 100644
--- a/framework-t/src/android/app/usage/NetworkStats.java
+++ b/framework-t/src/android/app/usage/NetworkStats.java
@@ -24,13 +24,15 @@
 import android.net.NetworkTemplate;
 import android.net.TrafficStats;
 import android.os.RemoteException;
-import android.util.IntArray;
 import android.util.Log;
 
+import com.android.net.module.util.CollectionUtils;
+
 import dalvik.system.CloseGuard;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 
 /**
  * Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects
@@ -568,7 +570,7 @@
         //       the filtering logic below can be removed.
         int[] uids = mSession.getRelevantUids();
         // Filtering of uids with empty history.
-        IntArray filteredUids = new IntArray(uids.length);
+        final ArrayList<Integer> filteredUids = new ArrayList<>();
         for (int uid : uids) {
             try {
                 NetworkStatsHistory history = mSession.getHistoryIntervalForUid(mTemplate, uid,
@@ -581,7 +583,7 @@
                 Log.w(TAG, "Error while getting history of uid " + uid, e);
             }
         }
-        mUids = filteredUids.toArray();
+        mUids = CollectionUtils.toIntArray(filteredUids);
         mUidOrUidIndex = -1;
         stepHistory();
     }
diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java
index 40b6371..a316b8a 100644
--- a/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -47,7 +47,6 @@
 import android.os.RemoteException;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
-import android.util.DataUnit;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -119,7 +118,7 @@
      * is reached.
      * @hide
      */
-    public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2);
+    public static final long MIN_THRESHOLD_BYTES = 2 * 1_048_576L; // 2MiB
 
     private final Context mContext;
     private final INetworkStatsService mService;
@@ -139,6 +138,7 @@
         mContext = context;
         mService = service;
         setPollOnOpen(true);
+        setAugmentWithSubscriptionPlan(true);
     }
 
     /** @hide */
diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java
index 1986b83..181a594 100644
--- a/framework-t/src/android/net/NetworkStats.java
+++ b/framework-t/src/android/net/NetworkStats.java
@@ -31,7 +31,7 @@
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
+import com.android.net.module.util.CollectionUtils;
 
 import libcore.util.EmptyArray;
 
@@ -1185,7 +1185,7 @@
      * @hide
      */
     public void removeUids(int[] uids) {
-        filter(e -> !ArrayUtils.contains(uids, e.uid));
+        filter(e -> !CollectionUtils.contains(uids, e.uid));
     }
 
     /**
@@ -1218,7 +1218,7 @@
         filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
                 && (limitTag == TAG_ALL || limitTag == e.tag)
                 && (limitIfaces == INTERFACES_ALL
-                    || ArrayUtils.contains(limitIfaces, e.iface)));
+                    || CollectionUtils.contains(limitIfaces, e.iface)));
     }
 
     /**
diff --git a/framework-t/src/android/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java
index 591605d..8980bbc 100644
--- a/framework-t/src/android/net/NetworkStatsAccess.java
+++ b/framework-t/src/android/net/NetworkStatsAccess.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_REMOVED;
 import static android.net.TrafficStats.UID_TETHERING;
@@ -106,7 +107,7 @@
 
     /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
     public static @NetworkStatsAccess.Level int checkAccessLevel(
-            Context context, int callingUid, String callingPackage) {
+            Context context, int callingPid, int callingUid, String callingPackage) {
         final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class);
         final TelephonyManager tm = (TelephonyManager)
                 context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -123,8 +124,12 @@
         final boolean isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage);
         final int appId = UserHandle.getAppId(callingUid);
 
+        final boolean isNetworkStack = context.checkPermission(
+                android.Manifest.permission.NETWORK_STACK, callingPid, callingUid)
+                == PERMISSION_GRANTED;
+
         if (hasCarrierPrivileges || isDeviceOwner
-                || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) {
+                || appId == Process.SYSTEM_UID || isNetworkStack) {
             // Carrier-privileged apps and device owners, and the system (including the
             // network stack) can access data usage for all apps on the device.
             return NetworkStatsAccess.Level.DEVICE;
@@ -155,6 +160,8 @@
      */
     public static boolean isAccessibleToUser(int uid, int callerUid,
             @NetworkStatsAccess.Level int accessLevel) {
+        final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+        final int callerUserId = UserHandle.getUserHandleForUid(callerUid).getIdentifier();
         switch (accessLevel) {
             case NetworkStatsAccess.Level.DEVICE:
                 // Device-level access - can access usage for any uid.
@@ -165,13 +172,13 @@
                 // anonymized uids
                 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
                         || uid == UID_TETHERING || uid == UID_ALL
-                        || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
+                        || userId == callerUserId;
             case NetworkStatsAccess.Level.USER:
                 // User-level access - can access usage for any app running in the same user, along
                 // with some special uids (system, removed, or tethering).
                 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
                         || uid == UID_TETHERING
-                        || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
+                        || userId == callerUserId;
             case NetworkStatsAccess.Level.DEFAULT:
             default:
                 // Default access level - can only access one's own usage.
diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java
index 8d1347e..7935d28 100644
--- a/framework-t/src/android/net/NetworkStatsCollection.java
+++ b/framework-t/src/android/net/NetworkStatsCollection.java
@@ -40,21 +40,17 @@
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
-import android.util.IntArray;
-import android.util.MathUtils;
+import android.util.IndentingPrintWriter;
+import android.util.Log;
 import android.util.Range;
-import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastDataInput;
 import com.android.internal.util.FastDataOutput;
 import com.android.internal.util.FileRotator;
-import com.android.internal.util.IndentingPrintWriter;
-
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.NetworkStatsUtils;
 
 import libcore.io.IoUtils;
 
@@ -196,11 +192,11 @@
 
     public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel,
                 final int callerUid) {
-        IntArray uids = new IntArray();
+        final ArrayList<Integer> uids = new ArrayList<>();
         for (int i = 0; i < mStats.size(); i++) {
             final Key key = mStats.keyAt(i);
             if (NetworkStatsAccess.isAccessibleToUser(key.uid, callerUid, accessLevel)) {
-                int j = uids.binarySearch(key.uid);
+                int j = Collections.binarySearch(uids, new Integer(key.uid));
 
                 if (j < 0) {
                     j = ~j;
@@ -208,7 +204,7 @@
                 }
             }
         }
-        return uids.toArray();
+        return CollectionUtils.toIntArray(uids);
     }
 
     /**
@@ -225,7 +221,8 @@
 
         // 180 days of history should be enough for anyone; if we end up needing
         // more, we'll dynamically grow the history object.
-        final int bucketEstimate = (int) MathUtils.constrain(((end - start) / mBucketDuration), 0,
+        final int bucketEstimate = (int) NetworkStatsUtils.constrain(
+                ((end - start) / mBucketDuration), 0,
                 (180 * DateUtils.DAY_IN_MILLIS) / mBucketDuration);
         final NetworkStatsHistory combined = new NetworkStatsHistory(
                 mBucketDuration, bucketEstimate, fields);
@@ -316,7 +313,7 @@
 
             final long deltaTotal = combined.getTotalBytes() - beforeTotal;
             if (deltaTotal != 0) {
-                Slog.d(TAG, "Augmented network usage by " + deltaTotal + " bytes");
+                Log.d(TAG, "Augmented network usage by " + deltaTotal + " bytes");
             }
 
             // Finally we can slice data as originally requested
@@ -489,11 +486,11 @@
 
     private void write(DataOutput out) throws IOException {
         // cluster key lists grouped by ident
-        final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = Maps.newHashMap();
+        final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = new HashMap<>();
         for (Key key : mStats.keySet()) {
             ArrayList<Key> keys = keysByIdent.get(key.ident);
             if (keys == null) {
-                keys = Lists.newArrayList();
+                keys = new ArrayList<>();
                 keysByIdent.put(key.ident, keys);
             }
             keys.add(key);
@@ -640,12 +637,12 @@
      * {@link TrafficStats#UID_REMOVED}.
      */
     public void removeUids(int[] uids) {
-        final ArrayList<Key> knownKeys = Lists.newArrayList();
+        final ArrayList<Key> knownKeys = new ArrayList<>();
         knownKeys.addAll(mStats.keySet());
 
         // migrate all UID stats into special "removed" bucket
         for (Key key : knownKeys) {
-            if (ArrayUtils.contains(uids, key.uid)) {
+            if (CollectionUtils.contains(uids, key.uid)) {
                 // only migrate combined TAG_NONE history
                 if (key.tag == TAG_NONE) {
                     final NetworkStatsHistory uidHistory = mStats.get(key);
@@ -672,7 +669,7 @@
     }
 
     private ArrayList<Key> getSortedKeys() {
-        final ArrayList<Key> keys = Lists.newArrayList();
+        final ArrayList<Key> keys = new ArrayList<>();
         keys.addAll(mStats.keySet());
         Collections.sort(keys);
         return keys;
diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java
index 3eef4ee..428bc6d 100644
--- a/framework-t/src/android/net/NetworkStatsHistory.java
+++ b/framework-t/src/android/net/NetworkStatsHistory.java
@@ -28,7 +28,6 @@
 import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 
-import static com.android.internal.util.ArrayUtils.total;
 import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
 
 import android.compat.annotation.UnsupportedAppUsage;
@@ -37,10 +36,11 @@
 import android.os.Parcelable;
 import android.service.NetworkStatsHistoryBucketProto;
 import android.service.NetworkStatsHistoryProto;
-import android.util.MathUtils;
+import android.util.IndentingPrintWriter;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.NetworkStatsUtils;
 
 import libcore.util.EmptyArray;
 
@@ -174,7 +174,7 @@
                 txPackets = new long[bucketStart.length];
                 operations = new long[bucketStart.length];
                 bucketCount = bucketStart.length;
-                totalBytes = total(rxBytes) + total(txBytes);
+                totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
                 break;
             }
             case VERSION_ADD_PACKETS:
@@ -189,7 +189,7 @@
                 txPackets = readVarLongArray(in);
                 operations = readVarLongArray(in);
                 bucketCount = bucketStart.length;
-                totalBytes = total(rxBytes) + total(txBytes);
+                totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
                 break;
             }
             default: {
@@ -267,7 +267,7 @@
         } else {
             index -= 1;
         }
-        return MathUtils.constrain(index, 0, bucketCount - 1);
+        return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
     }
 
     /**
@@ -281,7 +281,7 @@
         } else {
             index += 1;
         }
-        return MathUtils.constrain(index, 0, bucketCount - 1);
+        return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
     }
 
     /**
@@ -349,6 +349,9 @@
 
         // create any buckets needed by this range
         ensureBuckets(start, end);
+        // Return fast if there is still no entry. This would typically happen when the start,
+        // end or duration are not valid values, e.g. start > end, negative duration value, etc.
+        if (bucketCount == 0) return;
 
         // distribute data usage into buckets
         long duration = end - start;
@@ -560,6 +563,9 @@
         entry.txPackets = txPackets != null ? 0 : UNKNOWN;
         entry.operations = operations != null ? 0 : UNKNOWN;
 
+        // Return fast if there is no entry.
+        if (bucketCount == 0) return entry;
+
         final int startIndex = getIndexAfter(end);
         for (int i = startIndex; i >= 0; i--) {
             final long curStart = bucketStart[i];
diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java
index fa65061..d8feb88 100644
--- a/framework-t/src/android/net/TrafficStats.java
+++ b/framework-t/src/android/net/TrafficStats.java
@@ -29,7 +29,6 @@
 import android.os.Build;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.util.DataUnit;
 
 import com.android.server.NetworkManagementSocketTagger;
 
@@ -59,19 +58,19 @@
      */
     public final static int UNSUPPORTED = -1;
 
-    /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
     @Deprecated
     public static final long KB_IN_BYTES = 1024;
-    /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
     @Deprecated
     public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
-    /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
     @Deprecated
     public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
-    /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
     @Deprecated
     public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
-    /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */
+    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
     @Deprecated
     public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
 
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 2beca73..dd933dd 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -655,8 +655,6 @@
 
     @Override
     public INetworkStatsSession openSession() {
-        // NOTE: if callers want to get non-augmented data, they should go
-        // through the public API
         return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null);
     }
 
@@ -811,7 +809,7 @@
 
     private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
         return NetworkStatsAccess.checkAccessLevel(
-                mContext, Binder.getCallingUid(), callingPackage);
+                mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
     }
 
     /**
@@ -876,8 +874,6 @@
     private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
         assertSystemReady();
 
-        // NOTE: if callers want to get non-augmented data, they should go
-        // through the public API
         return internalGetSummaryForNetwork(template,
                 NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end,
                 NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes();