Merge "[AF02.1] Support read by FastDataInput in the NetworkStatsRecorder" into main

This commit is contained in:
Junyu Lai 2023-12-25 01:58:14 +00:00 • committed by Gerrit Code Review
commit 962515a8a8
8 changed files with 81 additions and 11 deletions

View file

@ -57,6 +57,10 @@ java_defaults {
"app-compat-annotations",
"androidx.annotation_annotation",
],
static_libs: [
// Cannot go to framework-connectivity because mid_sdk checks require 31.
"modules-utils-binary-xml",
],
impl_only_libs: [
// The build system will use framework-bluetooth module_current stubs, because
// of sdk_version: "module_current" above.

View file

@ -60,6 +60,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FileRotator;
import com.android.modules.utils.FastDataInput;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkStatsUtils;
@ -116,15 +117,28 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W
private long mEndMillis;
private long mTotalBytes;
private boolean mDirty;
private final boolean mUseFastDataInput;
/**
* Construct a {@link NetworkStatsCollection} object.
*
* @param bucketDuration duration of the buckets in this object, in milliseconds.
* @param bucketDurationMillis duration of the buckets in this object, in milliseconds.
* @hide
*/
public NetworkStatsCollection(long bucketDurationMillis) {
this(bucketDurationMillis, false /* useFastDataInput */);
}
/**
* Construct a {@link NetworkStatsCollection} object.
*
* @param bucketDurationMillis duration of the buckets in this object, in milliseconds.
* @param useFastDataInput true if using {@link FastDataInput} is preferred. Otherwise, false.
* @hide
*/
public NetworkStatsCollection(long bucketDurationMillis, boolean useFastDataInput) {
mBucketDurationMillis = bucketDurationMillis;
mUseFastDataInput = useFastDataInput;
reset();
}
@ -483,7 +497,11 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W
/** @hide */
@Override
public void read(InputStream in) throws IOException {
read((DataInput) new DataInputStream(in));
if (mUseFastDataInput) {
read(FastDataInput.obtain(in));
} else {
read((DataInput) new DataInputStream(in));
}
}
private void read(DataInput in) throws IOException {

View file

@ -79,6 +79,7 @@ public class NetworkStatsRecorder {
private final long mBucketDuration;
private final boolean mOnlyTags;
private final boolean mWipeOnError;
private final boolean mUseFastDataInput;
private long mPersistThresholdBytes = 2 * MB_IN_BYTES;
private NetworkStats mLastSnapshot;
@ -104,6 +105,7 @@ public class NetworkStatsRecorder {
mBucketDuration = YEAR_IN_MILLIS;
mOnlyTags = false;
mWipeOnError = true;
mUseFastDataInput = false;
mPending = null;
mSinceBoot = new NetworkStatsCollection(mBucketDuration);
@ -116,7 +118,7 @@ public class NetworkStatsRecorder {
*/
public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer,
DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags,
boolean wipeOnError) {
boolean wipeOnError, boolean useFastDataInput) {
mRotator = Objects.requireNonNull(rotator, "missing FileRotator");
mObserver = Objects.requireNonNull(observer, "missing NonMonotonicObserver");
mDropBox = Objects.requireNonNull(dropBox, "missing DropBoxManager");
@ -125,6 +127,7 @@ public class NetworkStatsRecorder {
mBucketDuration = bucketDuration;
mOnlyTags = onlyTags;
mWipeOnError = wipeOnError;
mUseFastDataInput = useFastDataInput;
mPending = new NetworkStatsCollection(bucketDuration);
mSinceBoot = new NetworkStatsCollection(bucketDuration);
@ -195,8 +198,12 @@ public class NetworkStatsRecorder {
}
private NetworkStatsCollection loadLocked(long start, long end) {
if (LOGD) Log.d(TAG, "loadLocked() reading from disk for " + mCookie);
final NetworkStatsCollection res = new NetworkStatsCollection(mBucketDuration);
if (LOGD) {
Log.d(TAG, "loadLocked() reading from disk for " + mCookie
+ " useFastDataInput: " + mUseFastDataInput);
}
final NetworkStatsCollection res =
new NetworkStatsCollection(mBucketDuration, mUseFastDataInput);
try {
mRotator.readMatching(res, start, end);
res.recordCollection(mPending);

View file

@ -969,7 +969,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return new NetworkStatsRecorder(new FileRotator(
baseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags,
wipeOnError);
wipeOnError, false /* useFastDataInput */);
}
@GuardedBy("mStatsLock")

View file

@ -133,7 +133,16 @@ class NetworkStatsTest {
}
@Test
fun testReadFromRecorder_manyUids() {
fun testReadFromRecorder_manyUids_useDataInput() {
doTestReadFromRecorder_manyUids(useFastDataInput = false)
}
@Test
fun testReadFromRecorder_manyUids_useFastDataInput() {
doTestReadFromRecorder_manyUids(useFastDataInput = true)
}
fun doTestReadFromRecorder_manyUids(useFastDataInput: Boolean) {
val mockObserver = mock<NonMonotonicObserver<String>>()
val mockDropBox = mock<DropBoxManager>()
testFilesAssets.forEach {
@ -146,7 +155,8 @@ class NetworkStatsTest {
PREFIX_UID,
UID_COLLECTION_BUCKET_DURATION_MS,
false /* includeTags */,
false /* wipeOnError */
false /* wipeOnError */,
useFastDataInput /* useFastDataInput */
)
recorder.orLoadCompleteLocked
}

View file

@ -64,6 +64,7 @@ import libcore.io.Streams;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
@ -90,7 +91,8 @@ import java.util.Set;
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
public class NetworkStatsCollectionTest {
@Rule
public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
private static final String TEST_FILE = "test.bin";
private static final String TEST_IMSI = "310260000000000";
private static final int TEST_SUBID = 1;
@ -199,6 +201,33 @@ public class NetworkStatsCollectionTest {
77017831L, 100995L, 35436758L, 92344L);
}
private InputStream getUidInputStreamFromRes(int uidRes) throws Exception {
final File testFile =
new File(InstrumentationRegistry.getContext().getFilesDir(), TEST_FILE);
stageFile(uidRes, testFile);
final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS);
collection.readLegacyUid(testFile, true);
// now export into a unified format
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
collection.write(bos);
return new ByteArrayInputStream(bos.toByteArray());
}
@Test
public void testFastDataInputRead() throws Exception {
final NetworkStatsCollection legacyCollection =
new NetworkStatsCollection(30 * MINUTE_IN_MILLIS, false /* useFastDataInput */);
final NetworkStatsCollection fastReadCollection =
new NetworkStatsCollection(30 * MINUTE_IN_MILLIS, true /* useFastDataInput */);
final InputStream bis = getUidInputStreamFromRes(R.raw.netstats_uid_v4);
legacyCollection.read(bis);
bis.reset();
fastReadCollection.read(bis);
assertCollectionEntries(legacyCollection.getEntries(), fastReadCollection);
}
@Test
public void testStartEndAtomicBuckets() throws Exception {
final NetworkStatsCollection collection = new NetworkStatsCollection(HOUR_IN_MILLIS);

View file

@ -64,7 +64,8 @@ public final class NetworkStatsRecorderTest {
private NetworkStatsRecorder buildRecorder(FileRotator rotator, boolean wipeOnError) {
return new NetworkStatsRecorder(rotator, mObserver, mDropBox, TEST_PREFIX,
HOUR_IN_MILLIS, false /* includeTags */, wipeOnError);
HOUR_IN_MILLIS, false /* includeTags */, wipeOnError,
false /* useFastDataInput */);
}
@Test

View file

@ -2230,7 +2230,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
final DropBoxManager dropBox = mock(DropBoxManager.class);
return new NetworkStatsRecorder(new FileRotator(
directory, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
observer, dropBox, prefix, config.bucketDuration, includeTags, wipeOnError);
observer, dropBox, prefix, config.bucketDuration, includeTags, wipeOnError,
false /* useFastDataInput */);
}
private NetworkStatsCollection getLegacyCollection(String prefix, boolean includeTags) {