Merge "No-op refactoring for TrafficStats APIs" into main

This commit is contained in:
Yun-Chen Cheng 2024-09-11 01:56:42 +00:00 • committed by Gerrit Code Review
commit 05fb57ea97
5 changed files with 193 additions and 136 deletions

View file

@ -78,13 +78,16 @@ interface INetworkStatsService {
void unregisterUsageRequest(in DataUsageRequest request);
/** Get the uid stats information since boot */
long getUidStats(int uid, int type);
NetworkStats getTypelessUidStats(int uid);
/** Get the iface stats information since boot */
long getIfaceStats(String iface, int type);
NetworkStats getTypelessIfaceStats(String iface);
/** Get the total network stats information since boot */
long getTotalStats(int type);
NetworkStats getTypelessTotalStats();
/** Get the uid stats information (with specified type) since boot */
long getUidStats(int uid, int type);
/** Registers a network stats provider */
INetworkStatsProviderCallback registerNetworkStatsProvider(String tag,

View file

@ -40,6 +40,9 @@ import java.io.IOException;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Iterator;
import java.util.Objects;
/**
* Class that provides network traffic statistics. These statistics include
@ -730,11 +733,7 @@ public class TrafficStats {
* @return The number of transmitted packets.
*/
public static long getTxPackets(@NonNull String iface) {
try {
return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getIfaceStats(iface, TYPE_TX_PACKETS);
}
/**
@ -753,11 +752,7 @@ public class TrafficStats {
* @return The number of received packets.
*/
public static long getRxPackets(@NonNull String iface) {
try {
return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getIfaceStats(iface, TYPE_RX_PACKETS);
}
/**
@ -776,11 +771,7 @@ public class TrafficStats {
* @return The number of transmitted bytes.
*/
public static long getTxBytes(@NonNull String iface) {
try {
return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getIfaceStats(iface, TYPE_TX_BYTES);
}
/**
@ -799,51 +790,31 @@ public class TrafficStats {
* @return The number of received bytes.
*/
public static long getRxBytes(@NonNull String iface) {
try {
return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getIfaceStats(iface, TYPE_RX_BYTES);
}
/** {@hide} */
@TestApi
public static long getLoopbackTxPackets() {
try {
return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_PACKETS);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getIfaceStats(LOOPBACK_IFACE, TYPE_TX_PACKETS);
}
/** {@hide} */
@TestApi
public static long getLoopbackRxPackets() {
try {
return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_PACKETS);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getIfaceStats(LOOPBACK_IFACE, TYPE_RX_PACKETS);
}
/** {@hide} */
@TestApi
public static long getLoopbackTxBytes() {
try {
return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_BYTES);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getIfaceStats(LOOPBACK_IFACE, TYPE_TX_BYTES);
}
/** {@hide} */
@TestApi
public static long getLoopbackRxBytes() {
try {
return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_BYTES);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getIfaceStats(LOOPBACK_IFACE, TYPE_RX_BYTES);
}
/**
@ -856,11 +827,7 @@ public class TrafficStats {
* return {@link #UNSUPPORTED} on devices where statistics aren't available.
*/
public static long getTotalTxPackets() {
try {
return getStatsService().getTotalStats(TYPE_TX_PACKETS);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getTotalStats(TYPE_TX_PACKETS);
}
/**
@ -873,11 +840,7 @@ public class TrafficStats {
* return {@link #UNSUPPORTED} on devices where statistics aren't available.
*/
public static long getTotalRxPackets() {
try {
return getStatsService().getTotalStats(TYPE_RX_PACKETS);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getTotalStats(TYPE_RX_PACKETS);
}
/**
@ -890,11 +853,7 @@ public class TrafficStats {
* return {@link #UNSUPPORTED} on devices where statistics aren't available.
*/
public static long getTotalTxBytes() {
try {
return getStatsService().getTotalStats(TYPE_TX_BYTES);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getTotalStats(TYPE_TX_BYTES);
}
/**
@ -907,11 +866,7 @@ public class TrafficStats {
* return {@link #UNSUPPORTED} on devices where statistics aren't available.
*/
public static long getTotalRxBytes() {
try {
return getStatsService().getTotalStats(TYPE_RX_BYTES);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getTotalStats(TYPE_RX_BYTES);
}
/**
@ -933,11 +888,7 @@ public class TrafficStats {
* @see android.content.pm.ApplicationInfo#uid
*/
public static long getUidTxBytes(int uid) {
try {
return getStatsService().getUidStats(uid, TYPE_TX_BYTES);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getUidStats(uid, TYPE_TX_BYTES);
}
/**
@ -959,11 +910,7 @@ public class TrafficStats {
* @see android.content.pm.ApplicationInfo#uid
*/
public static long getUidRxBytes(int uid) {
try {
return getStatsService().getUidStats(uid, TYPE_RX_BYTES);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getUidStats(uid, TYPE_RX_BYTES);
}
/**
@ -985,11 +932,7 @@ public class TrafficStats {
* @see android.content.pm.ApplicationInfo#uid
*/
public static long getUidTxPackets(int uid) {
try {
return getStatsService().getUidStats(uid, TYPE_TX_PACKETS);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getUidStats(uid, TYPE_TX_PACKETS);
}
/**
@ -1011,11 +954,50 @@ public class TrafficStats {
* @see android.content.pm.ApplicationInfo#uid
*/
public static long getUidRxPackets(int uid) {
return getUidStats(uid, TYPE_RX_PACKETS);
}
/** @hide */
public static long getUidStats(int uid, int type) {
if (!isEntryValueTypeValid(type)
|| android.os.Process.myUid() != uid) {
return UNSUPPORTED;
}
final NetworkStats stats;
try {
return getStatsService().getUidStats(uid, TYPE_RX_PACKETS);
stats = getStatsService().getTypelessUidStats(uid);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getValueForTypeFromFirstEntry(stats, type);
}
/** @hide */
public static long getTotalStats(int type) {
if (!isEntryValueTypeValid(type)) {
return UNSUPPORTED;
}
final NetworkStats stats;
try {
stats = getStatsService().getTypelessTotalStats();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getValueForTypeFromFirstEntry(stats, type);
}
/** @hide */
public static long getIfaceStats(String iface, int type) {
if (!isEntryValueTypeValid(type)) {
return UNSUPPORTED;
}
final NetworkStats stats;
try {
stats = getStatsService().getTypelessIfaceStats(iface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getValueForTypeFromFirstEntry(stats, type);
}
/**
@ -1143,4 +1125,45 @@ public class TrafficStats {
public static final int TYPE_TX_BYTES = 2;
/** {@hide} */
public static final int TYPE_TX_PACKETS = 3;
/** @hide */
private static long getEntryValueForType(@NonNull NetworkStats.Entry entry, int type) {
Objects.requireNonNull(entry);
if (!isEntryValueTypeValid(type)) return UNSUPPORTED;
switch (type) {
case TYPE_RX_BYTES:
return entry.getRxBytes();
case TYPE_RX_PACKETS:
return entry.getRxPackets();
case TYPE_TX_BYTES:
return entry.getTxBytes();
case TYPE_TX_PACKETS:
return entry.getTxPackets();
default:
throw new IllegalStateException("Bug: Invalid type: "
+ type + " should not reach here.");
}
}
/** @hide */
private static boolean isEntryValueTypeValid(int type) {
switch (type) {
case TYPE_RX_BYTES:
case TYPE_RX_PACKETS:
case TYPE_TX_BYTES:
case TYPE_TX_PACKETS:
return true;
default :
return false;
}
}
/** @hide */
public static long getValueForTypeFromFirstEntry(@NonNull NetworkStats stats, int type) {
Objects.requireNonNull(stats);
Iterator<NetworkStats.Entry> iter = stats.iterator();
if (!iter.hasNext()) return UNSUPPORTED;
return getEntryValueForType(iter.next(), type);
}
}

View file

@ -51,12 +51,8 @@ import static android.net.NetworkTemplate.MATCH_TEST;
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.TrafficStats.KB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.TYPE_RX_BYTES;
import static android.net.TrafficStats.TYPE_RX_PACKETS;
import static android.net.TrafficStats.TYPE_TX_BYTES;
import static android.net.TrafficStats.TYPE_TX_PACKETS;
import static android.net.TrafficStats.UID_TETHERING;
import static android.net.TrafficStats.UNSUPPORTED;
import static android.net.TrafficStats.getValueForTypeFromFirstEntry;
import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_TRAFFICSTATS_RATE_LIMIT_CACHE;
import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID;
import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG;
@ -2135,20 +2131,28 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public long getUidStats(int uid, int type) {
return getValueForTypeFromFirstEntry(getTypelessUidStats(uid), type);
}
@NonNull
@Override
public NetworkStats getTypelessUidStats(int uid) {
final NetworkStats stats = new NetworkStats(0, 0);
final int callingUid = Binder.getCallingUid();
if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) {
return UNSUPPORTED;
return stats;
}
if (!isEntryValueTypeValid(type)) return UNSUPPORTED;
final NetworkStats.Entry entry;
if (mAlwaysUseTrafficStatsRateLimitCache
|| mDeps.isChangeEnabled(ENABLE_TRAFFICSTATS_RATE_LIMIT_CACHE, callingUid)) {
final NetworkStats.Entry entry = mTrafficStatsUidCache.getOrCompute(IFACE_ALL, uid,
entry = mTrafficStatsUidCache.getOrCompute(IFACE_ALL, uid,
() -> mDeps.nativeGetUidStat(uid));
return getEntryValueForType(entry, type);
}
} else entry = mDeps.nativeGetUidStat(uid);
return getEntryValueForType(mDeps.nativeGetUidStat(uid), type);
if (entry != null) {
stats.insertEntry(entry);
}
return stats;
}
@Nullable
@ -2165,50 +2169,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return entry;
}
@NonNull
@Override
public long getIfaceStats(@NonNull String iface, int type) {
public NetworkStats getTypelessIfaceStats(@NonNull String iface) {
Objects.requireNonNull(iface);
if (!isEntryValueTypeValid(type)) return UNSUPPORTED;
final NetworkStats.Entry entry;
if (mAlwaysUseTrafficStatsRateLimitCache
|| mDeps.isChangeEnabled(
ENABLE_TRAFFICSTATS_RATE_LIMIT_CACHE, Binder.getCallingUid())) {
final NetworkStats.Entry entry = mTrafficStatsIfaceCache.getOrCompute(iface, UID_ALL,
entry = mTrafficStatsIfaceCache.getOrCompute(iface, UID_ALL,
() -> getIfaceStatsInternal(iface));
return getEntryValueForType(entry, type);
}
} else entry = getIfaceStatsInternal(iface);
return getEntryValueForType(getIfaceStatsInternal(iface), type);
}
private long getEntryValueForType(@Nullable NetworkStats.Entry entry, int type) {
if (entry == null) return UNSUPPORTED;
if (!isEntryValueTypeValid(type)) return UNSUPPORTED;
switch (type) {
case TYPE_RX_BYTES:
return entry.rxBytes;
case TYPE_RX_PACKETS:
return entry.rxPackets;
case TYPE_TX_BYTES:
return entry.txBytes;
case TYPE_TX_PACKETS:
return entry.txPackets;
default:
throw new IllegalStateException("Bug: Invalid type: "
+ type + " should not reach here.");
}
}
private boolean isEntryValueTypeValid(int type) {
switch (type) {
case TYPE_RX_BYTES:
case TYPE_RX_PACKETS:
case TYPE_TX_BYTES:
case TYPE_TX_PACKETS:
return true;
default :
return false;
NetworkStats stats = new NetworkStats(0, 0);
if (entry != null) {
stats.insertEntry(entry);
}
return stats;
}
@Nullable
@ -2221,18 +2199,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return entry;
}
@NonNull
@Override
public long getTotalStats(int type) {
if (!isEntryValueTypeValid(type)) return UNSUPPORTED;
public NetworkStats getTypelessTotalStats() {
final NetworkStats.Entry entry;
if (mAlwaysUseTrafficStatsRateLimitCache
|| mDeps.isChangeEnabled(
ENABLE_TRAFFICSTATS_RATE_LIMIT_CACHE, Binder.getCallingUid())) {
final NetworkStats.Entry entry = mTrafficStatsTotalCache.getOrCompute(
entry = mTrafficStatsTotalCache.getOrCompute(
IFACE_ALL, UID_ALL, () -> getTotalStatsInternal());
return getEntryValueForType(entry, type);
}
} else entry = getTotalStatsInternal();
return getEntryValueForType(getTotalStatsInternal(), type);
final NetworkStats stats = new NetworkStats(0, 0);
if (entry != null) {
stats.insertEntry(entry);
}
return stats;
}
@Override

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net
import android.net.TrafficStats.getValueForTypeFromFirstEntry
import android.net.TrafficStats.TYPE_RX_BYTES
import android.net.TrafficStats.UNSUPPORTED
import android.os.Build
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
private const val TEST_IFACE1 = "test_iface1"
@RunWith(DevSdkIgnoreRunner::class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
class TrafficStatsTest {
@Test
fun testGetValueForTypeFromFirstEntry() {
var stats: NetworkStats = NetworkStats(0, 0)
// empty stats
assertEquals(getValueForTypeFromFirstEntry(stats, TYPE_RX_BYTES), UNSUPPORTED.toLong())
// invalid type
stats.insertEntry(TEST_IFACE1, 1, 2, 3, 4)
assertEquals(getValueForTypeFromFirstEntry(stats, 1000), UNSUPPORTED.toLong())
// valid type
assertEquals(getValueForTypeFromFirstEntry(stats, TYPE_RX_BYTES), 1)
}
}

View file

@ -56,6 +56,7 @@ import static android.net.NetworkTemplate.OEM_MANAGED_YES;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.UID_REMOVED;
import static android.net.TrafficStats.UID_TETHERING;
import static android.net.TrafficStats.getValueForTypeFromFirstEntry;
import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_TRAFFICSTATS_RATE_LIMIT_CACHE;
import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID;
import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG;
@ -2514,11 +2515,13 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
private void assertTrafficStatsValues(String iface, int uid, long rxBytes, long rxPackets,
long txBytes, long txPackets) {
assertTrafficStatsValuesThat(rxBytes, rxPackets, txBytes, txPackets,
(type) -> mService.getTotalStats(type));
(type) -> getValueForTypeFromFirstEntry(mService.getTypelessTotalStats(), type));
assertTrafficStatsValuesThat(rxBytes, rxPackets, txBytes, txPackets,
(type) -> mService.getIfaceStats(iface, type));
(type) -> getValueForTypeFromFirstEntry(
mService.getTypelessIfaceStats(iface), type)
);
assertTrafficStatsValuesThat(rxBytes, rxPackets, txBytes, txPackets,
(type) -> mService.getUidStats(uid, type));
(type) -> getValueForTypeFromFirstEntry(mService.getTypelessUidStats(uid), type));
}
private void assertTrafficStatsValuesThat(long rxBytes, long rxPackets, long txBytes,