Merge "Improve the release of predict_back animaton leash" into main
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 1f19f81..5f61a91 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -713,8 +713,8 @@
                         mCurrentSize);
             } else {
                 applyContent(null, false, e);
+                mLastExecutionSignal = null;
             }
-            mLastExecutionSignal = null;
         }
     }
 
diff --git a/core/java/com/android/internal/os/flags.aconfig b/core/java/com/android/internal/os/flags.aconfig
index c8d6810..809c1a1 100644
--- a/core/java/com/android/internal/os/flags.aconfig
+++ b/core/java/com/android/internal/os/flags.aconfig
@@ -2,6 +2,48 @@
 container: "system"
 
 flag {
+     namespace: "ravenwood"
+     name: "ravenwood_flag_rw_1"
+     description: "Ravenwood test RW flag 1"
+     bug: "311370221"
+     metadata {
+         purpose: PURPOSE_BUGFIX
+     }
+}
+
+flag {
+     namespace: "ravenwood"
+     name: "ravenwood_flag_rw_2"
+     description: "Ravenwood test RW flag 2"
+     bug: "311370221"
+     metadata {
+         purpose: PURPOSE_BUGFIX
+     }
+}
+
+flag {
+     namespace: "ravenwood"
+     name: "ravenwood_flag_ro_1"
+     description: "Ravenwood test RO flag 1"
+     is_fixed_read_only: true
+     bug: "311370221"
+     metadata {
+         purpose: PURPOSE_BUGFIX
+     }
+}
+
+flag {
+     namespace: "ravenwood"
+     name: "ravenwood_flag_ro_2"
+     description: "Ravenwood test RO flag 2"
+     is_fixed_read_only: true
+     bug: "311370221"
+     metadata {
+         purpose: PURPOSE_BUGFIX
+     }
+}
+
+flag {
     name: "enable_apache_http_legacy_preload"
     namespace: "system_performance"
     description: "Enables zygote preload of non-BCP org.apache.http.legacy.jar library."
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
index 478bead..e0f9ec9 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
@@ -25,6 +25,7 @@
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import org.junit.AssumptionViolatedException;
 import org.junit.runner.Description;
 import org.junit.runners.model.TestClass;
 
@@ -134,8 +135,17 @@
         if (scope == Scope.Instance && order == Order.Outer) {
             // End of a test method.
             runner.mState.exitTestMethod();
-            RavenwoodTestStats.getInstance().onTestFinished(classDescription, description,
-                    th == null ? Result.Passed : Result.Failed);
+
+            final Result result;
+            if (th == null) {
+                result = Result.Passed;
+            } else if (th instanceof AssumptionViolatedException) {
+                result = Result.Skipped;
+            } else {
+                result = Result.Failed;
+            }
+
+            RavenwoodTestStats.getInstance().onTestFinished(classDescription, description, result);
         }
 
         // If RUN_DISABLED_TESTS is set, and the method did _not_ throw, make it an error.
diff --git a/ravenwood/scripts/ravenwood-test-summary b/ravenwood/scripts/ravenwood-test-summary
new file mode 100755
index 0000000..602fbff
--- /dev/null
+++ b/ravenwood/scripts/ravenwood-test-summary
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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.
+
+'''
+Print the latest Ravenwood test execution summary
+
+Usage: /ravenwood-test-summary
+
+Example output:
+Module                                                         Passed   Failed  Skipped
+android.test.mock.ravenwood.tests                                   2        0        0
+CarLibHostUnitTest                                                565        0        7
+CarServiceHostUnitTest                                            364        0        0
+CtsAccountManagerTestCasesRavenwood                                 4        0        0
+CtsAppTestCasesRavenwood                                           21        0        0
+
+Description:
+This script finds all the test execution result from /tmp/Ravenwood-stats*,
+and shows per-module summary.
+'''
+
+import csv
+import glob
+import sys
+
+# Find the latest stats files.
+stats_files = glob.glob('/tmp/Ravenwood-stats_*_latest.csv')
+
+if len(stats_files) == 0:
+    print("No log files found.", file=sys.stderr)
+    exit(1)
+
+
+def parse_stats(file, result):
+    module = '(unknwon)'
+    passed = 0
+    failed = 0
+    skipped = 0
+    with open(file) as csvfile:
+        reader = csv.reader(csvfile, delimiter=',')
+
+
+        for i, row in enumerate(reader):
+            if i == 0: continue # Skip header line
+            module = row[0]
+            passed += int(row[3])
+            failed += int(row[4])
+            skipped += int(row[5])
+
+    result[module] = (passed, failed, skipped)
+
+
+result = {}
+
+for file in stats_files:
+    parse_stats(file, result)
+
+print('%-60s %8s %8s %8s' % ("Module", "Passed", "Failed", "Skipped"))
+
+for module in sorted(result.keys(), key=str.casefold):
+    r = result[module]
+    print('%-60s %8d %8d %8d' % (module, r[0], r[1], r[2]))
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 918f130..0dedb73 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -289,7 +289,7 @@
         public void scheduleCheckLocked(long handlerCheckerTimeoutMillis) {
             mWaitMaxMillis = handlerCheckerTimeoutMillis;
 
-            if (mCompleted) {
+            if (mCompleted && !mMonitorQueue.isEmpty()) {
                 // Safe to update monitors in queue, Handler is not in the middle of work
                 mMonitors.addAll(mMonitorQueue);
                 mMonitorQueue.clear();
diff --git a/services/core/java/com/android/server/integrity/IntegrityFileManager.java b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
deleted file mode 100644
index 7f0231e..0000000
--- a/services/core/java/com/android/server/integrity/IntegrityFileManager.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2019 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.integrity;
-
-import android.annotation.Nullable;
-import android.content.integrity.AppInstallMetadata;
-import android.content.integrity.Rule;
-import android.os.Environment;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.integrity.model.RuleMetadata;
-import com.android.server.integrity.parser.RandomAccessObject;
-import com.android.server.integrity.parser.RuleBinaryParser;
-import com.android.server.integrity.parser.RuleIndexRange;
-import com.android.server.integrity.parser.RuleIndexingController;
-import com.android.server.integrity.parser.RuleMetadataParser;
-import com.android.server.integrity.parser.RuleParseException;
-import com.android.server.integrity.parser.RuleParser;
-import com.android.server.integrity.serializer.RuleBinarySerializer;
-import com.android.server.integrity.serializer.RuleMetadataSerializer;
-import com.android.server.integrity.serializer.RuleSerializeException;
-import com.android.server.integrity.serializer.RuleSerializer;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-/** Abstraction over the underlying storage of rules and other metadata. */
-public class IntegrityFileManager {
-    private static final String TAG = "IntegrityFileManager";
-
-    private static final String METADATA_FILE = "metadata";
-    private static final String RULES_FILE = "rules";
-    private static final String INDEXING_FILE = "indexing";
-    private static final Object RULES_LOCK = new Object();
-
-    private static IntegrityFileManager sInstance = null;
-
-    private final RuleParser mRuleParser;
-    private final RuleSerializer mRuleSerializer;
-
-    private final File mDataDir;
-    // mRulesDir contains data of the actual rules currently stored.
-    private final File mRulesDir;
-    // mStagingDir is used to store the temporary rules / metadata during updating, since we want to
-    // update rules atomically.
-    private final File mStagingDir;
-
-    @Nullable private RuleMetadata mRuleMetadataCache;
-    @Nullable private RuleIndexingController mRuleIndexingController;
-
-    /** Get the singleton instance of this class. */
-    public static synchronized IntegrityFileManager getInstance() {
-        if (sInstance == null) {
-            sInstance = new IntegrityFileManager();
-        }
-        return sInstance;
-    }
-
-    private IntegrityFileManager() {
-        this(
-                new RuleBinaryParser(),
-                new RuleBinarySerializer(),
-                Environment.getDataSystemDirectory());
-    }
-
-    @VisibleForTesting
-    IntegrityFileManager(RuleParser ruleParser, RuleSerializer ruleSerializer, File dataDir) {
-        mRuleParser = ruleParser;
-        mRuleSerializer = ruleSerializer;
-        mDataDir = dataDir;
-
-        mRulesDir = new File(dataDir, "integrity_rules");
-        mStagingDir = new File(dataDir, "integrity_staging");
-
-        if (!mStagingDir.mkdirs() || !mRulesDir.mkdirs()) {
-            Slog.e(TAG, "Error creating staging and rules directory");
-            // TODO: maybe throw an exception?
-        }
-
-        File metadataFile = new File(mRulesDir, METADATA_FILE);
-        if (metadataFile.exists()) {
-            try (FileInputStream inputStream = new FileInputStream(metadataFile)) {
-                mRuleMetadataCache = RuleMetadataParser.parse(inputStream);
-            } catch (Exception e) {
-                Slog.e(TAG, "Error reading metadata file.", e);
-            }
-        }
-
-        updateRuleIndexingController();
-    }
-
-    /**
-     * Returns if the rules have been initialized.
-     *
-     * <p>Used to fail early if there are no rules (so we don't need to parse the apk at all).
-     */
-    public boolean initialized() {
-        return new File(mRulesDir, RULES_FILE).exists()
-                && new File(mRulesDir, METADATA_FILE).exists()
-                && new File(mRulesDir, INDEXING_FILE).exists();
-    }
-
-    /** Write rules to persistent storage. */
-    public void writeRules(String version, String ruleProvider, List<Rule> rules)
-            throws IOException, RuleSerializeException {
-        try {
-            writeMetadata(mStagingDir, ruleProvider, version);
-        } catch (IOException e) {
-            Slog.e(TAG, "Error writing metadata.", e);
-            // We don't consider this fatal so we continue execution.
-        }
-
-        try (FileOutputStream ruleFileOutputStream =
-                        new FileOutputStream(new File(mStagingDir, RULES_FILE));
-                FileOutputStream indexingFileOutputStream =
-                        new FileOutputStream(new File(mStagingDir, INDEXING_FILE))) {
-            mRuleSerializer.serialize(
-                    rules, Optional.empty(), ruleFileOutputStream, indexingFileOutputStream);
-        }
-
-        switchStagingRulesDir();
-
-        // Update object holding the indexing information.
-        updateRuleIndexingController();
-    }
-
-    /**
-     * Read rules from persistent storage.
-     *
-     * @param appInstallMetadata information about the install used to select rules to read. If
-     *     null, all rules will be read.
-     */
-    public List<Rule> readRules(@Nullable AppInstallMetadata appInstallMetadata)
-            throws IOException, RuleParseException {
-        synchronized (RULES_LOCK) {
-            // Try to identify indexes from the index file.
-            List<RuleIndexRange> ruleReadingIndexes = Collections.emptyList();
-            if (appInstallMetadata != null) {
-                try {
-                    ruleReadingIndexes =
-                            mRuleIndexingController.identifyRulesToEvaluate(appInstallMetadata);
-                } catch (Exception e) {
-                    Slog.w(TAG, "Error identifying the rule indexes. Trying unindexed.", e);
-                }
-            }
-
-            // Read the rules based on the index information when available.
-            File ruleFile = new File(mRulesDir, RULES_FILE);
-            List<Rule> rules =
-                    mRuleParser.parse(RandomAccessObject.ofFile(ruleFile), ruleReadingIndexes);
-            return rules;
-        }
-    }
-
-    /** Read the metadata of the current rules in storage. */
-    @Nullable
-    public RuleMetadata readMetadata() {
-        return mRuleMetadataCache;
-    }
-
-    private void switchStagingRulesDir() throws IOException {
-        synchronized (RULES_LOCK) {
-            File tmpDir = new File(mDataDir, "temp");
-
-            if (!(mRulesDir.renameTo(tmpDir)
-                    && mStagingDir.renameTo(mRulesDir)
-                    && tmpDir.renameTo(mStagingDir))) {
-                throw new IOException("Error switching staging/rules directory");
-            }
-
-            for (File file : mStagingDir.listFiles()) {
-                file.delete();
-            }
-        }
-    }
-
-    private void updateRuleIndexingController() {
-        File ruleIndexingFile = new File(mRulesDir, INDEXING_FILE);
-        if (ruleIndexingFile.exists()) {
-            try (FileInputStream inputStream = new FileInputStream(ruleIndexingFile)) {
-                mRuleIndexingController = new RuleIndexingController(inputStream);
-            } catch (Exception e) {
-                Slog.e(TAG, "Error parsing the rule indexing file.", e);
-            }
-        }
-    }
-
-    private void writeMetadata(File directory, String ruleProvider, String version)
-            throws IOException {
-        mRuleMetadataCache = new RuleMetadata(ruleProvider, version);
-
-        File metadataFile = new File(directory, METADATA_FILE);
-
-        try (FileOutputStream outputStream = new FileOutputStream(metadataFile)) {
-            RuleMetadataSerializer.serialize(mRuleMetadataCache, outputStream);
-        }
-    }
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index cae941f..52a2fd6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -2970,8 +2970,13 @@
                     || context.getPackageManager().hasSystemFeature(
                             PackageManager.FEATURE_WIFI_RTT)) {
                 t.traceBegin("RangingService");
-                mSystemServiceManager.startServiceFromJar(RANGING_SERVICE_CLASS,
-                        RANGING_APEX_SERVICE_JAR_PATH);
+                // TODO: b/375264320 - Remove after RELEASE_RANGING_STACK is ramped to next.
+                try {
+                    mSystemServiceManager.startServiceFromJar(RANGING_SERVICE_CLASS,
+                            RANGING_APEX_SERVICE_JAR_PATH);
+                } catch (Throwable e) {
+                    Slog.d(TAG, "service-ranging.jar not found, not starting RangingService");
+                }
                 t.traceEnd();
             }
         }
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 105147f..42c171b 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.hardware.camera2.CameraManager;
+import android.hardware.usb.UsbManager;
 import android.os.Handler;
 import android.os.IBinder.DeathRecipient;
 import android.os.Looper;
@@ -67,6 +68,8 @@
     private int mUsageSetting;
     private boolean mUploadEnabled;
 
+    private boolean mAdbActive;
+
     private IProfCollectd mIProfcollect;
     private static ProfcollectForwardingService sSelfService;
     private final Handler mHandler = new ProfcollectdHandler(IoThread.getHandler().getLooper());
@@ -84,6 +87,14 @@
                 Log.d(LOG_TAG, "Received broadcast to pack and upload reports");
                 createAndUploadReport(sSelfService);
             }
+            if (UsbManager.ACTION_USB_STATE.equals(intent.getAction())) {
+                boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
+                boolean isADB = intent.getBooleanExtra(UsbManager.USB_FUNCTION_ADB, false);
+                if (isADB) {
+                    Log.d(LOG_TAG, "Received broadcast that ADB became " + connected);
+                    mAdbActive = connected;
+                }
+            }
         }
     };
 
@@ -106,8 +117,12 @@
         mUploadEnabled =
             context.getResources().getBoolean(R.bool.config_profcollectReportUploaderEnabled);
 
+        // TODO: ADB might already be active when our service started.
+        mAdbActive = false;
+
         final IntentFilter filter = new IntentFilter();
         filter.addAction(INTENT_UPLOAD_PROFILES);
+        filter.addAction(UsbManager.ACTION_USB_STATE);
         context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
     }
 
@@ -281,6 +296,9 @@
             if (mIProfcollect == null) {
                 return;
             }
+            if (mAdbActive) {
+                return;
+            }
             if (Utils.withFrequency("applaunch_trace_freq", 5)) {
                 Utils.traceSystem(mIProfcollect, "applaunch");
             }
@@ -303,6 +321,9 @@
         if (mIProfcollect == null) {
             return;
         }
+        if (mAdbActive) {
+            return;
+        }
         if (Utils.withFrequency("dex2oat_trace_freq", 25)) {
             // Dex2oat could take a while before it starts. Add a short delay before start tracing.
             Utils.traceSystem(mIProfcollect, "dex2oat", /* delayMs */ 1000);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
deleted file mode 100644
index 096c80b..0000000
--- a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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.integrity;
-
-import static com.android.server.integrity.model.IndexingFileConstants.INDEXING_BLOCK_SIZE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.integrity.AppInstallMetadata;
-import android.content.integrity.AtomicFormula;
-import android.content.integrity.AtomicFormula.LongAtomicFormula;
-import android.content.integrity.AtomicFormula.StringAtomicFormula;
-import android.content.integrity.CompoundFormula;
-import android.content.integrity.Rule;
-import android.util.Slog;
-
-import com.android.server.integrity.parser.RuleBinaryParser;
-import com.android.server.integrity.serializer.RuleBinarySerializer;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/** Unit test for {@link IntegrityFileManager} */
-@RunWith(JUnit4.class)
-public class IntegrityFileManagerTest {
-    private static final String TAG = "IntegrityFileManagerTest";
-
-    private static final String VERSION = "version";
-    private static final String RULE_PROVIDER = "rule_provider";
-
-    private File mTmpDir;
-
-    // under test
-    private IntegrityFileManager mIntegrityFileManager;
-
-    @Before
-    public void setUp() throws Exception {
-        mTmpDir = Files.createTempDirectory("IntegrityFileManagerTest").toFile();
-        Slog.i(TAG, "Using temp directory " + mTmpDir);
-
-        // Use Xml Parser/Serializer to help with debugging since we can just print the file.
-        mIntegrityFileManager =
-                new IntegrityFileManager(
-                        new RuleBinaryParser(), new RuleBinarySerializer(), mTmpDir);
-        Files.walk(mTmpDir.toPath())
-                .forEach(
-                        path -> {
-                            Slog.i(TAG, "before " + path);
-                        });
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        Files.walk(mTmpDir.toPath())
-                .forEach(
-                        path -> {
-                            Slog.i(TAG, "after " + path);
-                        });
-        // Sorting paths in reverse order guarantees that we delete inside files before deleting
-        // directory.
-        Files.walk(mTmpDir.toPath())
-                .sorted(Comparator.reverseOrder())
-                .map(Path::toFile)
-                .forEach(File::delete);
-    }
-
-    @Test
-    public void testGetMetadata() throws Exception {
-        assertThat(mIntegrityFileManager.readMetadata()).isNull();
-        mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
-
-        assertThat(mIntegrityFileManager.readMetadata()).isNotNull();
-        assertThat(mIntegrityFileManager.readMetadata().getVersion()).isEqualTo(VERSION);
-        assertThat(mIntegrityFileManager.readMetadata().getRuleProvider()).isEqualTo(RULE_PROVIDER);
-    }
-
-    @Test
-    public void testIsInitialized() throws Exception {
-        assertThat(mIntegrityFileManager.initialized()).isFalse();
-        mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
-        assertThat(mIntegrityFileManager.initialized()).isTrue();
-    }
-
-    @Test
-    public void testGetRules() throws Exception {
-        String packageName = "package";
-        String packageCert = "cert";
-        int version = 123;
-        Rule packageNameRule = getPackageNameIndexedRule(packageName);
-        Rule packageCertRule = getAppCertificateIndexedRule(packageCert);
-        Rule versionCodeRule =
-                new Rule(
-                        new LongAtomicFormula(
-                                AtomicFormula.VERSION_CODE, AtomicFormula.EQ, version),
-                        Rule.DENY);
-        Rule randomRule =
-                new Rule(
-                        new CompoundFormula(
-                                CompoundFormula.OR,
-                                Arrays.asList(
-                                        new StringAtomicFormula(
-                                                AtomicFormula.PACKAGE_NAME,
-                                                "abc",
-                                                /* isHashedValue= */ false),
-                                        new LongAtomicFormula(
-                                                AtomicFormula.VERSION_CODE,
-                                                AtomicFormula.EQ,
-                                                version))),
-                        Rule.DENY);
-
-        List<Rule> rules =
-                Arrays.asList(packageNameRule, packageCertRule, versionCodeRule, randomRule);
-        mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, rules);
-
-        AppInstallMetadata appInstallMetadata =
-                new AppInstallMetadata.Builder()
-                        .setPackageName(packageName)
-                        .setAppCertificates(Collections.singletonList(packageCert))
-                        .setAppCertificateLineage(Collections.singletonList(packageCert))
-                        .setVersionCode(version)
-                        .setInstallerName("abc")
-                        .setInstallerCertificates(Collections.singletonList("abc"))
-                        .setIsPreInstalled(true)
-                        .build();
-        List<Rule> rulesFetched = mIntegrityFileManager.readRules(appInstallMetadata);
-
-        assertThat(rulesFetched)
-                .containsExactly(packageNameRule, packageCertRule, versionCodeRule, randomRule);
-    }
-
-    @Test
-    public void testGetRules_indexedForManyRules() throws Exception {
-        String packageName = "package";
-        String installerName = "installer";
-        String appCertificate = "cert";
-
-        // Create a rule set with 2500 package name indexed, 2500 app certificate indexed and
-        // 500 unindexed rules.
-        List<Rule> rules = new ArrayList<>();
-        int unindexedRuleCount = 70;
-
-        for (int i = 0; i < 2500; i++) {
-            rules.add(getPackageNameIndexedRule(String.format("%s%04d", packageName, i)));
-            rules.add(getAppCertificateIndexedRule(String.format("%s%04d", appCertificate, i)));
-        }
-
-        for (int i = 0; i < unindexedRuleCount; i++) {
-            rules.add(getInstallerCertificateRule(String.format("%s%04d", installerName, i)));
-        }
-
-        // Write the rules and get them indexed.
-        mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, rules);
-
-        // Read the rules for a specific rule.
-        String installedPackageName = String.format("%s%04d", packageName, 264);
-        String installedAppCertificate = String.format("%s%04d", appCertificate, 1264);
-        AppInstallMetadata appInstallMetadata =
-                new AppInstallMetadata.Builder()
-                        .setPackageName(installedPackageName)
-                        .setAppCertificates(Collections.singletonList(installedAppCertificate))
-                        .setAppCertificateLineage(
-                                Collections.singletonList(installedAppCertificate))
-                        .setVersionCode(250)
-                        .setInstallerName("abc")
-                        .setInstallerCertificates(Collections.singletonList("abc"))
-                        .setIsPreInstalled(true)
-                        .build();
-        List<Rule> rulesFetched = mIntegrityFileManager.readRules(appInstallMetadata);
-
-        // Verify that we do not load all the rules and we have the necessary rules to evaluate.
-        assertThat(rulesFetched.size())
-                .isEqualTo(INDEXING_BLOCK_SIZE * 2 + unindexedRuleCount);
-        assertThat(rulesFetched)
-                .containsAtLeast(
-                        getPackageNameIndexedRule(installedPackageName),
-                        getAppCertificateIndexedRule(installedAppCertificate));
-    }
-
-    private Rule getPackageNameIndexedRule(String packageName) {
-        return new Rule(
-                new StringAtomicFormula(
-                        AtomicFormula.PACKAGE_NAME, packageName, /* isHashedValue= */false),
-                Rule.DENY);
-    }
-
-    private Rule getAppCertificateIndexedRule(String appCertificate) {
-        return new Rule(
-                new StringAtomicFormula(
-                        AtomicFormula.APP_CERTIFICATE,
-                        appCertificate, /* isHashedValue= */ false),
-                Rule.DENY);
-    }
-
-    private Rule getInstallerCertificateRule(String installerCert) {
-        return new Rule(
-                new StringAtomicFormula(
-                        AtomicFormula.INSTALLER_NAME, installerCert, /* isHashedValue= */false),
-                Rule.DENY);
-    }
-
-    @Test
-    public void testStagingDirectoryCleared() throws Exception {
-        // We must push rules two times to ensure that staging directory is empty because we cleared
-        // it, rather than because original rules directory is empty.
-        mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
-        mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
-
-        assertStagingDirectoryCleared();
-    }
-
-    private void assertStagingDirectoryCleared() {
-        File stagingDir = new File(mTmpDir, "integrity_staging");
-        assertThat(stagingDir.exists()).isTrue();
-        assertThat(stagingDir.isDirectory()).isTrue();
-        assertThat(stagingDir.listFiles()).isEmpty();
-    }
-}