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

Commit c58131c3 authored by Junyu Lai's avatar Junyu Lai Committed by Automerger Merge Worker
Browse files

Merge "Remove hidden API dependencies from StatsPullAtomService" am:...

Merge "Remove hidden API dependencies from StatsPullAtomService" am: 15d18f70 am: a7f2055a am: f7240d06 am: 7112e246

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1952102

Change-Id: Ib379fb6461cb87f59c5bbf8245bbe035bfc289dd
parents a16704d6 7112e246
Loading
Loading
Loading
Loading
+101 −118
Original line number Diff line number Diff line
@@ -18,9 +18,6 @@ package com.android.server.stats.pull;

import static android.app.AppOpsManager.OP_FLAG_SELF;
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
import static android.app.usage.NetworkStatsManager.FLAG_POLL_FORCE;
import static android.app.usage.NetworkStatsManager.FLAG_POLL_ON_OPEN;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -82,6 +79,7 @@ import android.app.ProcessMemoryState;
import android.app.RuntimeAppOpAccessMessage;
import android.app.StatsManager;
import android.app.StatsManager.PullAtomMetadata;
import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.UidTraffic;
@@ -100,8 +98,6 @@ import android.media.AudioManager;
import android.media.MediaDrm;
import android.media.UnsupportedSchemeException;
import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
import android.net.Network;
import android.net.NetworkRequest;
import android.net.NetworkStats;
@@ -197,6 +193,7 @@ import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.net.module.util.NetworkStatsUtils;
import com.android.role.RoleManagerLocal;
import com.android.server.BinderCallsStatsService;
import com.android.server.LocalManagerRegistry;
@@ -244,7 +241,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * SystemService containing PullAtomCallbacks that are registered with statsd.
@@ -340,6 +337,7 @@ public class StatsPullAtomService extends SystemService {
    private WifiManager mWifiManager;
    private TelephonyManager mTelephony;
    private SubscriptionManager mSubscriptionManager;
    private NetworkStatsManager mNetworkStatsManager;

    @GuardedBy("mKernelWakelockLock")
    private KernelWakelockReader mKernelWakelockReader;
@@ -788,7 +786,7 @@ public class StatsPullAtomService extends SystemService {
                mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
        mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager);
        mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);

        mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class);
        // Initialize DiskIO
        mStoragedUidIoStatsReader = new StoragedUidIoStatsReader();

@@ -981,32 +979,6 @@ public class StatsPullAtomService extends SystemService {
        registerOemManagedBytesTransfer();
    }

    /**
     * Return the {@code INetworkStatsSession} object that holds the necessary properties needed
     * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or
     * null if the service or binder cannot be obtained. Calling this method will trigger poll
     * in NetworkStatsService with once per 15 seconds rate-limit, unless {@code bypassRateLimit}
     * is set to true. This is needed in {@link #getUidNetworkStatsSnapshotForTemplate}, where
     * bypassing the limit is necessary for perfd to supply realtime stats to developers looking at
     * the network usage of their app.
     */
    @Nullable
    private INetworkStatsSession getNetworkStatsSession(boolean bypassRateLimit) {
        final INetworkStatsService networkStatsService =
                INetworkStatsService.Stub.asInterface(
                        ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
        if (networkStatsService == null) return null;

        try {
            return networkStatsService.openSessionForUsageStats(
                    FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN | (bypassRateLimit ? FLAG_POLL_FORCE
                            : FLAG_POLL_ON_OPEN), mContext.getOpPackageName());
        } catch (RemoteException e) {
            Slog.e(TAG, "Cannot get NetworkStats session", e);
            return null;
        }
    }

    private IThermalService getIThermalService() {
        synchronized (mThermalLock) {
            if (mThermalService == null) {
@@ -1137,8 +1109,8 @@ public class StatsPullAtomService extends SystemService {
            case FrameworkStatsLog.WIFI_BYTES_TRANSFER: {
                final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI);
                if (stats != null) {
                    ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI},
                                    /*slicedByFgbg=*/false));
                    ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
                            new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/false));
                }
                break;
            }
@@ -1154,7 +1126,7 @@ public class StatsPullAtomService extends SystemService {
                final NetworkStats stats =
                        getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR);
                if (stats != null) {
                    ret.add(new NetworkStatsExt(stats.groupedByUid(),
                    ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
                                    new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false));
                }
                break;
@@ -1245,23 +1217,19 @@ public class StatsPullAtomService extends SystemService {

    private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret,
            @NonNull NetworkStatsExt statsExt) {
        int size = statsExt.stats.size();
        final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
        for (int j = 0; j < size; j++) {
            statsExt.stats.getValues(j, entry);
        for (NetworkStats.Entry entry : statsExt.stats) {
            StatsEvent statsEvent;

            if (statsExt.slicedByFgbg) {
                // MobileBytesTransferByFgBg atom or WifiBytesTransferByFgBg atom.
                statsEvent = FrameworkStatsLog.buildStatsEvent(
                        atomTag, entry.uid,
                        (entry.set > 0), entry.rxBytes, entry.rxPackets, entry.txBytes,
                        entry.txPackets);
                        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.uid, entry.rxBytes,
                        entry.rxPackets, entry.txBytes, entry.txPackets);
                        atomTag, entry.getUid(), entry.getRxBytes(),
                        entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets());
            }
            ret.add(statsEvent);
        }
@@ -1269,13 +1237,12 @@ public class StatsPullAtomService extends SystemService {

    private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt,
            @NonNull List<StatsEvent> pulledData) {
        final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
        for (int i = 0; i < statsExt.stats.size(); i++) {
            statsExt.stats.getValues(i, entry);
        for (NetworkStats.Entry entry : statsExt.stats) {
            pulledData.add(FrameworkStatsLog.buildStatsEvent(
                    FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.uid,
                    entry.metered == NetworkStats.METERED_YES, entry.tag, entry.rxBytes,
                    entry.rxPackets, entry.txBytes, entry.txPackets));
                    FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.getUid(),
                    entry.getMetered() == NetworkStats.METERED_YES, entry.getTag(),
                    entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(),
                    entry.getTxPackets()));
        }
    }

@@ -1290,12 +1257,11 @@ public class StatsPullAtomService extends SystemService {
        // 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;

        final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
        for (int i = 0; i < statsExt.stats.size(); i++) {
            statsExt.stats.getValues(i, entry);
        for (NetworkStats.Entry entry : statsExt.stats) {
            pulledData.add(FrameworkStatsLog.buildStatsEvent(
                    FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER, entry.set, entry.rxBytes,
                    entry.rxPackets, entry.txBytes, entry.txPackets,
                    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.
@@ -1309,15 +1275,13 @@ public class StatsPullAtomService extends SystemService {

    private void addOemDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt,
            @NonNull List<StatsEvent> pulledData) {
        final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
        final int oemManaged = statsExt.oemManaged;
        for (final int transport : statsExt.transports) {
            for (int i = 0; i < statsExt.stats.size(); i++) {
                statsExt.stats.getValues(i, entry);
            for (NetworkStats.Entry entry : statsExt.stats) {
                pulledData.add(FrameworkStatsLog.buildStatsEvent(
                        FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.uid, (entry.set > 0),
                        oemManaged, transport, entry.rxBytes, entry.rxPackets, entry.txBytes,
                        entry.txPackets));
                        FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.getUid(),
                        (entry.getSet() > 0), oemManaged, transport, entry.getRxBytes(),
                        entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()));
            }
        }
    }
@@ -1385,22 +1349,32 @@ public class StatsPullAtomService extends SystemService {
        final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro());
        final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(),
                NETSTATS_UID_BUCKET_DURATION, NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS);
        try {

        // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats
        //  history when query in every second in order to show realtime statistics. However,
        //  this is not a good long-term solution since NetworkStatsService will make frequent
        //  I/O and also block main thread when polling.
        //  Consider making perfd queries NetworkStatsService directly.
            final NetworkStats stats = getNetworkStatsSession(template.getMatchRule()
                    == NetworkTemplate.MATCH_WIFI_WILDCARD).getSummaryForAllUid(template,
                    currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
                    currentTimeInMillis, includeTags);
            return stats;
        } catch (RemoteException | NullPointerException e) {
            Slog.e(TAG, "Pulling netstats for template=" + template + " and includeTags="
                    + includeTags  + " causes error", e);
        if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) {
            mNetworkStatsManager.forceUpdate();
        }
        return null;

        final android.app.usage.NetworkStats queryNonTaggedStats =
                mNetworkStatsManager.querySummary(
                template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
                currentTimeInMillis);

        final NetworkStats nonTaggedStats =
                NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats);
        if (!includeTags) return nonTaggedStats;

        final android.app.usage.NetworkStats quaryTaggedStats =
                mNetworkStatsManager.queryTaggedSummary(template,
                currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
                currentTimeInMillis);
        final NetworkStats taggedStats =
                NetworkStatsUtils.fromPublicNetworkStats(quaryTaggedStats);
        return nonTaggedStats.add(taggedStats);
    }

    @NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSub(
@@ -1424,27 +1398,51 @@ public class StatsPullAtomService extends SystemService {
        return ret;
    }

    @NonNull private NetworkStats sliceNetworkStatsByUid(@NonNull NetworkStats stats) {
        return sliceNetworkStats(stats,
                (entry) -> {
                        return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
                                NetworkStats.SET_ALL, NetworkStats.TAG_NONE,
                                NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
                                NetworkStats.DEFAULT_NETWORK_ALL,
                                entry.getRxBytes(), entry.getRxPackets(),
                                entry.getTxBytes(), entry.getTxPackets(), 0);
                });
    }

    @NonNull private NetworkStats sliceNetworkStatsByFgbg(@NonNull NetworkStats stats) {
        return sliceNetworkStats(stats,
                (newEntry, oldEntry) -> {
                    newEntry.set = oldEntry.set;
                (entry) -> {
                        return new NetworkStats.Entry(null /* IFACE_ALL */, NetworkStats.UID_ALL,
                                entry.getSet(), NetworkStats.TAG_NONE,
                                NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
                                NetworkStats.DEFAULT_NETWORK_ALL,
                                entry.getRxBytes(), entry.getRxPackets(),
                                entry.getTxBytes(), entry.getTxPackets(), 0);
                });
    }

    @NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) {
        return sliceNetworkStats(stats,
                (newEntry, oldEntry) -> {
                    newEntry.uid = oldEntry.uid;
                    newEntry.set = oldEntry.set;
                (entry) -> {
                        return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
                                entry.getSet(), NetworkStats.TAG_NONE,
                                NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
                                NetworkStats.DEFAULT_NETWORK_ALL,
                                entry.getRxBytes(), entry.getRxPackets(),
                                entry.getTxBytes(), entry.getTxPackets(), 0);
                });
    }

    @NonNull private NetworkStats sliceNetworkStatsByUidTagAndMetered(@NonNull NetworkStats stats) {
        return sliceNetworkStats(stats,
                (newEntry, oldEntry) -> {
                    newEntry.uid = oldEntry.uid;
                    newEntry.tag = oldEntry.tag;
                    newEntry.metered = oldEntry.metered;
                (entry) -> {
                        return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
                                NetworkStats.SET_ALL, entry.getTag(),
                                entry.getMetered(), NetworkStats.ROAMING_ALL,
                                NetworkStats.DEFAULT_NETWORK_ALL,
                                entry.getRxBytes(), entry.getRxPackets(),
                                entry.getTxBytes(), entry.getTxPackets(), 0);
                });
    }

@@ -1454,46 +1452,31 @@ public class StatsPullAtomService extends SystemService {
     *
     * This function iterates through each NetworkStats.Entry, sets its dimensions equal to the
     * default state (with the presumption that we don't want to slice on anything), and then
     * applies the slicer lambda to allow users to control which dimensions to slice on. This is
     * adapted from groupedByUid within NetworkStats.java
     * applies the slicer lambda to allow users to control which dimensions to slice on.
     *
     * @param slicer An operation taking into two parameters, new NetworkStats.Entry and old
     *               NetworkStats.Entry, that should be used to copy state from the old to the new.
     * @param slicer An operation taking one parameter, NetworkStats.Entry, that should be used to
     *               get the state from entry to replace the default value.
     *               This is useful for slicing by particular dimensions. For example, if we wished
     *               to slice by uid and tag, we could write the following lambda:
     *                  (new, old) -> {
     *                          new.uid = old.uid;
     *                          new.tag = old.tag;
     *                  (entry) -> {
     *                   return new NetworkStats.Entry(null, entry.getUid(),
     *                           NetworkStats.SET_ALL, entry.getTag(),
     *                           NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
     *                           NetworkStats.DEFAULT_NETWORK_ALL,
     *                           entry.getRxBytes(), entry.getRxPackets(),
     *                           entry.getTxBytes(), entry.getTxPackets(), 0);
     *                  }
     *               If no slicer is provided, the data is not sliced by any dimensions.
     * @return new NeworkStats object appropriately sliced
     */
    @NonNull private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats,
            @Nullable BiConsumer<NetworkStats.Entry, NetworkStats.Entry> slicer) {
        final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1);

        final NetworkStats.Entry entry = new NetworkStats.Entry();
        entry.uid = NetworkStats.UID_ALL;
        entry.iface = NetworkStats.IFACE_ALL;
        entry.set = NetworkStats.SET_ALL;
        entry.tag = NetworkStats.TAG_NONE;
        entry.metered = NetworkStats.METERED_ALL;
        entry.roaming = NetworkStats.ROAMING_ALL;
        entry.defaultNetwork = NetworkStats.DEFAULT_NETWORK_ALL;

        final NetworkStats.Entry recycle = new NetworkStats.Entry(); // used for retrieving values
        for (int i = 0; i < stats.size(); i++) {
            stats.getValues(i, recycle);
            @NonNull Function<NetworkStats.Entry, NetworkStats.Entry> slicer) {
        NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1);
        NetworkStats.Entry entry = new NetworkStats.Entry();
        for (NetworkStats.Entry e : stats) {
            if (slicer != null) {
                slicer.accept(entry, recycle);
                entry = slicer.apply(e);
            }

            entry.rxBytes = recycle.rxBytes;
            entry.rxPackets = recycle.rxPackets;
            entry.txBytes = recycle.txBytes;
            entry.txPackets = recycle.txPackets;
            // Operations purposefully omitted since we don't use them for statsd.
            ret.combineValues(entry);
            ret = ret.addEntry(entry);
        }
        return ret;
    }