Merge "Remove the IntegrityFileManager class that is unused after cleaning up references from AppIntegrityManagerServiceImpl." into main
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/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();
-    }
-}