Merge "Deduplicate items after clear interface in NetworkStats" into main

This commit is contained in:
Treehugger Robot
2023-08-01 07:40:57 +00:00
committed by Gerrit Code Review
5 changed files with 37 additions and 23 deletions

View File

@@ -1147,7 +1147,8 @@ public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent
entry.txPackets = left.txPackets[i]; entry.txPackets = left.txPackets[i];
entry.operations = left.operations[i]; entry.operations = left.operations[i];
// find remote row that matches, and subtract // Find the remote row that matches and subtract.
// The returned row must be uniquely matched.
final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
entry.metered, entry.roaming, entry.defaultNetwork, i); entry.metered, entry.roaming, entry.defaultNetwork, i);
if (j != -1) { if (j != -1) {
@@ -1304,13 +1305,14 @@ public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Ent
/** /**
* Removes the interface name from all entries. * Removes the interface name from all entries.
* This mutates the original structure in place. * This returns a newly constructed object instead of mutating the original structure.
* @hide * @hide
*/ */
public void clearInterfaces() { @NonNull
for (int i = 0; i < size; i++) { public NetworkStats clearInterfaces() {
iface[i] = null; final Entry temp = new Entry();
} return map(entry -> temp.setKeys(IFACE_ALL, entry.getUid(), entry.getSet(),
entry.getTag(), entry.getMetered(), entry.getRoaming(), entry.getDefaultNetwork()));
} }
/** /**

View File

@@ -1744,8 +1744,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// information. This is because no caller needs this information for now, and it // information. This is because no caller needs this information for now, and it
// makes it easier to change the implementation later by using the histories in the // makes it easier to change the implementation later by using the histories in the
// recorder. // recorder.
stats.clearInterfaces(); return stats.clearInterfaces();
return stats;
} catch (RemoteException e) { } catch (RemoteException e) {
Log.wtf(TAG, "Error compiling UID stats", e); Log.wtf(TAG, "Error compiling UID stats", e);
return new NetworkStats(0L, 0); return new NetworkStats(0L, 0);

View File

@@ -1073,30 +1073,35 @@ public class NetworkStatsTest {
final NetworkStats.Entry entry1 = new NetworkStats.Entry( final NetworkStats.Entry entry1 = new NetworkStats.Entry(
"test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L); DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L);
final NetworkStats.Entry entry2 = new NetworkStats.Entry( final NetworkStats.Entry entry2 = new NetworkStats.Entry(
"test2", 10101, SET_DEFAULT, 0xF0DD, METERED_NO, ROAMING_NO, "test2", 10101, SET_DEFAULT, 0xF0DD, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 51200, 25L, 101010L, 50L, 0L); DEFAULT_NETWORK_NO, 51200, 25L, 101010L, 50L, 0L);
final NetworkStats.Entry entry3 = new NetworkStats.Entry(
"test3", 10101, SET_DEFAULT, 0xF0DD, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1, 2L, 3L, 4L, 5L);
stats.insertEntry(entry1); stats.insertEntry(entry1);
stats.insertEntry(entry2); stats.insertEntry(entry2);
stats.insertEntry(entry3);
// Verify that the interfaces have indeed been recorded. // Verify that the interfaces have indeed been recorded.
assertEquals(2, stats.size()); assertEquals(3, stats.size());
assertValues(stats, 0, "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, assertValues(stats, 0, "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L); ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L);
assertValues(stats, 1, "test2", 10101, SET_DEFAULT, 0xF0DD, METERED_NO, assertValues(stats, 1, "test2", 10101, SET_DEFAULT, 0xF0DD, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, 51200, 25L, 101010L, 50L, 0L); ROAMING_NO, DEFAULT_NETWORK_NO, 51200, 25L, 101010L, 50L, 0L);
assertValues(stats, 2, "test3", 10101, SET_DEFAULT, 0xF0DD, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, 1, 2L, 3L, 4L, 5L);
// Clear interfaces. // Clear interfaces.
stats.clearInterfaces(); final NetworkStats ifaceClearedStats = stats.clearInterfaces();
// Verify that the interfaces are cleared. // Verify that the interfaces are cleared, and key-duplicated items are merged.
assertEquals(2, stats.size()); assertEquals(2, ifaceClearedStats.size());
assertValues(stats, 0, null /* iface */, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, assertValues(ifaceClearedStats, 0, null /* iface */, 10100, SET_DEFAULT, TAG_NONE,
ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L); METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 50L, 100L, 20L, 0L);
assertValues(stats, 1, null /* iface */, 10101, SET_DEFAULT, 0xF0DD, METERED_NO, assertValues(ifaceClearedStats, 1, null /* iface */, 10101, SET_DEFAULT, 0xF0DD,
ROAMING_NO, DEFAULT_NETWORK_NO, 51200, 25L, 101010L, 50L, 0L); METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 51201, 27L, 101013L, 54L, 5L);
} }
private static void assertContains(NetworkStats stats, String iface, int uid, int set, private static void assertContains(NetworkStats stats, String iface, int uid, int set,

View File

@@ -41,6 +41,7 @@ import java.util.Arrays;
abstract class NetworkStatsBaseTest { abstract class NetworkStatsBaseTest {
static final String TEST_IFACE = "test0"; static final String TEST_IFACE = "test0";
static final String TEST_IFACE2 = "test1"; static final String TEST_IFACE2 = "test1";
static final String TEST_IFACE3 = "test2";
static final String TUN_IFACE = "test_nss_tun0"; static final String TUN_IFACE = "test_nss_tun0";
static final String TUN_IFACE2 = "test_nss_tun1"; static final String TUN_IFACE2 = "test_nss_tun1";

View File

@@ -1250,8 +1250,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
TEST_IFACE2, IMSI_1, null /* wifiNetworkKey */, TEST_IFACE2, IMSI_1, null /* wifiNetworkKey */,
false /* isTemporarilyNotMetered */, false /* isRoaming */); false /* isTemporarilyNotMetered */, false /* isRoaming */);
final NetworkStateSnapshot[] states = new NetworkStateSnapshot[] { final NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{
mobileState, buildWifiState()}; mobileState, buildWifiState(false, TEST_IFACE, null),
buildWifiState(false, TEST_IFACE3, null)};
mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states), mService.notifyNetworkStatus(NETWORKS_MOBILE, states, getActiveIface(states),
new UnderlyingNetworkInfo[0]); new UnderlyingNetworkInfo[0]);
setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_LTE); setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_LTE);
@@ -1266,16 +1267,22 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
final NetworkStats.Entry entry3 = new NetworkStats.Entry( final NetworkStats.Entry entry3 = new NetworkStats.Entry(
TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xBEEF, METERED_NO, ROAMING_NO, TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xBEEF, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 8L, 512L, 4L, 2L); DEFAULT_NETWORK_NO, 1024L, 8L, 512L, 4L, 2L);
// Add an entry that with different wifi interface, but expected to be merged into entry3
// after clearing interface information.
final NetworkStats.Entry entry4 = new NetworkStats.Entry(
TEST_IFACE3, UID_BLUE, SET_DEFAULT, 0xBEEF, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1L, 2L, 3L, 4L, 5L);
final TetherStatsParcel[] emptyTetherStats = {}; final TetherStatsParcel[] emptyTetherStats = {};
// The interfaces that expect to be used to query the stats. // The interfaces that expect to be used to query the stats.
final String[] wifiIfaces = {TEST_IFACE}; final String[] wifiIfaces = {TEST_IFACE, TEST_IFACE3};
incrementCurrentTime(HOUR_IN_MILLIS); incrementCurrentTime(HOUR_IN_MILLIS);
mockDefaultSettings(); mockDefaultSettings();
mockNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) mockNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 4)
.insertEntry(entry1) .insertEntry(entry1)
.insertEntry(entry2) .insertEntry(entry2)
.insertEntry(entry3), emptyTetherStats, wifiIfaces); .insertEntry(entry3)
.insertEntry(entry4), emptyTetherStats, wifiIfaces);
// getUidStatsForTransport (through getNetworkStatsUidDetail) adds all operation counts // getUidStatsForTransport (through getNetworkStatsUidDetail) adds all operation counts
// with active interface, and the interface here is mobile interface, so this test makes // with active interface, and the interface here is mobile interface, so this test makes
@@ -1293,7 +1300,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
assertValues(wifiStats, null /* iface */, UID_RED, SET_DEFAULT, 0xF00D, assertValues(wifiStats, null /* iface */, UID_RED, SET_DEFAULT, 0xF00D,
METERED_NO, ROAMING_NO, METERED_NO, 50L, 5L, 50L, 5L, 1L); METERED_NO, ROAMING_NO, METERED_NO, 50L, 5L, 50L, 5L, 1L);
assertValues(wifiStats, null /* iface */, UID_BLUE, SET_DEFAULT, 0xBEEF, assertValues(wifiStats, null /* iface */, UID_BLUE, SET_DEFAULT, 0xBEEF,
METERED_NO, ROAMING_NO, METERED_NO, 1024L, 8L, 512L, 4L, 2L); METERED_NO, ROAMING_NO, METERED_NO, 1025L, 10L, 515L, 8L, 7L);
final String[] mobileIfaces = {TEST_IFACE2}; final String[] mobileIfaces = {TEST_IFACE2};
mockNetworkStatsUidDetail(buildEmptyStats(), emptyTetherStats, mobileIfaces); mockNetworkStatsUidDetail(buildEmptyStats(), emptyTetherStats, mobileIfaces);