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();
- }
-}