[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
This commit is contained in:
junyulai
2020-05-15 18:26:25 +08:00
parent edcb2c38f4
commit ee3ea79c38

View File

@@ -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<NetworkStatsExt> 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<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);
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()