From ee3ea79c3811a6d8d801b24b769f4fef9dacddf6 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 15 May 2020 18:26:25 +0800 Subject: [PATCH 1/3] [SM14] Create new puller for reporting data usage per rat Test: adb shell cmd stats pull-source 10082, 10000~10003 Test: atest UidAtomTests#testMobileBytesTransfer \ UidAtomTests#testMobileBytesTransferByFgBg \ UidAtomTests#testDataUsageBytesTransfer Bug: 129082217 Change-Id: If9948e37980e9de342f84e5fde3088fac7f36a15 Change-Id: I7d3931c3b10e377abdf1ab6fcb67100dcdf1f96d --- .../stats/pull/StatsPullAtomService.java | 131 ++++++++++++++---- 1 file changed, 104 insertions(+), 27 deletions(-) diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index 0b3254f53324c..643bf44acd59b 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -24,6 +24,10 @@ import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; +import static android.net.NetworkTemplate.buildTemplateMobileWildcard; +import static android.net.NetworkTemplate.buildTemplateMobileWithRatType; +import static android.net.NetworkTemplate.buildTemplateWifiWildcard; +import static android.net.NetworkTemplate.getAllCollapsedRatTypes; import static android.os.Debug.getIonHeapsSizeKb; import static android.os.Process.getUidForPid; import static android.os.storage.VolumeInfo.TYPE_PRIVATE; @@ -327,6 +331,7 @@ public class StatsPullAtomService extends SystemService { case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: + case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER: return pullDataBytesTransfer(atomTag, data); case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER: return pullBluetoothBytesTransfer(atomTag, data); @@ -645,12 +650,15 @@ public class StatsPullAtomService extends SystemService { FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG)); mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtom( FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED)); + mNetworkStatsBaselines.addAll( + collectNetworkStatsSnapshotForAtom(FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER)); registerWifiBytesTransfer(); registerWifiBytesTransferBackground(); registerMobileBytesTransfer(); registerMobileBytesTransferBackground(); registerBytesTransferByTagAndMetered(); + registerDataUsageBytesTransfer(); } /** @@ -796,13 +804,15 @@ public class StatsPullAtomService extends SystemService { public final boolean slicedByFgbg; public final boolean slicedByTag; public final boolean slicedByMetered; + public final int ratType; NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg) { - this(stats, transports, slicedByFgbg, /*slicedByTag=*/false, /*slicedByMetered=*/false); + this(stats, transports, slicedByFgbg, /*slicedByTag=*/false, /*slicedByMetered=*/false, + TelephonyManager.NETWORK_TYPE_UNKNOWN); } NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg, - boolean slicedByTag, boolean slicedByMetered) { + boolean slicedByTag, boolean slicedByMetered, int ratType) { this.stats = stats; // Sort transports array so that we can test for equality without considering order. @@ -812,11 +822,13 @@ public class StatsPullAtomService extends SystemService { this.slicedByFgbg = slicedByFgbg; this.slicedByTag = slicedByTag; this.slicedByMetered = slicedByMetered; + this.ratType = ratType; } public boolean hasSameSlicing(@NonNull NetworkStatsExt other) { return Arrays.equals(transports, other.transports) && slicedByFgbg == other.slicedByFgbg - && slicedByTag == other.slicedByTag && slicedByMetered == other.slicedByMetered; + && slicedByTag == other.slicedByTag && slicedByMetered == other.slicedByMetered + && ratType == other.ratType; } } @@ -825,8 +837,7 @@ public class StatsPullAtomService extends SystemService { List ret = new ArrayList<>(); switch(atomTag) { case FrameworkStatsLog.WIFI_BYTES_TRANSFER: { - final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_WIFI, - /*includeTags=*/false); + final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI); if (stats != null) { ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/false)); @@ -834,8 +845,7 @@ public class StatsPullAtomService extends SystemService { break; } case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: { - final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_WIFI, - /*includeTags=*/false); + final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI); if (stats != null) { ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats), new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/true)); @@ -843,8 +853,8 @@ public class StatsPullAtomService extends SystemService { break; } case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: { - final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_CELLULAR, - /*includeTags=*/false); + final NetworkStats stats = + getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR); if (stats != null) { ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false)); @@ -852,8 +862,8 @@ public class StatsPullAtomService extends SystemService { break; } case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: { - final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_CELLULAR, - /*includeTags=*/false); + final NetworkStats stats = + getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR); if (stats != null) { ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats), new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true)); @@ -861,16 +871,29 @@ public class StatsPullAtomService extends SystemService { break; } case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: { - final NetworkStats wifiStats = getUidNetworkStatsSnapshot(TRANSPORT_WIFI, - /*includeTags=*/true); - final NetworkStats cellularStats = getUidNetworkStatsSnapshot(TRANSPORT_CELLULAR, - /*includeTags=*/true); + final NetworkStats wifiStats = getUidNetworkStatsSnapshotForTemplate( + buildTemplateWifiWildcard(), /*includeTags=*/true); + final NetworkStats cellularStats = getUidNetworkStatsSnapshotForTemplate( + buildTemplateMobileWildcard(), /*includeTags=*/true); if (wifiStats != null && cellularStats != null) { final NetworkStats stats = wifiStats.add(cellularStats); ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats), - new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR}, - /*slicedByFgbg=*/false, /*slicedByTag=*/true, - /*slicedByMetered=*/true)); + new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR}, + /*slicedByFgbg=*/false, /*slicedByTag=*/true, + /*slicedByMetered=*/true, TelephonyManager.NETWORK_TYPE_UNKNOWN)); + } + break; + } + case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER: { + for (final int ratType : getAllCollapsedRatTypes()) { + final NetworkTemplate template = buildTemplateMobileWithRatType(null, ratType); + final NetworkStats stats = + getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false); + if (stats != null) { + ret.add(new NetworkStatsExt(sliceNetworkStatsByFgbg(stats), + new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true, + /*slicedByTag=*/false, /*slicedByMetered=*/false, ratType)); + } } break; } @@ -901,7 +924,7 @@ public class StatsPullAtomService extends SystemService { } final NetworkStatsExt diff = new NetworkStatsExt( item.stats.subtract(baseline.stats).removeEmptyEntries(), item.transports, - item.slicedByFgbg, item.slicedByTag, item.slicedByMetered); + item.slicedByFgbg, item.slicedByTag, item.slicedByMetered, item.ratType); // If no diff, skip. if (diff.stats.size() == 0) continue; @@ -910,6 +933,9 @@ public class StatsPullAtomService extends SystemService { case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: addBytesTransferByTagAndMeteredAtoms(diff, pulledData); break; + case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER: + addDataUsageBytesTransferAtoms(diff, pulledData); + break; default: addNetworkStats(atomTag, pulledData, diff); } @@ -966,18 +992,49 @@ public class StatsPullAtomService extends SystemService { } } + private void addDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt, + @NonNull List pulledData) { + final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling + for (int i = 0; i < statsExt.stats.size(); i++) { + statsExt.stats.getValues(i, entry); + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER) + .addBooleanAnnotation(ANNOTATION_ID_TRUNCATE_TIMESTAMP, true) + .writeInt(entry.set) + .writeLong(entry.rxBytes) + .writeLong(entry.rxPackets) + .writeLong(entry.txBytes) + .writeLong(entry.txPackets) + .writeInt(statsExt.ratType) + // TODO: Fill information about subscription. + .writeString(/*sim_mcc=*/null) + .writeString(/*sim_mnc=*/null) + .writeInt(/*carrier_id=*/0) + .writeInt(/*opportunistic_data_sub=*/0) + .build(); + pulledData.add(e); + } + } + /** - * Create a snapshot of NetworkStats since boot, but add 1 bucket duration before boot as a - * buffer to ensure at least one full bucket will be included. + * Create a snapshot of NetworkStats for a given transport. + */ + @Nullable private NetworkStats getUidNetworkStatsSnapshotForTransport(int transport) { + final NetworkTemplate template = (transport == TRANSPORT_CELLULAR) + ? NetworkTemplate.buildTemplateMobileWithRatType( + /*subscriptionId=*/null, NETWORK_TYPE_ALL) + : NetworkTemplate.buildTemplateWifiWildcard(); + return getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false); + } + + /** + * Create a snapshot of NetworkStats since boot for the given template, but add 1 bucket + * duration before boot as a buffer to ensure at least one full bucket will be included. * Note that this should be only used to calculate diff since the snapshot might contains * some traffic before boot. */ - @Nullable private NetworkStats getUidNetworkStatsSnapshot(int transport, boolean includeTags) { - final NetworkTemplate template = (transport == TRANSPORT_CELLULAR) - ? NetworkTemplate.buildTemplateMobileWithRatType( - /*subscriptionId=*/null, NETWORK_TYPE_ALL) - : NetworkTemplate.buildTemplateWifiWildcard(); - + @Nullable private NetworkStats getUidNetworkStatsSnapshotForTemplate( + @NonNull NetworkTemplate template, boolean includeTags) { final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime(); final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro()); final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(), @@ -994,6 +1051,13 @@ public class StatsPullAtomService extends SystemService { return null; } + @NonNull private NetworkStats sliceNetworkStatsByFgbg(@NonNull NetworkStats stats) { + return sliceNetworkStats(stats, + (newEntry, oldEntry) -> { + newEntry.set = oldEntry.set; + }); + } + @NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (newEntry, oldEntry) -> { @@ -1113,6 +1177,19 @@ public class StatsPullAtomService extends SystemService { ); } + private void registerDataUsageBytesTransfer() { + int tagId = FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER; + PullAtomMetadata metadata = new PullAtomMetadata.Builder() + .setAdditiveFields(new int[] {2, 3, 4, 5}) + .build(); + mStatsManager.setPullAtomCallback( + tagId, + metadata, + BackgroundThread.getExecutor(), + mStatsCallbackImpl + ); + } + private void registerBluetoothBytesTransfer() { int tagId = FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER; PullAtomMetadata metadata = new PullAtomMetadata.Builder() From aa31d3cb11526f5af572f9a6f9f9637ad0f6d4f0 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 10 Apr 2020 15:11:54 +0800 Subject: [PATCH 2/3] [SM16] Collect metrics per subscription Test: adb shell cmd stats pull-source 10082 Test: atest UidAtomTests#testMobileBytesTransfer \ UidAtomTests#testMobileBytesTransferByFgBg \ UidAtomTests#testDataUsageBytesTransfer Bug: 148905838 Change-Id: Icc27f6314f8c6eed2ede0500dd0257ea97a13332 --- .../stats/pull/StatsPullAtomService.java | 122 +++++++++++++++--- .../server/stats/pull/netstats/SubInfo.java | 66 ++++++++++ 2 files changed, 169 insertions(+), 19 deletions(-) create mode 100644 services/core/java/com/android/server/stats/pull/netstats/SubInfo.java diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index 643bf44acd59b..927f036abab5b 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -33,12 +33,15 @@ import static android.os.Process.getUidForPid; import static android.os.storage.VolumeInfo.TYPE_PRIVATE; import static android.os.storage.VolumeInfo.TYPE_PUBLIC; import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION; +import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID; import static android.util.MathUtils.abs; import static android.util.MathUtils.constrain; import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID; import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_TRUNCATE_TIMESTAMP; +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.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs; import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs; @@ -112,7 +115,10 @@ import android.provider.DeviceConfig; import android.provider.Settings; import android.stats.storage.StorageEnums; import android.telephony.ModemActivityInfo; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -154,6 +160,7 @@ import com.android.server.notification.NotificationManagerService; import com.android.server.role.RoleManagerInternal; import com.android.server.stats.pull.IonMemoryUtil.IonAllocations; import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot; +import com.android.server.stats.pull.netstats.SubInfo; import com.android.server.storage.DiskStatsFileLogger; import com.android.server.storage.DiskStatsLoggingService; @@ -175,10 +182,12 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.MissingResourceException; +import java.util.Objects; import java.util.Random; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; @@ -269,6 +278,7 @@ public class StatsPullAtomService extends SystemService { private StorageManager mStorageManager; private WifiManager mWifiManager; private TelephonyManager mTelephony; + private SubscriptionManager mSubscriptionManager; private KernelWakelockReader mKernelWakelockReader; private KernelWakelockStats mTmpWakelockStats; @@ -304,6 +314,11 @@ public class StatsPullAtomService extends SystemService { @NonNull private final List mNetworkStatsBaselines = new ArrayList<>(); + // Listener for monitoring subscriptions changed event. + private StatsSubscriptionsListener mStatsSubscriptionsListener; + // List that store SubInfo of subscriptions that ever appeared since boot. + private final CopyOnWriteArrayList mHistoricalSubs = new CopyOnWriteArrayList<>(); + public StatsPullAtomService(Context context) { super(context); mContext = context; @@ -484,6 +499,9 @@ public class StatsPullAtomService extends SystemService { mStatsManager = (StatsManager) mContext.getSystemService(Context.STATS_MANAGER); mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); mTelephony = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + mSubscriptionManager = (SubscriptionManager) + mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); + mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager); mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class); // Initialize DiskIO @@ -653,6 +671,11 @@ public class StatsPullAtomService extends SystemService { mNetworkStatsBaselines.addAll( collectNetworkStatsSnapshotForAtom(FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER)); + // Listen to subscription changes to record historical subscriptions that activated before + // pulling, this is used by {@link #pullMobileBytesTransfer}. + mSubscriptionManager.addOnSubscriptionsChangedListener( + BackgroundThread.getExecutor(), mStatsSubscriptionsListener); + registerWifiBytesTransfer(); registerWifiBytesTransferBackground(); registerMobileBytesTransfer(); @@ -805,14 +828,17 @@ public class StatsPullAtomService extends SystemService { public final boolean slicedByTag; public final boolean slicedByMetered; public final int ratType; + @Nullable + public final SubInfo subInfo; NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg) { this(stats, transports, slicedByFgbg, /*slicedByTag=*/false, /*slicedByMetered=*/false, - TelephonyManager.NETWORK_TYPE_UNKNOWN); + TelephonyManager.NETWORK_TYPE_UNKNOWN, /*subInfo=*/null); } NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg, - boolean slicedByTag, boolean slicedByMetered, int ratType) { + boolean slicedByTag, boolean slicedByMetered, int ratType, + @Nullable SubInfo subInfo) { this.stats = stats; // Sort transports array so that we can test for equality without considering order. @@ -823,12 +849,13 @@ public class StatsPullAtomService extends SystemService { this.slicedByTag = slicedByTag; this.slicedByMetered = slicedByMetered; this.ratType = ratType; + this.subInfo = subInfo; } public boolean hasSameSlicing(@NonNull NetworkStatsExt other) { return Arrays.equals(transports, other.transports) && slicedByFgbg == other.slicedByFgbg && slicedByTag == other.slicedByTag && slicedByMetered == other.slicedByMetered - && ratType == other.ratType; + && ratType == other.ratType && Objects.equals(subInfo, other.subInfo); } } @@ -880,20 +907,14 @@ public class StatsPullAtomService extends SystemService { ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats), new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false, /*slicedByTag=*/true, - /*slicedByMetered=*/true, TelephonyManager.NETWORK_TYPE_UNKNOWN)); + /*slicedByMetered=*/true, TelephonyManager.NETWORK_TYPE_UNKNOWN, + /*subInfo=*/null)); } break; } case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER: { - for (final int ratType : getAllCollapsedRatTypes()) { - final NetworkTemplate template = buildTemplateMobileWithRatType(null, ratType); - final NetworkStats stats = - getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false); - if (stats != null) { - ret.add(new NetworkStatsExt(sliceNetworkStatsByFgbg(stats), - new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true, - /*slicedByTag=*/false, /*slicedByMetered=*/false, ratType)); - } + for (final SubInfo subInfo : mHistoricalSubs) { + ret.addAll(getDataUsageBytesTransferSnapshotForSub(subInfo)); } break; } @@ -924,7 +945,8 @@ public class StatsPullAtomService extends SystemService { } final NetworkStatsExt diff = new NetworkStatsExt( item.stats.subtract(baseline.stats).removeEmptyEntries(), item.transports, - item.slicedByFgbg, item.slicedByTag, item.slicedByMetered, item.ratType); + item.slicedByFgbg, item.slicedByTag, item.slicedByMetered, item.ratType, + item.subInfo); // If no diff, skip. if (diff.stats.size() == 0) continue; @@ -1006,11 +1028,14 @@ public class StatsPullAtomService extends SystemService { .writeLong(entry.txBytes) .writeLong(entry.txPackets) .writeInt(statsExt.ratType) - // TODO: Fill information about subscription. - .writeString(/*sim_mcc=*/null) - .writeString(/*sim_mnc=*/null) - .writeInt(/*carrier_id=*/0) - .writeInt(/*opportunistic_data_sub=*/0) + // Fill information about subscription, these cannot be null since invalid data + // would be filtered when adding into subInfo list. + .writeString(statsExt.subInfo.mcc) + .writeString(statsExt.subInfo.mnc) + .writeInt(statsExt.subInfo.carrierId) + .writeInt(statsExt.subInfo.isOpportunistic + ? DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__OPPORTUNISTIC + : DATA_USAGE_BYTES_TRANSFER__OPPORTUNISTIC_DATA_SUB__NOT_OPPORTUNISTIC) .build(); pulledData.add(e); } @@ -1051,6 +1076,23 @@ public class StatsPullAtomService extends SystemService { return null; } + @NonNull private List getDataUsageBytesTransferSnapshotForSub( + @NonNull SubInfo subInfo) { + final List ret = new ArrayList<>(); + for (final int ratType : getAllCollapsedRatTypes()) { + final NetworkTemplate template = + buildTemplateMobileWithRatType(subInfo.subscriberId, ratType); + final NetworkStats stats = + getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false); + if (stats != null) { + ret.add(new NetworkStatsExt(sliceNetworkStatsByFgbg(stats), + new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true, + /*slicedByTag=*/false, /*slicedByMetered=*/false, ratType, subInfo)); + } + } + return ret; + } + @NonNull private NetworkStats sliceNetworkStatsByFgbg(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (newEntry, oldEntry) -> { @@ -3645,4 +3687,46 @@ public class StatsPullAtomService extends SystemService { FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED); } } + + private final class StatsSubscriptionsListener + extends SubscriptionManager.OnSubscriptionsChangedListener { + @NonNull + private final SubscriptionManager mSm; + + StatsSubscriptionsListener(@NonNull SubscriptionManager sm) { + mSm = sm; + } + + @Override + public void onSubscriptionsChanged() { + final List currentSubs = mSm.getCompleteActiveSubscriptionInfoList(); + for (final SubscriptionInfo sub : currentSubs) { + final SubInfo match = CollectionUtils.find(mHistoricalSubs, + (SubInfo it) -> it.subId == sub.getSubscriptionId()); + // SubInfo exists, ignore. + if (match != null) continue; + + // Ignore if no valid mcc, mnc, imsi, carrierId. + final int subId = sub.getSubscriptionId(); + final String mcc = sub.getMccString(); + final String mnc = sub.getMncString(); + final String subscriberId = mTelephony.getSubscriberId(subId); + if (TextUtils.isEmpty(subscriberId) || TextUtils.isEmpty(mcc) + || TextUtils.isEmpty(mnc) || sub.getCarrierId() == UNKNOWN_CARRIER_ID) { + Slog.e(TAG, "subInfo of subId " + subId + " is invalid, ignored."); + continue; + } + + final SubInfo subInfo = new SubInfo(subId, sub.getCarrierId(), mcc, mnc, + subscriberId, sub.isOpportunistic()); + Slog.i(TAG, "subId " + subId + " added into historical sub list"); + mHistoricalSubs.add(subInfo); + + // Since getting snapshot when pulling will also include data before boot, + // query stats as baseline to prevent double count is needed. + mNetworkStatsBaselines.addAll(getDataUsageBytesTransferSnapshotForSub(subInfo)); + } + } + } + } diff --git a/services/core/java/com/android/server/stats/pull/netstats/SubInfo.java b/services/core/java/com/android/server/stats/pull/netstats/SubInfo.java new file mode 100644 index 0000000000000..a03a45493261b --- /dev/null +++ b/services/core/java/com/android/server/stats/pull/netstats/SubInfo.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 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 com.android.server.stats.pull.netstats; + +import android.annotation.NonNull; + +import java.util.Objects; + +/** + * Information for a subscription that needed for sending NetworkStats related atoms. + * + * @hide + */ +public final class SubInfo { + public final int subId; + public final int carrierId; + @NonNull + public final String mcc; + @NonNull + public final String mnc; + @NonNull + public final String subscriberId; + public final boolean isOpportunistic; + + public SubInfo(int subId, int carrierId, @NonNull String mcc, @NonNull String mnc, + @NonNull String subscriberId, boolean isOpportunistic) { + this.subId = subId; + this.carrierId = carrierId; + this.mcc = mcc; + this.mnc = mnc; + this.subscriberId = subscriberId; + this.isOpportunistic = isOpportunistic; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final SubInfo other = (SubInfo) o; + return subId == other.subId + && carrierId == other.carrierId + && isOpportunistic == other.isOpportunistic + && mcc.equals(other.mcc) + && mnc.equals(other.mnc) + && subscriberId.equals(other.subscriberId); + } + + @Override + public int hashCode() { + return Objects.hash(subId, mcc, mnc, carrierId, subscriberId, isOpportunistic); + } +} From c2d3a68873a928c56602087a09923ab75b2ba706 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 22 May 2020 11:44:03 +0800 Subject: [PATCH 3/3] Move NetworkStatsExt to a standalone file This is a no-op refactoring. Test: atest UidAtomTests#testMobileBytesTransfer \ UidAtomTests#testMobileBytesTransferByFgBg \ UidAtomTests#testDataUsageBytesTransfer Bug: 129082217 Change-Id: I52d3418c1f46acfd38bc281d87fa1d1abf6ff469 --- .../stats/pull/StatsPullAtomService.java | 44 +----------- .../stats/pull/netstats/NetworkStatsExt.java | 72 +++++++++++++++++++ 2 files changed, 73 insertions(+), 43 deletions(-) create mode 100644 services/core/java/com/android/server/stats/pull/netstats/NetworkStatsExt.java diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index 927f036abab5b..24378a5b6fbda 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -160,6 +160,7 @@ import com.android.server.notification.NotificationManagerService; import com.android.server.role.RoleManagerInternal; import com.android.server.stats.pull.IonMemoryUtil.IonAllocations; import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot; +import com.android.server.stats.pull.netstats.NetworkStatsExt; import com.android.server.stats.pull.netstats.SubInfo; import com.android.server.storage.DiskStatsFileLogger; import com.android.server.storage.DiskStatsLoggingService; @@ -182,7 +183,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.MissingResourceException; -import java.util.Objects; import java.util.Random; import java.util.Set; import java.util.UUID; @@ -817,48 +817,6 @@ public class StatsPullAtomService extends SystemService { ); } - /** - * A data class to store a NetworkStats object with information associated to it. - */ - private static class NetworkStatsExt { - @NonNull - public final NetworkStats stats; - public final int[] transports; - public final boolean slicedByFgbg; - public final boolean slicedByTag; - public final boolean slicedByMetered; - public final int ratType; - @Nullable - public final SubInfo subInfo; - - NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg) { - this(stats, transports, slicedByFgbg, /*slicedByTag=*/false, /*slicedByMetered=*/false, - TelephonyManager.NETWORK_TYPE_UNKNOWN, /*subInfo=*/null); - } - - NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg, - boolean slicedByTag, boolean slicedByMetered, int ratType, - @Nullable SubInfo subInfo) { - this.stats = stats; - - // Sort transports array so that we can test for equality without considering order. - this.transports = Arrays.copyOf(transports, transports.length); - Arrays.sort(this.transports); - - this.slicedByFgbg = slicedByFgbg; - this.slicedByTag = slicedByTag; - this.slicedByMetered = slicedByMetered; - this.ratType = ratType; - this.subInfo = subInfo; - } - - public boolean hasSameSlicing(@NonNull NetworkStatsExt other) { - return Arrays.equals(transports, other.transports) && slicedByFgbg == other.slicedByFgbg - && slicedByTag == other.slicedByTag && slicedByMetered == other.slicedByMetered - && ratType == other.ratType && Objects.equals(subInfo, other.subInfo); - } - } - @NonNull private List collectNetworkStatsSnapshotForAtom(int atomTag) { List ret = new ArrayList<>(); diff --git a/services/core/java/com/android/server/stats/pull/netstats/NetworkStatsExt.java b/services/core/java/com/android/server/stats/pull/netstats/NetworkStatsExt.java new file mode 100644 index 0000000000000..06c81ee5e2bec --- /dev/null +++ b/services/core/java/com/android/server/stats/pull/netstats/NetworkStatsExt.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 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 com.android.server.stats.pull.netstats; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.NetworkStats; +import android.telephony.TelephonyManager; + +import java.util.Arrays; +import java.util.Objects; + +/** + * A data class to store a NetworkStats object with information associated to it. + * + * @hide + */ +public class NetworkStatsExt { + @NonNull + public final NetworkStats stats; + public final int[] transports; + public final boolean slicedByFgbg; + public final boolean slicedByTag; + public final boolean slicedByMetered; + public final int ratType; + @Nullable + public final SubInfo subInfo; + + public NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg) { + this(stats, transports, slicedByFgbg, /*slicedByTag=*/false, /*slicedByMetered=*/false, + TelephonyManager.NETWORK_TYPE_UNKNOWN, /*subInfo=*/null); + } + + public NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg, + boolean slicedByTag, boolean slicedByMetered, int ratType, + @Nullable SubInfo subInfo) { + this.stats = stats; + + // Sort transports array so that we can test for equality without considering order. + this.transports = Arrays.copyOf(transports, transports.length); + Arrays.sort(this.transports); + + this.slicedByFgbg = slicedByFgbg; + this.slicedByTag = slicedByTag; + this.slicedByMetered = slicedByMetered; + this.ratType = ratType; + this.subInfo = subInfo; + } + + /** + * A helper function to compare if all fields except NetworkStats are the same. + */ + public boolean hasSameSlicing(@NonNull NetworkStatsExt other) { + return Arrays.equals(transports, other.transports) && slicedByFgbg == other.slicedByFgbg + && slicedByTag == other.slicedByTag && slicedByMetered == other.slicedByMetered + && ratType == other.ratType && Objects.equals(subInfo, other.subInfo); + } +}