Move battery stats to xt_qtaguid for data stats.

Replace TrafficStats calls by reading values from xt_qtaguid kernel
module. To keep BatteryStatsImpl changes lightweight, cache recently
parsed stats. Tracks mobile ifaces from ConnectivityService.

Refactor xt_qtaguid parsing into factory outside of NMS. Add stats
grouping based on UID, and total based on limiting filters like iface
prefix and UID.

Bug: 4902271
Change-Id: I533f116c434b77f93355bf95b839e7478528505b
diff --git a/services/tests/servicestests/res/raw/xt_qtaguid_iface_typical b/core/tests/coretests/res/raw/xt_qtaguid_iface_typical
similarity index 99%
rename from services/tests/servicestests/res/raw/xt_qtaguid_iface_typical
rename to core/tests/coretests/res/raw/xt_qtaguid_iface_typical
index efa4cd5..610723a 100644
--- a/services/tests/servicestests/res/raw/xt_qtaguid_iface_typical
+++ b/core/tests/coretests/res/raw/xt_qtaguid_iface_typical
@@ -1,6 +1,6 @@
-rmnet3 1 0 0 0 0 20822 501 1149991 815

-rmnet2 1 0 0 0 0 1594 15 1313 15

-rmnet1 1 0 0 0 0 207398 458 166918 565

-rmnet0 1 0 0 0 0 2112 24 700 10

-test1 1 1 2 3 4 5 6 7 8

-test2 0 1 2 3 4 5 6 7 8

+rmnet3 1 0 0 0 0 20822 501 1149991 815
+rmnet2 1 0 0 0 0 1594 15 1313 15
+rmnet1 1 0 0 0 0 207398 458 166918 565
+rmnet0 1 0 0 0 0 2112 24 700 10
+test1 1 1 2 3 4 5 6 7 8
+test2 0 1 2 3 4 5 6 7 8
diff --git a/services/tests/servicestests/res/raw/xt_qtaguid_typical b/core/tests/coretests/res/raw/xt_qtaguid_typical
similarity index 100%
rename from services/tests/servicestests/res/raw/xt_qtaguid_typical
rename to core/tests/coretests/res/raw/xt_qtaguid_typical
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index d78d2ef..7082deb 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -25,8 +25,12 @@
 
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.google.android.collect.Sets;
+
 import junit.framework.TestCase;
 
+import java.util.HashSet;
+
 @SmallTest
 public class NetworkStatsTest extends TestCase {
 
@@ -233,13 +237,43 @@
         assertValues(first, 2, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
     }
 
+    public void testGetTotal() {
+        final NetworkStats stats = new NetworkStats(TEST_START, 3)
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 64L, 4L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 512L, 32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L);
+
+        assertValues(stats.getTotal(null), 1280L, 80L, 0L, 2L, 20L);
+        assertValues(stats.getTotal(null, 100), 1152L, 72L, 0L, 2L, 20L);
+        assertValues(stats.getTotal(null, 101), 128L, 8L, 0L, 0L, 0L);
+
+        final HashSet<String> ifaces = Sets.newHashSet();
+        assertValues(stats.getTotal(null, ifaces), 0L, 0L, 0L, 0L, 0L);
+
+        ifaces.add(TEST_IFACE2);
+        assertValues(stats.getTotal(null, ifaces), 1024L, 64L, 0L, 0L, 0L);
+    }
+
     private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
             int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
         final NetworkStats.Entry entry = stats.getValues(index, null);
+        assertValues(entry, iface, uid, set, tag);
+        assertValues(entry, rxBytes, rxPackets, txBytes, txPackets, operations);
+    }
+
+    private static void assertValues(
+            NetworkStats.Entry entry, String iface, int uid, int set, int tag) {
         assertEquals(iface, entry.iface);
         assertEquals(uid, entry.uid);
         assertEquals(set, entry.set);
         assertEquals(tag, entry.tag);
+    }
+
+    private static void assertValues(NetworkStats.Entry entry, long rxBytes, long rxPackets,
+            long txBytes, long txPackets, long operations) {
         assertEquals(rxBytes, entry.rxBytes);
         assertEquals(rxPackets, entry.rxPackets);
         assertEquals(txBytes, entry.txBytes);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
similarity index 89%
rename from services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
rename to core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
index 40640e0..8a64f2b 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
+++ b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.internal.net;
 
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.SET_FOREGROUND;
@@ -25,9 +25,8 @@
 import android.content.res.Resources;
 import android.net.NetworkStats;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
 
-import com.android.frameworks.servicestests.R;
+import com.android.frameworks.coretests.R;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -39,12 +38,11 @@
 import libcore.io.Streams;
 
 /**
- * Tests for {@link NetworkManagementService}.
+ * Tests for {@link NetworkStatsFactory}.
  */
-@LargeTest
-public class NetworkManagementServiceTest extends AndroidTestCase {
+public class NetworkStatsFactoryTest extends AndroidTestCase {
     private File mTestProc;
-    private NetworkManagementService mService;
+    private NetworkStatsFactory mFactory;
 
     @Override
     public void setUp() throws Exception {
@@ -55,12 +53,12 @@
             IoUtils.deleteContents(mTestProc);
         }
 
-        mService = NetworkManagementService.createForTest(mContext, mTestProc, true);
+        mFactory = new NetworkStatsFactory(mTestProc);
     }
 
     @Override
     public void tearDown() throws Exception {
-        mService = null;
+        mFactory = null;
 
         if (mTestProc.exists()) {
             IoUtils.deleteContents(mTestProc);
@@ -72,7 +70,7 @@
     public void testNetworkStatsDetail() throws Exception {
         stageFile(R.raw.xt_qtaguid_typical, new File(mTestProc, "net/xt_qtaguid/stats"));
 
-        final NetworkStats stats = mService.getNetworkStatsDetail();
+        final NetworkStats stats = mFactory.readNetworkStatsDetail();
         assertEquals(31, stats.size());
         assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0, 14615L, 4270L);
         assertStatsEntry(stats, "wlan0", 10004, SET_DEFAULT, 0, 333821L, 53558L);
@@ -84,7 +82,7 @@
     public void testNetworkStatsDetailExtended() throws Exception {
         stageFile(R.raw.xt_qtaguid_extended, new File(mTestProc, "net/xt_qtaguid/stats"));
 
-        final NetworkStats stats = mService.getNetworkStatsDetail();
+        final NetworkStats stats = mFactory.readNetworkStatsDetail();
         assertEquals(2, stats.size());
         assertStatsEntry(stats, "test0", 1000, SET_DEFAULT, 0, 1024L, 2048L);
         assertStatsEntry(stats, "test0", 1000, SET_DEFAULT, 0xF00D, 512L, 512L);
@@ -93,7 +91,7 @@
     public void testNetworkStatsSummary() throws Exception {
         stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
 
-        final NetworkStats stats = mService.getNetworkStatsSummary();
+        final NetworkStats stats = mFactory.readNetworkStatsSummary();
         assertEquals(6, stats.size());
         assertStatsEntry(stats, "lo", UID_ALL, SET_DEFAULT, TAG_NONE, 8308L, 8308L);
         assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 1507570L, 489339L);
@@ -111,7 +109,7 @@
         stageLong(2048L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_bytes"));
         stageLong(256L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_packets"));
 
-        final NetworkStats stats = mService.getNetworkStatsSummary();
+        final NetworkStats stats = mFactory.readNetworkStatsSummary();
         assertEquals(7, stats.size());
         assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 1507570L, 489339L);
         assertStatsEntry(stats, "wlan0", UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 2048L);
@@ -125,7 +123,7 @@
         stageLong(30L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_bytes"));
         stageLong(40L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_packets"));
 
-        final NetworkStats stats = mService.getNetworkStatsSummary();
+        final NetworkStats stats = mFactory.readNetworkStatsSummary();
         assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 1507570L + 10L,
                 2205L + 20L, 489339L + 30L, 2237L + 40L);
     }
@@ -138,7 +136,7 @@
         stageLong(30L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_bytes"));
         stageLong(40L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_packets"));
 
-        final NetworkStats stats = mService.getNetworkStatsSummary();
+        final NetworkStats stats = mFactory.readNetworkStatsSummary();
         assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 10L, 20L, 30L, 40L);
     }
 
@@ -153,7 +151,7 @@
     public void testNetworkStatsWithSet() throws Exception {
         stageFile(R.raw.xt_qtaguid_typical_with_set, new File(mTestProc, "net/xt_qtaguid/stats"));
 
-        final NetworkStats stats = mService.getNetworkStatsDetail();
+        final NetworkStats stats = mFactory.readNetworkStatsDetail();
         assertEquals(12, stats.size());
         assertStatsEntry(stats, "rmnet0", 1000, SET_DEFAULT, 0, 278102L, 253L, 10487L, 182L);
         assertStatsEntry(stats, "rmnet0", 1000, SET_FOREGROUND, 0, 26033L, 30L, 1401L, 26L);
@@ -162,7 +160,7 @@
     public void testNetworkStatsSingle() throws Exception {
         stageFile(R.raw.xt_qtaguid_iface_typical, new File(mTestProc, "net/xt_qtaguid/iface_stat_all"));
 
-        final NetworkStats stats = mService.getNetworkStatsSummary();
+        final NetworkStats stats = mFactory.readNetworkStatsSummary();
         assertEquals(6, stats.size());
         assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 2112L, 24L, 700L, 10L);
         assertStatsEntry(stats, "test1", UID_ALL, SET_DEFAULT, TAG_NONE, 6L, 8L, 10L, 12L);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index ce31474..498bdfc 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -73,6 +73,7 @@
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.telephony.Phone;
+import com.android.server.am.BatteryStatsService;
 import com.android.server.connectivity.Tethering;
 import com.android.server.connectivity.Vpn;
 import com.google.android.collect.Lists;
@@ -1649,11 +1650,11 @@
     }
 
     private void handleConnect(NetworkInfo info) {
-        int type = info.getType();
+        final int type = info.getType();
 
         // snapshot isFailover, because sendConnectedBroadcast() resets it
         boolean isFailover = info.isFailover();
-        NetworkStateTracker thisNet = mNetTrackers[type];
+        final NetworkStateTracker thisNet = mNetTrackers[type];
 
         // if this is a default net and other default is running
         // kill the one not preferred
@@ -1710,6 +1711,16 @@
         updateNetworkSettings(thisNet);
         handleConnectivityChange(type, false);
         sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
+
+        // notify battery stats service about this network
+        final String iface = thisNet.getLinkProperties().getInterfaceName();
+        if (iface != null) {
+            try {
+                BatteryStatsService.getService().noteNetworkInterfaceType(iface, type);
+            } catch (RemoteException e) {
+                // ignored; service lives in system_server
+            }
+        }
     }
 
     /**