Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee3d3b88 authored by Chris Weir's avatar Chris Weir
Browse files

Add Ethernet and Satellite Metrics

Adding metrics to track Ethernet and Satellite data usage.

The com.android.net.flags.netstats_transport_type flag in the
Connectivity module should be enabled before enabling the
com.android.server.stats.netstats_use_transport_type flag added here.

Flag: com.android.server.stats.netstats_use_transport_type
Bug:420531377
Test: build
Test: statsd_testdrive 10249
Test: for seahawk,set the ConnectivityOverlay's
config_ethernet_interfaces transport override type to "10" (satellite),
then run statsd_testdrive 10250
Test: BytesTransferredTest

Change-Id: I7364bd2986c8b97c9e9efd836b95df3b81bbe844
parent 0c4e4345
Loading
Loading
Loading
Loading
+145 −82
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static android.hardware.graphics.common.Hdr.DOLBY_VISION;
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_SATELLITE;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkStats.METERED_YES;
import static android.net.NetworkTemplate.MATCH_ETHERNET;
@@ -62,10 +63,12 @@ import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__SOFTWARE_SHORTCUT_TYPE__UNKNOWN_TYPE;
import static com.android.internal.util.FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__NOT_OPPORTUNISTIC;
import static com.android.internal.util.FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__OPPORTUNISTIC;
import static com.android.internal.util.FrameworkStatsLog.ETHERNET_BYTES_TRANSFER;
import static com.android.internal.util.FrameworkStatsLog.PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_CPU;
import static com.android.internal.util.FrameworkStatsLog.PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_IO;
import static com.android.internal.util.FrameworkStatsLog.PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_MEMORY;
import static com.android.internal.util.FrameworkStatsLog.PRESSURE_STALL_INFORMATION__PSI_RESOURCE__PSI_RESOURCE_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.SATELLITE_BYTES_TRANSFER;
import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__GEO;
import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__MANUAL;
import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__TELEPHONY;
@@ -77,6 +80,7 @@ import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHe
import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
import static com.android.server.stats.pull.netstats.NetworkStatsUtils.fromPublicNetworkStats;
import static com.android.server.stats.pull.netstats.NetworkStatsUtils.isAddEntriesSupported;
import static com.android.server.stats.pull.netstats.NetworkStatsUtils.isTransportTypeSupported;

import static libcore.io.IoUtils.closeQuietly;

@@ -577,6 +581,8 @@ public class StatsPullAtomService extends SystemService {
                    case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
                    case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER:
                    case FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER:
                    case ETHERNET_BYTES_TRANSFER:
                    case SATELLITE_BYTES_TRANSFER:
                        synchronized (mDataBytesTransferLock) {
                            return pullDataBytesTransferLocked(atomTag, data);
                        }
@@ -1127,6 +1133,12 @@ public class StatsPullAtomService extends SystemService {
                mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtomLocked(
                        FrameworkStatsLog.PROXY_BYTES_TRANSFER_BY_FG_BG));
            }
            if (isTransportTypeSupported()) {
                mNetworkStatsBaselines.addAll(
                        collectNetworkStatsSnapshotForAtomLocked(ETHERNET_BYTES_TRANSFER));
                mNetworkStatsBaselines.addAll(
                        collectNetworkStatsSnapshotForAtomLocked(SATELLITE_BYTES_TRANSFER));
            }
        }

        // Listen to subscription changes to record historical subscriptions that activated before
@@ -1148,6 +1160,10 @@ public class StatsPullAtomService extends SystemService {
        if (canQueryTypeProxy) {
            registerProxyBytesTransferBackground();
        }
        if (isTransportTypeSupported()) {
            registerEthernetBytesTransfer();
            registerSatelliteBytesTransfer();
        }
    }

    private void registerMobileBytesTransferByProcState() {
@@ -1317,28 +1333,30 @@ public class StatsPullAtomService extends SystemService {
        switch (atomTag) {
            case FrameworkStatsLog.WIFI_BYTES_TRANSFER: {
                final NetworkStats stats = getUidNetworkStatsSnapshotForTransportLocked(
                        TRANSPORT_WIFI);
                        TRANSPORT_WIFI, /*includeTags=*/false);
                ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
                        new int[]{TRANSPORT_WIFI}, /*slicedByFgbg=*/false));
                break;
            }
            case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: {
                final NetworkStats stats = getUidNetworkStatsSnapshotForTransportLocked(
                        TRANSPORT_WIFI);
                        TRANSPORT_WIFI, /*includeTags=*/false);
                ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
                        new int[]{TRANSPORT_WIFI}, /*slicedByFgbg=*/true));
                break;
            }
            case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: {
                final NetworkStats stats =
                        getUidNetworkStatsSnapshotForTransportLocked(TRANSPORT_CELLULAR);
                        getUidNetworkStatsSnapshotForTransportLocked(TRANSPORT_CELLULAR,
                                /*includeTags=*/false);
                ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
                        new int[]{TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false));
                break;
            }
            case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: {
                final NetworkStats stats =
                        getUidNetworkStatsSnapshotForTransportLocked(TRANSPORT_CELLULAR);
                        getUidNetworkStatsSnapshotForTransportLocked(TRANSPORT_CELLULAR,
                                /*includeTags=*/false);
                ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
                        new int[]{TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true));
                break;
@@ -1377,6 +1395,22 @@ public class StatsPullAtomService extends SystemService {
                ret.addAll(getDataUsageBytesTransferSnapshotForOemManagedLocked());
                break;
            }
            case ETHERNET_BYTES_TRANSFER:
            case SATELLITE_BYTES_TRANSFER: {
                if (!isTransportTypeSupported()) {
                    Log.wtf(TAG, "Ethernet/Satellite case reached without flag enabled!");
                    break;
                }
                final int transportType = (atomTag == SATELLITE_BYTES_TRANSFER)
                        ? TRANSPORT_SATELLITE : TRANSPORT_ETHERNET;
                final NetworkStats stats = getUidNetworkStatsSnapshotForTransportLocked(
                        transportType, /*includeTags=*/true);
                ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
                        new int[]{transportType}, /*slicedByFgbg=*/true, /*slicedByTag=*/true,
                        /*slicedByMetered=*/true, TelephonyManager.NETWORK_TYPE_UNKNOWN,
                        /*subInfo=*/null, OEM_MANAGED_ALL, /*isTypeProxy=*/false));
                break;
            }
            default:
                throw new IllegalArgumentException("Unknown atomTag " + atomTag);
        }
@@ -1411,20 +1445,8 @@ public class StatsPullAtomService extends SystemService {
            // If no diff, skip.
            if (!diff.stats.iterator().hasNext()) continue;

            switch (atomTag) {
                case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
                    addBytesTransferByTagAndMeteredAtoms(diff, pulledData);
                    break;
                case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER:
                    addDataUsageBytesTransferAtoms(diff, pulledData);
                    break;
                case FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER:
                    addOemDataUsageBytesTransferAtoms(diff, pulledData);
                    break;
                default:
            addNetworkStats(atomTag, pulledData, diff);
        }
        }
        return StatsManager.PULL_SUCCESS;
    }

@@ -1448,35 +1470,39 @@ public class StatsPullAtomService extends SystemService {
        }
    }

    private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret,
            @NonNull NetworkStatsExt statsExt) {
        for (NetworkStats.Entry entry : statsExt.stats) {
            StatsEvent statsEvent;
            if (statsExt.slicedByFgbg) {
                // MobileBytesTransferByFgBg atom or WifiBytesTransferByFgBg atom.
                statsEvent = FrameworkStatsLog.buildStatsEvent(
                        atomTag, entry.getUid(),
                        (entry.getSet() > 0), entry.getRxBytes(), entry.getRxPackets(),
                        entry.getTxBytes(), entry.getTxPackets());
            } else {
                // MobileBytesTransfer atom or WifiBytesTransfer atom.
                statsEvent = FrameworkStatsLog.buildStatsEvent(
                        atomTag, entry.getUid(), entry.getRxBytes(),
                        entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets());
            }
            ret.add(statsEvent);
        }
    // absurdly long lines don't fit in addNetworkStats.
    private int subInfoisOpportunistic(SubInfo subInfo) {
        return subInfo.isOpportunistic
                ? DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__OPPORTUNISTIC
                : DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__NOT_OPPORTUNISTIC;
    }

    private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt,
            @NonNull List<StatsEvent> pulledData) {
    private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> pulledData,
            @NonNull NetworkStatsExt statsExt) {
        final int oemManaged = statsExt.oemManaged;
        // Workaround for 5G NSA mode, see {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
        // 5G NSA mode means the primary cell is LTE with a secondary connection to an
        // NR cell. To mitigate risk, NetworkStats is currently storing this state as
        // a fake RAT type rather than storing the boolean separately.
        final boolean is5GNsa = statsExt.ratType == NetworkStatsManager.NETWORK_TYPE_5G_NSA;
        // Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with.
        final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR;

        if (atomTag == FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER) {
            for (final int transport : statsExt.transports) {
                for (NetworkStats.Entry entry : statsExt.stats) {
                    pulledData.add(FrameworkStatsLog.buildStatsEvent(
                            FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.getUid(),
                            (entry.getSet() > 0), oemManaged, transport, entry.getRxBytes(),
                            entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()));
                }
            }
            return;
        }

        for (NetworkStats.Entry entry : statsExt.stats) {
            switch (atomTag) {
                case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED -> {
                    pulledData.add(FrameworkStatsLog.buildStatsEvent(
                            FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.getUid(),
                            entry.getMetered() == NetworkStats.METERED_YES, entry.getTag(),
@@ -1484,45 +1510,47 @@ public class StatsPullAtomService extends SystemService {
                            entry.getTxPackets(),
                            is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType));
                }
    }

    private void addDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt,
            @NonNull List<StatsEvent> pulledData) {

        // Workaround for 5G NSA mode, see {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
        // 5G NSA mode means the primary cell is LTE with a secondary connection to an
        // NR cell. To mitigate risk, NetworkStats is currently storing this state as
        // a fake RAT type rather than storing the boolean separately.
        final boolean is5GNsa = statsExt.ratType == NetworkStatsManager.NETWORK_TYPE_5G_NSA;
        // Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with.
        final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR;

        for (NetworkStats.Entry entry : statsExt.stats) {
                case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER -> {
                    pulledData.add(FrameworkStatsLog.buildStatsEvent(
                            FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER,
                            entry.getSet(), entry.getRxBytes(), entry.getRxPackets(),
                            entry.getTxBytes(), entry.getTxPackets(),
                            is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType,
                    // Fill information about subscription, these cannot be null since invalid data
                    // would be filtered when adding into subInfo list.
                            // Fill information about subscription, these cannot be null since
                            // invalid data would be filtered when adding into subInfo list.
                            statsExt.subInfo.mcc, statsExt.subInfo.mnc, statsExt.subInfo.carrierId,
                    statsExt.subInfo.isOpportunistic
                            ? DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__OPPORTUNISTIC
                            : DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__NOT_OPPORTUNISTIC,
                    isNR));
                            subInfoisOpportunistic(statsExt.subInfo), isNR));
                }
                case SATELLITE_BYTES_TRANSFER, ETHERNET_BYTES_TRANSFER -> {
                    if (!isTransportTypeSupported()) {
                        Log.wtf(TAG,
                                "addNetworkStats for Satellite/Ethernet without flag enabled!");
                        return;
                    }

    private void addOemDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt,
            @NonNull List<StatsEvent> pulledData) {
        final int oemManaged = statsExt.oemManaged;
        for (final int transport : statsExt.transports) {
            for (NetworkStats.Entry entry : statsExt.stats) {
                pulledData.add(FrameworkStatsLog.buildStatsEvent(
                        FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.getUid(),
                        (entry.getSet() > 0), oemManaged, transport, entry.getRxBytes(),
                    if (UserHandle.isIsolated(entry.getUid())) {
                        // Skip individual isolated uids because they are recycled and quickly
                        // removed from the underlying data source.
                        continue;
                    }
                    pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, entry.getUid(),
                            entry.getTag(), entry.getMetered() == NetworkStats.METERED_YES,
                            entry.getSet() == NetworkStats.SET_FOREGROUND, entry.getRxBytes(),
                            entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()));
                }
                case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG,
                        FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG -> {
                    pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, entry.getUid(),
                                (entry.getSet() > 0), entry.getRxBytes(), entry.getRxPackets(),
                                entry.getTxBytes(), entry.getTxPackets()));
                }
                case FrameworkStatsLog.MOBILE_BYTES_TRANSFER,
                        FrameworkStatsLog.WIFI_BYTES_TRANSFER -> {
                    pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, entry.getUid(),
                            entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(),
                            entry.getTxPackets()));
                }
                default -> Slog.e(TAG, "unexpected atom passed to addNetworkStats: " + atomTag);
            }
        }
    }

@@ -1565,7 +1593,8 @@ public class StatsPullAtomService extends SystemService {
     */
    @GuardedBy("mDataBytesTransferLock")
    @NonNull
    private NetworkStats getUidNetworkStatsSnapshotForTransportLocked(int transport) {
    private NetworkStats getUidNetworkStatsSnapshotForTransportLocked(int transport,
            boolean includeTags) {
        NetworkTemplate template = null;
        switch (transport) {
            case TRANSPORT_CELLULAR:
@@ -1575,10 +1604,18 @@ public class StatsPullAtomService extends SystemService {
            case TRANSPORT_WIFI:
                template = new NetworkTemplate.Builder(MATCH_WIFI).build();
                break;
            case TRANSPORT_ETHERNET:
            case TRANSPORT_SATELLITE:
                if (!isTransportTypeSupported()) {
                    Log.wtf(TAG, "Attempted to call setTransportType without flag enabled!");
                    break;
                }
                template =  new NetworkTemplate.Builder().setTransportType(transport).build();
                break;
            default:
                Log.wtf(TAG, "Unexpected transport.");
        }
        return getUidNetworkStatsSnapshotForTemplateLocked(template, /*includeTags=*/false);
        return getUidNetworkStatsSnapshotForTemplateLocked(template, includeTags);
    }

    /**
@@ -1884,6 +1921,32 @@ public class StatsPullAtomService extends SystemService {
        );
    }

    private void registerEthernetBytesTransfer() {
        int tagId = ETHERNET_BYTES_TRANSFER;
        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                .setAdditiveFields(new int[]{5, 6, 7, 8})
                .build();
        mStatsManager.setPullAtomCallback(
                tagId,
                metadata,
                DIRECT_EXECUTOR,
                mStatsCallbackImpl
        );
    }

    private void registerSatelliteBytesTransfer() {
        int tagId = SATELLITE_BYTES_TRANSFER;
        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                .setAdditiveFields(new int[]{5, 6, 7, 8})
                .build();
        mStatsManager.setPullAtomCallback(
                tagId,
                metadata,
                DIRECT_EXECUTOR,
                mStatsCallbackImpl
        );
    }

    private void registerBluetoothBytesTransfer() {
        int tagId = FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER;
        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
+4 −0
Original line number Diff line number Diff line
@@ -122,4 +122,8 @@ public class NetworkStatsUtils {
    public static boolean isAddEntriesSupported() {
        return Flags.netstatsUseAddEntries();
    }

    public static boolean isTransportTypeSupported() {
        return Flags.netstatsUseTransportType();
    }
}
+11 −0
Original line number Diff line number Diff line
package: "com.android.server.stats"
container: "system"

# This flag exists as the statsd counterpart to com.android.net.flags.netstats_transport_type,
# which is only available in the Connectivity module. This flag should not be enabled without first
# enabling the com.android.net.flags.netstats_transport_type flag.
flag {
    name: "netstats_use_transport_type"
    namespace: "statsd"
    description: "Use NetworkTemplate#setTransportType API instead of matchers"
    bug: "420531377"
    is_fixed_read_only: true
}

# Note: To ensure compatibility across all release configurations, initiate the ramp-up process
# only after the 'com.android.net.flags.netstats_add_entries' flag has been fully deployed.
# This flag provides the necessary API from the Connectivity module.