Merge changes Id91fabb4,I6d117032,I88fce1b2 into tm-dev

* changes:
  Address comment at ag/18491259 and ag/18486388
  Run comparison code if the data migration finished with fallback
  Persisting status int on the device if fallback happened
This commit is contained in:
TreeHugger Robot
2022-05-24 23:47:50 +00:00
committed by Android (Google) Code Review
2 changed files with 64 additions and 40 deletions

View File

@@ -253,7 +253,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
"netstats_import_legacy_target_attempts";
static final int DEFAULT_NETSTATS_IMPORT_LEGACY_TARGET_ATTEMPTS = 1;
static final String NETSTATS_IMPORT_ATTEMPTS_COUNTER_NAME = "import.attempts";
static final String NETSTATS_IMPORT_SUCCESS_COUNTER_NAME = "import.successes";
static final String NETSTATS_IMPORT_SUCCESSES_COUNTER_NAME = "import.successes";
static final String NETSTATS_IMPORT_FALLBACKS_COUNTER_NAME = "import.fallbacks";
private final Context mContext;
private final NetworkStatsFactory mStatsFactory;
@@ -273,10 +274,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final AlertObserver mAlertObserver = new AlertObserver();
// Persistent counters that backed by AtomicFile which stored in the data directory as a file,
// to track attempts/successes count across reboot. Note that these counter values will be
// rollback as the module rollbacks.
// to track attempts/successes/fallbacks count across reboot. Note that these counter values
// will be rollback as the module rollbacks.
private PersistentInt mImportLegacyAttemptsCounter = null;
private PersistentInt mImportLegacySuccessesCounter = null;
private PersistentInt mImportLegacyFallbacksCounter = null;
@VisibleForTesting
public static final String ACTION_NETWORK_STATS_POLL =
@@ -619,21 +621,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
/**
* Create the persistent counter that counts total import legacy stats attempts.
* Create a persistent counter for given directory and name.
*/
public PersistentInt createImportLegacyAttemptsCounter(@NonNull Path path)
public PersistentInt createPersistentCounter(@NonNull Path dir, @NonNull String name)
throws IOException {
// TODO: Modify PersistentInt to call setStartTime every time a write is made.
// Create and pass a real logger here.
return new PersistentInt(path.toString(), null /* logger */);
}
/**
* Create the persistent counter that counts total import legacy stats successes.
*/
public PersistentInt createImportLegacySuccessesCounter(@NonNull Path path)
throws IOException {
return new PersistentInt(path.toString(), null /* logger */);
final String path = dir.resolve(name).toString();
return new PersistentInt(path, null /* logger */);
}
/**
@@ -911,10 +906,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return;
}
try {
mImportLegacyAttemptsCounter = mDeps.createImportLegacyAttemptsCounter(
mStatsDir.toPath().resolve(NETSTATS_IMPORT_ATTEMPTS_COUNTER_NAME));
mImportLegacySuccessesCounter = mDeps.createImportLegacySuccessesCounter(
mStatsDir.toPath().resolve(NETSTATS_IMPORT_SUCCESS_COUNTER_NAME));
mImportLegacyAttemptsCounter = mDeps.createPersistentCounter(mStatsDir.toPath(),
NETSTATS_IMPORT_ATTEMPTS_COUNTER_NAME);
mImportLegacySuccessesCounter = mDeps.createPersistentCounter(mStatsDir.toPath(),
NETSTATS_IMPORT_SUCCESSES_COUNTER_NAME);
mImportLegacyFallbacksCounter = mDeps.createPersistentCounter(mStatsDir.toPath(),
NETSTATS_IMPORT_FALLBACKS_COUNTER_NAME);
} catch (IOException e) {
Log.wtf(TAG, "Failed to create persistent counters, skip.", e);
return;
@@ -922,15 +919,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final int targetAttempts = mDeps.getImportLegacyTargetAttempts();
final int attempts;
final int fallbacks;
try {
attempts = mImportLegacyAttemptsCounter.get();
fallbacks = mImportLegacyFallbacksCounter.get();
} catch (IOException e) {
Log.wtf(TAG, "Failed to read attempts counter, skip.", e);
Log.wtf(TAG, "Failed to read counters, skip.", e);
return;
}
if (attempts >= targetAttempts) return;
// If fallbacks is not zero, proceed with reading only to give signals from dogfooders.
// TODO(b/233752318): Remove fallbacks counter check before T formal release.
if (attempts >= targetAttempts && fallbacks == 0) return;
Log.i(TAG, "Starting import : attempts " + attempts + "/" + targetAttempts);
final boolean dryRunImportOnly = (attempts >= targetAttempts);
if (dryRunImportOnly) {
Log.i(TAG, "Starting import : only perform read");
} else {
Log.i(TAG, "Starting import : attempts " + attempts + "/" + targetAttempts);
}
final MigrationInfo[] migrations = new MigrationInfo[]{
new MigrationInfo(mDevRecorder), new MigrationInfo(mXtRecorder),
@@ -987,6 +993,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
// For cases where the fallbacks is not zero but target attempts counts reached,
// only perform reads above and return here.
if (dryRunImportOnly) return;
// Find the latest end time.
for (final MigrationInfo migration : migrations) {
final long migrationEnd = migration.collection.getEndMillis();
@@ -1009,11 +1019,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
migration.recorder.importCollectionLocked(migration.collection);
}
if (endedWithFallback) {
Log.wtf(TAG, "Imported platform collections with legacy fallback");
} else {
Log.i(TAG, "Successfully imported platform collections");
}
// Success normally or uses fallback method.
} catch (Throwable e) {
// The code above calls OEM code that may behave differently across devices.
// It can throw any exception including RuntimeExceptions and
@@ -1053,10 +1059,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// Success ! No need to import again next time.
try {
mImportLegacyAttemptsCounter.set(targetAttempts);
// The successes counter is only for debugging. Hence, the synchronization
// between these two counters are not very critical.
final int successCount = mImportLegacySuccessesCounter.get();
mImportLegacySuccessesCounter.set(successCount + 1);
if (endedWithFallback) {
Log.wtf(TAG, "Imported platform collections with legacy fallback");
final int fallbacksCount = mImportLegacyFallbacksCounter.get();
mImportLegacyFallbacksCounter.set(fallbacksCount + 1);
} else {
Log.i(TAG, "Successfully imported platform collections");
// The successes counter is only for debugging. Hence, the synchronization
// between successes counter and attempts counter are not very critical.
final int successCount = mImportLegacySuccessesCounter.get();
mImportLegacySuccessesCounter.set(successCount + 1);
}
} catch (IOException e) {
Log.wtf(TAG, "Succeed but failed to update counters.", e);
}
@@ -2478,6 +2491,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
pw.print("platform legacy stats import successes count",
mImportLegacySuccessesCounter.get());
pw.println();
pw.print("platform legacy stats import fallbacks count",
mImportLegacyFallbacksCounter.get());
pw.println();
} catch (IOException e) {
pw.println("(failed to dump platform legacy stats import counters)");
}

View File

@@ -67,6 +67,9 @@ import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static com.android.net.module.util.NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
import static com.android.server.net.NetworkStatsService.NETSTATS_IMPORT_ATTEMPTS_COUNTER_NAME;
import static com.android.server.net.NetworkStatsService.NETSTATS_IMPORT_FALLBACKS_COUNTER_NAME;
import static com.android.server.net.NetworkStatsService.NETSTATS_IMPORT_SUCCESSES_COUNTER_NAME;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static org.junit.Assert.assertEquals;
@@ -141,6 +144,7 @@ import com.android.testutils.TestBpfMap;
import com.android.testutils.TestableNetworkStatsProviderBinder;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Clock;
@@ -239,6 +243,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
private int mImportLegacyTargetAttempts = 0;
private @Mock PersistentInt mImportLegacyAttemptsCounter;
private @Mock PersistentInt mImportLegacySuccessesCounter;
private @Mock PersistentInt mImportLegacyFallbacksCounter;
private class MockContext extends BroadcastInterceptingContext {
private final Context mBaseContext;
@@ -379,15 +384,18 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
}
@Override
public PersistentInt createImportLegacyAttemptsCounter(
@androidx.annotation.NonNull Path path) {
return mImportLegacyAttemptsCounter;
}
@Override
public PersistentInt createImportLegacySuccessesCounter(
@androidx.annotation.NonNull Path path) {
return mImportLegacySuccessesCounter;
public PersistentInt createPersistentCounter(@androidx.annotation.NonNull Path dir,
@androidx.annotation.NonNull String name) throws IOException {
switch (name) {
case NETSTATS_IMPORT_ATTEMPTS_COUNTER_NAME:
return mImportLegacyAttemptsCounter;
case NETSTATS_IMPORT_SUCCESSES_COUNTER_NAME:
return mImportLegacySuccessesCounter;
case NETSTATS_IMPORT_FALLBACKS_COUNTER_NAME:
return mImportLegacyFallbacksCounter;
default:
throw new IllegalArgumentException("Unknown counter name: " + name);
}
}
@Override
@@ -1861,7 +1869,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
}
private NetworkStatsCollection getLegacyCollection(String prefix, boolean includeTags) {
final NetworkStatsRecorder recorder = makeTestRecorder(mLegacyStatsDir, PREFIX_DEV,
final NetworkStatsRecorder recorder = makeTestRecorder(mLegacyStatsDir, prefix,
mSettings.getDevConfig(), includeTags);
return recorder.getOrLoadCompleteLocked();
}