Persisting status int on the device if fallback happened

This CL also stop from incresing "successes" counter if the
importer finishes with fallback.

Test: manual
Bug: 230289468
Change-Id: I88fce1b2d0dea3772a8b31df8f8fa93bf13bffad
Merged-In: I88fce1b2d0dea3772a8b31df8f8fa93bf13bffad
  (cherry-picked from ag/18486388)
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index ff6e45d..9bf0d81 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -255,7 +255,8 @@
             "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;
@@ -275,10 +276,11 @@
     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 =
@@ -628,6 +630,7 @@
         /**
          * Create the persistent counter that counts total import legacy stats attempts.
          */
+        // TODO: Refactor multiple create counter functions into one.
         public PersistentInt createImportLegacyAttemptsCounter(@NonNull Path path)
                 throws IOException {
             // TODO: Modify PersistentInt to call setStartTime every time a write is made.
@@ -644,6 +647,14 @@
         }
 
         /**
+         * Create the persistent counter that counts total import legacy stats fallbacks.
+         */
+        public PersistentInt createImportLegacyFallbacksCounter(@NonNull Path path)
+                throws IOException {
+            return new PersistentInt(path.toString(), null /* logger */);
+        }
+
+        /**
          * Get the flag of storing files in the apex data directory.
          * @return whether to store files in the apex data directory.
          */
@@ -921,7 +932,9 @@
             mImportLegacyAttemptsCounter = mDeps.createImportLegacyAttemptsCounter(
                     mStatsDir.toPath().resolve(NETSTATS_IMPORT_ATTEMPTS_COUNTER_NAME));
             mImportLegacySuccessesCounter = mDeps.createImportLegacySuccessesCounter(
-                    mStatsDir.toPath().resolve(NETSTATS_IMPORT_SUCCESS_COUNTER_NAME));
+                    mStatsDir.toPath().resolve(NETSTATS_IMPORT_SUCCESSES_COUNTER_NAME));
+            mImportLegacyFallbacksCounter = mDeps.createImportLegacyFallbacksCounter(
+                    mStatsDir.toPath().resolve(NETSTATS_IMPORT_FALLBACKS_COUNTER_NAME));
         } catch (IOException e) {
             Log.wtf(TAG, "Failed to create persistent counters, skip.", e);
             return;
@@ -1029,11 +1042,7 @@
                 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
@@ -1073,10 +1082,17 @@
         // 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);
         }
@@ -2506,6 +2522,9 @@
                     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)");
                 }
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 4fbbc75..8ca3677 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -242,6 +242,7 @@
     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;
@@ -394,6 +395,12 @@
             }
 
             @Override
+            public PersistentInt createImportLegacyFallbacksCounter(
+                    @androidx.annotation.NonNull Path path) {
+                return mImportLegacyFallbacksCounter;
+            }
+
+            @Override
             public NetworkStatsCollection readPlatformCollection(
                     @NonNull String prefix, long bucketDuration) {
                 return mPlatformNetworkStatsCollection.get(prefix);
@@ -1901,7 +1908,7 @@
     }
 
     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();
     }