From 38b94091a9b23c9aced530315bee50287a9a44c3 Mon Sep 17 00:00:00 2001 From: Victor Hsieh Date: Tue, 31 Jan 2023 09:30:03 -0800 Subject: Support measuring split measurePackage is changed into measureApk, which would hint that the method deals with a file instead of a "package" in the package manager's term. collectAppInfo is added to measure an app package, which may include split. Test * Add a test that leverages debug.transparency.bg-install-apps of BICs. * Copy BaseInstallMultiple from another test in frameworks/base to support split install. Misc * Delete getApexInfo and corresponding unit tests, since it's now coverred through collectAllApexInfo in integration test. This also makes it easy for refactoring without having to keeping the Bundle works as the return type. Bug: 264296226 Test: atest BinaryTransparencyServiceTest BinaryTransparencyHostTest Change-Id: Iaa4118dfa8605acda313dbcc2466ae96a60b4721 --- .../transparency/test/BaseInstallMultiple.java | 140 +++++++++++++++++++++ .../test/BinaryTransparencyHostTest.java | 32 +++++ 2 files changed, 172 insertions(+) create mode 100644 tests/BinaryTransparencyHostTest/src/android/transparency/test/BaseInstallMultiple.java (limited to 'tests/BinaryTransparencyHostTest/src') diff --git a/tests/BinaryTransparencyHostTest/src/android/transparency/test/BaseInstallMultiple.java b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BaseInstallMultiple.java new file mode 100644 index 000000000000..3e94f25b5fc7 --- /dev/null +++ b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BaseInstallMultiple.java @@ -0,0 +1,140 @@ +/* + * 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 android.transparency.test; + +import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; +import com.android.tradefed.build.IBuildInfo; +import com.android.tradefed.device.DeviceNotAvailableException; +import com.android.tradefed.device.ITestDevice; + +import junit.framework.TestCase; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Base class for invoking the install-multiple command via ADB. Subclass this for less typing: + * + * private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> { public + * InstallMultiple() { super(getDevice(), null); } } + */ +/*package*/ class BaseInstallMultiple> { + + private final ITestDevice mDevice; + private final IBuildInfo mBuild; + + private final List mArgs = new ArrayList<>(); + private final Map mFileToRemoteMap = new HashMap<>(); + + /*package*/ BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo) { + mDevice = device; + mBuild = buildInfo; + addArg("-g"); + } + + T addArg(String arg) { + mArgs.add(arg); + return (T) this; + } + + T addFile(String filename) throws FileNotFoundException { + return addFile(filename, filename); + } + + T addFile(String filename, String remoteName) throws FileNotFoundException { + CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild); + mFileToRemoteMap.put(buildHelper.getTestFile(filename), remoteName); + return (T) this; + } + + T inheritFrom(String packageName) { + addArg("-r"); + addArg("-p " + packageName); + return (T) this; + } + + void run() throws DeviceNotAvailableException { + run(true); + } + + void runExpectingFailure() throws DeviceNotAvailableException { + run(false); + } + + private void run(boolean expectingSuccess) throws DeviceNotAvailableException { + final ITestDevice device = mDevice; + + // Create an install session + final StringBuilder cmd = new StringBuilder(); + cmd.append("pm install-create"); + for (String arg : mArgs) { + cmd.append(' ').append(arg); + } + + String result = device.executeShellCommand(cmd.toString()); + TestCase.assertTrue(result, result.startsWith("Success")); + + final int start = result.lastIndexOf("["); + final int end = result.lastIndexOf("]"); + int sessionId = -1; + try { + if (start != -1 && end != -1 && start < end) { + sessionId = Integer.parseInt(result.substring(start + 1, end)); + } + } catch (NumberFormatException e) { + throw new IllegalStateException("Failed to parse install session: " + result); + } + if (sessionId == -1) { + throw new IllegalStateException("Failed to create install session: " + result); + } + + // Push our files into session. Ideally we'd use stdin streaming, + // but ddmlib doesn't support it yet. + for (final Map.Entry entry : mFileToRemoteMap.entrySet()) { + final File file = entry.getKey(); + final String remoteName = entry.getValue(); + final String remotePath = "/data/local/tmp/" + file.getName(); + if (!device.pushFile(file, remotePath)) { + throw new IllegalStateException("Failed to push " + file); + } + + cmd.setLength(0); + cmd.append("pm install-write"); + cmd.append(' ').append(sessionId); + cmd.append(' ').append(remoteName); + cmd.append(' ').append(remotePath); + + result = device.executeShellCommand(cmd.toString()); + TestCase.assertTrue(result, result.startsWith("Success")); + } + + // Everything staged; let's pull trigger + cmd.setLength(0); + cmd.append("pm install-commit"); + cmd.append(' ').append(sessionId); + + result = device.executeShellCommand(cmd.toString()); + if (expectingSuccess) { + TestCase.assertTrue(result, result.contains("Success")); + } else { + TestCase.assertFalse(result, result.contains("Success")); + } + } +} diff --git a/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java index 6fe548fe0ba4..b8e9a1751775 100644 --- a/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java +++ b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java @@ -18,6 +18,7 @@ package android.transparency.test; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -80,6 +81,28 @@ public final class BinaryTransparencyHostTest extends BaseHostJUnit4Test { } } + @Test + public void testCollectAllSilentInstalledMbaInfo() throws Exception { + try { + new InstallMultiple() + .addFile("ApkVerityTestApp.apk") + .addFile("ApkVerityTestAppSplit.apk") + .run(); + updatePreloadApp(); + assertNotNull(getDevice().getAppPackageInfo("com.android.apkverity")); + assertNotNull(getDevice().getAppPackageInfo("com.android.egg")); + + assertTrue(getDevice().setProperty("debug.transparency.bg-install-apps", + "com.android.apkverity,com.android.egg")); + runDeviceTest("testCollectAllSilentInstalledMbaInfo"); + } finally { + // No need to wait until job complete, since we can't verifying very meaningfully. + cancelPendingJob(); + uninstallPackage("com.android.apkverity"); + uninstallPackage("com.android.egg"); + } + } + @Test public void testRebootlessApexUpdateTriggersJobScheduling() throws Exception { try { @@ -171,4 +194,13 @@ public final class BinaryTransparencyHostTest extends BaseHostJUnit4Test { result = getDevice().executeShellV2Command("pm install " + path); assertTrue(result.getStatus() == CommandStatus.SUCCESS); } + + private class InstallMultiple extends BaseInstallMultiple { + InstallMultiple() { + super(getDevice(), getBuild()); + // Needed since in getMockBackgroundInstalledPackages, getPackageInfo runs as the caller + // uid. This also makes it consistent with installPackage's behavior. + addArg("--force-queryable"); + } + } } -- cgit v1.2.3-59-g8ed1b