Merge changes from topics "sm14-puller", "sm16-per-sub" into rvc-dev
* changes: Move NetworkStatsExt to a standalone file [SM16] Collect metrics per subscription [SM14] Create new puller for reporting data usage per rat
This commit is contained in:
@@ -24,17 +24,24 @@ import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
|
|||||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
|
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.Debug.getIonHeapsSizeKb;
|
||||||
import static android.os.Process.getUidForPid;
|
import static android.os.Process.getUidForPid;
|
||||||
import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
|
import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
|
||||||
import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
|
import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
|
||||||
import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
|
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.abs;
|
||||||
import static android.util.MathUtils.constrain;
|
import static android.util.MathUtils.constrain;
|
||||||
|
|
||||||
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
|
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_IS_UID;
|
||||||
import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_TRUNCATE_TIMESTAMP;
|
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.am.MemoryStatUtil.readMemoryStatFromFilesystem;
|
||||||
import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
|
import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
|
||||||
import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
|
import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
|
||||||
@@ -108,7 +115,10 @@ import android.provider.DeviceConfig;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.stats.storage.StorageEnums;
|
import android.stats.storage.StorageEnums;
|
||||||
import android.telephony.ModemActivityInfo;
|
import android.telephony.ModemActivityInfo;
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -150,6 +160,8 @@ import com.android.server.notification.NotificationManagerService;
|
|||||||
import com.android.server.role.RoleManagerInternal;
|
import com.android.server.role.RoleManagerInternal;
|
||||||
import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
|
import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
|
||||||
import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
|
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.DiskStatsFileLogger;
|
||||||
import com.android.server.storage.DiskStatsLoggingService;
|
import com.android.server.storage.DiskStatsLoggingService;
|
||||||
|
|
||||||
@@ -175,6 +187,7 @@ import java.util.Random;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -265,6 +278,7 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
private StorageManager mStorageManager;
|
private StorageManager mStorageManager;
|
||||||
private WifiManager mWifiManager;
|
private WifiManager mWifiManager;
|
||||||
private TelephonyManager mTelephony;
|
private TelephonyManager mTelephony;
|
||||||
|
private SubscriptionManager mSubscriptionManager;
|
||||||
|
|
||||||
private KernelWakelockReader mKernelWakelockReader;
|
private KernelWakelockReader mKernelWakelockReader;
|
||||||
private KernelWakelockStats mTmpWakelockStats;
|
private KernelWakelockStats mTmpWakelockStats;
|
||||||
@@ -300,6 +314,11 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final List<NetworkStatsExt> mNetworkStatsBaselines = new ArrayList<>();
|
private final List<NetworkStatsExt> 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<SubInfo> mHistoricalSubs = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
public StatsPullAtomService(Context context) {
|
public StatsPullAtomService(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
@@ -327,6 +346,7 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
case FrameworkStatsLog.MOBILE_BYTES_TRANSFER:
|
case FrameworkStatsLog.MOBILE_BYTES_TRANSFER:
|
||||||
case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG:
|
case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG:
|
||||||
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
|
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
|
||||||
|
case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER:
|
||||||
return pullDataBytesTransfer(atomTag, data);
|
return pullDataBytesTransfer(atomTag, data);
|
||||||
case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER:
|
case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER:
|
||||||
return pullBluetoothBytesTransfer(atomTag, data);
|
return pullBluetoothBytesTransfer(atomTag, data);
|
||||||
@@ -479,6 +499,9 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
mStatsManager = (StatsManager) mContext.getSystemService(Context.STATS_MANAGER);
|
mStatsManager = (StatsManager) mContext.getSystemService(Context.STATS_MANAGER);
|
||||||
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
|
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
|
||||||
mTelephony = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_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);
|
mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);
|
||||||
|
|
||||||
// Initialize DiskIO
|
// Initialize DiskIO
|
||||||
@@ -645,12 +668,20 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG));
|
FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG));
|
||||||
mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtom(
|
mNetworkStatsBaselines.addAll(collectNetworkStatsSnapshotForAtom(
|
||||||
FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED));
|
FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED));
|
||||||
|
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();
|
registerWifiBytesTransfer();
|
||||||
registerWifiBytesTransferBackground();
|
registerWifiBytesTransferBackground();
|
||||||
registerMobileBytesTransfer();
|
registerMobileBytesTransfer();
|
||||||
registerMobileBytesTransferBackground();
|
registerMobileBytesTransferBackground();
|
||||||
registerBytesTransferByTagAndMetered();
|
registerBytesTransferByTagAndMetered();
|
||||||
|
registerDataUsageBytesTransfer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -786,47 +817,12 @@ 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;
|
|
||||||
|
|
||||||
NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg) {
|
|
||||||
this(stats, transports, slicedByFgbg, /*slicedByTag=*/false, /*slicedByMetered=*/false);
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkStatsExt(@NonNull NetworkStats stats, int[] transports, boolean slicedByFgbg,
|
|
||||||
boolean slicedByTag, boolean slicedByMetered) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasSameSlicing(@NonNull NetworkStatsExt other) {
|
|
||||||
return Arrays.equals(transports, other.transports) && slicedByFgbg == other.slicedByFgbg
|
|
||||||
&& slicedByTag == other.slicedByTag && slicedByMetered == other.slicedByMetered;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private List<NetworkStatsExt> collectNetworkStatsSnapshotForAtom(int atomTag) {
|
private List<NetworkStatsExt> collectNetworkStatsSnapshotForAtom(int atomTag) {
|
||||||
List<NetworkStatsExt> ret = new ArrayList<>();
|
List<NetworkStatsExt> ret = new ArrayList<>();
|
||||||
switch(atomTag) {
|
switch(atomTag) {
|
||||||
case FrameworkStatsLog.WIFI_BYTES_TRANSFER: {
|
case FrameworkStatsLog.WIFI_BYTES_TRANSFER: {
|
||||||
final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_WIFI,
|
final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI);
|
||||||
/*includeTags=*/false);
|
|
||||||
if (stats != null) {
|
if (stats != null) {
|
||||||
ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI},
|
ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI},
|
||||||
/*slicedByFgbg=*/false));
|
/*slicedByFgbg=*/false));
|
||||||
@@ -834,8 +830,7 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: {
|
case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: {
|
||||||
final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_WIFI,
|
final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI);
|
||||||
/*includeTags=*/false);
|
|
||||||
if (stats != null) {
|
if (stats != null) {
|
||||||
ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
|
ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
|
||||||
new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/true));
|
new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/true));
|
||||||
@@ -843,8 +838,8 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: {
|
case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: {
|
||||||
final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_CELLULAR,
|
final NetworkStats stats =
|
||||||
/*includeTags=*/false);
|
getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR);
|
||||||
if (stats != null) {
|
if (stats != null) {
|
||||||
ret.add(new NetworkStatsExt(stats.groupedByUid(),
|
ret.add(new NetworkStatsExt(stats.groupedByUid(),
|
||||||
new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false));
|
new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false));
|
||||||
@@ -852,8 +847,8 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: {
|
case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: {
|
||||||
final NetworkStats stats = getUidNetworkStatsSnapshot(TRANSPORT_CELLULAR,
|
final NetworkStats stats =
|
||||||
/*includeTags=*/false);
|
getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR);
|
||||||
if (stats != null) {
|
if (stats != null) {
|
||||||
ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
|
ret.add(new NetworkStatsExt(sliceNetworkStatsByUidAndFgbg(stats),
|
||||||
new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true));
|
new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/true));
|
||||||
@@ -861,16 +856,23 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: {
|
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: {
|
||||||
final NetworkStats wifiStats = getUidNetworkStatsSnapshot(TRANSPORT_WIFI,
|
final NetworkStats wifiStats = getUidNetworkStatsSnapshotForTemplate(
|
||||||
/*includeTags=*/true);
|
buildTemplateWifiWildcard(), /*includeTags=*/true);
|
||||||
final NetworkStats cellularStats = getUidNetworkStatsSnapshot(TRANSPORT_CELLULAR,
|
final NetworkStats cellularStats = getUidNetworkStatsSnapshotForTemplate(
|
||||||
/*includeTags=*/true);
|
buildTemplateMobileWildcard(), /*includeTags=*/true);
|
||||||
if (wifiStats != null && cellularStats != null) {
|
if (wifiStats != null && cellularStats != null) {
|
||||||
final NetworkStats stats = wifiStats.add(cellularStats);
|
final NetworkStats stats = wifiStats.add(cellularStats);
|
||||||
ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
|
ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
|
||||||
new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR},
|
new int[] {TRANSPORT_WIFI, TRANSPORT_CELLULAR},
|
||||||
/*slicedByFgbg=*/false, /*slicedByTag=*/true,
|
/*slicedByFgbg=*/false, /*slicedByTag=*/true,
|
||||||
/*slicedByMetered=*/true));
|
/*slicedByMetered=*/true, TelephonyManager.NETWORK_TYPE_UNKNOWN,
|
||||||
|
/*subInfo=*/null));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER: {
|
||||||
|
for (final SubInfo subInfo : mHistoricalSubs) {
|
||||||
|
ret.addAll(getDataUsageBytesTransferSnapshotForSub(subInfo));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -901,7 +903,8 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
}
|
}
|
||||||
final NetworkStatsExt diff = new NetworkStatsExt(
|
final NetworkStatsExt diff = new NetworkStatsExt(
|
||||||
item.stats.subtract(baseline.stats).removeEmptyEntries(), item.transports,
|
item.stats.subtract(baseline.stats).removeEmptyEntries(), item.transports,
|
||||||
item.slicedByFgbg, item.slicedByTag, item.slicedByMetered);
|
item.slicedByFgbg, item.slicedByTag, item.slicedByMetered, item.ratType,
|
||||||
|
item.subInfo);
|
||||||
|
|
||||||
// If no diff, skip.
|
// If no diff, skip.
|
||||||
if (diff.stats.size() == 0) continue;
|
if (diff.stats.size() == 0) continue;
|
||||||
@@ -910,6 +913,9 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
|
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
|
||||||
addBytesTransferByTagAndMeteredAtoms(diff, pulledData);
|
addBytesTransferByTagAndMeteredAtoms(diff, pulledData);
|
||||||
break;
|
break;
|
||||||
|
case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER:
|
||||||
|
addDataUsageBytesTransferAtoms(diff, pulledData);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
addNetworkStats(atomTag, pulledData, diff);
|
addNetworkStats(atomTag, pulledData, diff);
|
||||||
}
|
}
|
||||||
@@ -966,18 +972,52 @@ 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)
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a snapshot of NetworkStats since boot, but add 1 bucket duration before boot as a
|
* Create a snapshot of NetworkStats for a given transport.
|
||||||
* 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) {
|
@Nullable private NetworkStats getUidNetworkStatsSnapshotForTransport(int transport) {
|
||||||
final NetworkTemplate template = (transport == TRANSPORT_CELLULAR)
|
final NetworkTemplate template = (transport == TRANSPORT_CELLULAR)
|
||||||
? NetworkTemplate.buildTemplateMobileWithRatType(
|
? NetworkTemplate.buildTemplateMobileWithRatType(
|
||||||
/*subscriptionId=*/null, NETWORK_TYPE_ALL)
|
/*subscriptionId=*/null, NETWORK_TYPE_ALL)
|
||||||
: NetworkTemplate.buildTemplateWifiWildcard();
|
: 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 getUidNetworkStatsSnapshotForTemplate(
|
||||||
|
@NonNull NetworkTemplate template, boolean includeTags) {
|
||||||
final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime();
|
final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime();
|
||||||
final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro());
|
final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro());
|
||||||
final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(),
|
final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(),
|
||||||
@@ -994,6 +1034,30 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSub(
|
||||||
|
@NonNull SubInfo subInfo) {
|
||||||
|
final List<NetworkStatsExt> 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) -> {
|
||||||
|
newEntry.set = oldEntry.set;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) {
|
@NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) {
|
||||||
return sliceNetworkStats(stats,
|
return sliceNetworkStats(stats,
|
||||||
(newEntry, oldEntry) -> {
|
(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() {
|
private void registerBluetoothBytesTransfer() {
|
||||||
int tagId = FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER;
|
int tagId = FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER;
|
||||||
PullAtomMetadata metadata = new PullAtomMetadata.Builder()
|
PullAtomMetadata metadata = new PullAtomMetadata.Builder()
|
||||||
@@ -3568,4 +3645,46 @@ public class StatsPullAtomService extends SystemService {
|
|||||||
FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED);
|
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<SubscriptionInfo> 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user