Merge "Check for downgrade and signature of outer .apex certificate" into sc-dev
This commit is contained in:
@@ -32,6 +32,7 @@ import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageInstaller;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageParser.PackageParserException;
|
||||
import android.content.pm.PackageParser.SigningDetails;
|
||||
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
|
||||
import android.content.pm.parsing.ParsingPackageUtils;
|
||||
import android.os.Binder;
|
||||
@@ -45,6 +46,7 @@ import android.util.ArraySet;
|
||||
import android.util.Singleton;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.apk.ApkSignatureVerifier;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -52,6 +54,7 @@ import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.pm.parsing.PackageParser2;
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
import com.android.server.pm.parsing.pkg.ParsedPackage;
|
||||
import com.android.server.utils.TimingsTraceAndSlog;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
@@ -390,9 +393,10 @@ public abstract class ApexManager {
|
||||
throws RemoteException;
|
||||
|
||||
/**
|
||||
* Performs a non-staged install of an APEX package with given {@code packagePath}.
|
||||
* Performs a non-staged install of the given {@code apexFile}.
|
||||
*/
|
||||
abstract void installPackage(String packagePath) throws PackageManagerException;
|
||||
abstract void installPackage(File apexFile, PackageParser2 packageParser)
|
||||
throws PackageManagerException;
|
||||
|
||||
/**
|
||||
* Dumps various state information to the provided {@link PrintWriter} object.
|
||||
@@ -979,12 +983,80 @@ public abstract class ApexManager {
|
||||
waitForApexService().reserveSpaceForCompressedApex(infoList);
|
||||
}
|
||||
|
||||
@Override
|
||||
void installPackage(String packagePath) throws PackageManagerException {
|
||||
private SigningDetails getSigningDetails(PackageInfo pkg) throws PackageManagerException {
|
||||
int minSignatureScheme =
|
||||
ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
|
||||
pkg.applicationInfo.targetSdkVersion);
|
||||
try {
|
||||
// TODO(b/187864524): do pre-install verification.
|
||||
waitForApexService().installAndActivatePackage(packagePath);
|
||||
// TODO(b/187864524): update mAllPackagesCache.
|
||||
return ApkSignatureVerifier.verify(pkg.applicationInfo.sourceDir,
|
||||
minSignatureScheme);
|
||||
} catch (PackageParserException e) {
|
||||
throw PackageManagerException.from(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkApexSignature(PackageInfo existingApexPkg, PackageInfo newApexPkg)
|
||||
throws PackageManagerException {
|
||||
final SigningDetails existingSigningDetails = getSigningDetails(existingApexPkg);
|
||||
final SigningDetails newSigningDetails = getSigningDetails(newApexPkg);
|
||||
if (!newSigningDetails.checkCapability(existingSigningDetails,
|
||||
SigningDetails.CertCapabilities.INSTALLED_DATA)) {
|
||||
throw new PackageManagerException(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
|
||||
"APK container signature of " + newApexPkg.applicationInfo.sourceDir
|
||||
+ " is not compatible with currently installed on device");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDowngrade(PackageInfo existingApexPkg, PackageInfo newApexPkg)
|
||||
throws PackageManagerException {
|
||||
final long currentVersionCode = existingApexPkg.applicationInfo.longVersionCode;
|
||||
final long newVersionCode = newApexPkg.applicationInfo.longVersionCode;
|
||||
if (currentVersionCode > newVersionCode) {
|
||||
throw new PackageManagerException(PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE,
|
||||
"Downgrade of APEX package " + newApexPkg.packageName
|
||||
+ " is not allowed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void installPackage(File apexFile, PackageParser2 packageParser)
|
||||
throws PackageManagerException {
|
||||
try {
|
||||
final int flags = PackageManager.GET_META_DATA
|
||||
| PackageManager.GET_SIGNING_CERTIFICATES
|
||||
| PackageManager.GET_SIGNATURES;
|
||||
final ParsedPackage parsedPackage = packageParser.parsePackage(
|
||||
apexFile, flags, /* useCaches= */ false);
|
||||
final PackageInfo newApexPkg = PackageInfoWithoutStateUtils.generate(parsedPackage,
|
||||
/* apexInfo= */ null, flags);
|
||||
if (newApexPkg == null) {
|
||||
throw new PackageManagerException(PackageManager.INSTALL_FAILED_INVALID_APK,
|
||||
"Failed to generate package info for " + apexFile.getAbsolutePath());
|
||||
}
|
||||
final PackageInfo existingApexPkg = getPackageInfo(newApexPkg.packageName,
|
||||
MATCH_ACTIVE_PACKAGE);
|
||||
if (existingApexPkg == null) {
|
||||
Slog.w(TAG, "Attempting to install new APEX package " + newApexPkg.packageName);
|
||||
throw new PackageManagerException(PackageManager.INSTALL_FAILED_PACKAGE_CHANGED,
|
||||
"It is forbidden to install new APEX packages");
|
||||
}
|
||||
checkApexSignature(existingApexPkg, newApexPkg);
|
||||
checkDowngrade(existingApexPkg, newApexPkg);
|
||||
ApexInfo apexInfo = waitForApexService().installAndActivatePackage(
|
||||
apexFile.getAbsolutePath());
|
||||
final ParsedPackage parsedPackage2 = packageParser.parsePackage(
|
||||
new File(apexInfo.modulePath), flags, /* useCaches= */ false);
|
||||
final PackageInfo finalApexPkg = PackageInfoWithoutStateUtils.generate(
|
||||
parsedPackage, apexInfo, flags);
|
||||
// Installation was successful, time to update mAllPackagesCache
|
||||
synchronized (mLock) {
|
||||
for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) {
|
||||
if (mAllPackagesCache.get(i).equals(existingApexPkg)) {
|
||||
mAllPackagesCache.set(i, finalApexPkg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new PackageManagerException(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
|
||||
"apexservice not available");
|
||||
@@ -1262,7 +1334,7 @@ public abstract class ApexManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
void installPackage(String packagePath) {
|
||||
void installPackage(File apexFile, PackageParser2 packageParser) {
|
||||
throw new UnsupportedOperationException("APEX updates are not supported");
|
||||
}
|
||||
|
||||
|
||||
@@ -17118,7 +17118,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
try {
|
||||
// Should directory scanning logic be moved to ApexManager for better test coverage?
|
||||
final File dir = request.args.origin.resolvedFile;
|
||||
final String[] apexes = dir.list();
|
||||
final File[] apexes = dir.listFiles();
|
||||
if (apexes == null) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
|
||||
dir.getAbsolutePath() + " is not a directory");
|
||||
@@ -17128,7 +17128,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
"Expected exactly one .apex file under " + dir.getAbsolutePath()
|
||||
+ " got: " + apexes.length);
|
||||
}
|
||||
mApexManager.installPackage(dir.getAbsolutePath() + "/" + apexes[0]);
|
||||
try (PackageParser2 packageParser = mInjector.getScanningPackageParser()) {
|
||||
mApexManager.installPackage(apexes[0], packageParser);
|
||||
}
|
||||
} catch (PackageManagerException e) {
|
||||
request.installResult.setError("APEX installation failed", e);
|
||||
}
|
||||
|
||||
@@ -118,6 +118,11 @@ android_test {
|
||||
":PackageParserTestApp3",
|
||||
":PackageParserTestApp4",
|
||||
":apex.test",
|
||||
":test.rebootless_apex_v1",
|
||||
":test.rebootless_apex_v2",
|
||||
":com.android.apex.cts.shim.v1_prebuilt",
|
||||
":com.android.apex.cts.shim.v2_different_certificate_prebuilt",
|
||||
":com.android.apex.cts.shim.v2_unsigned_apk_container_prebuilt",
|
||||
],
|
||||
resource_zips: [":FrameworksServicesTests_apks_as_resources"],
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
@@ -29,6 +30,7 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
import android.apex.ApexInfo;
|
||||
import android.apex.ApexSessionInfo;
|
||||
@@ -84,7 +86,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetPackageInfo_setFlagsMatchActivePackage() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
final PackageInfo activePkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
|
||||
@@ -101,7 +103,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetPackageInfo_setFlagsMatchFactoryPackage() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
PackageInfo factoryPkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
|
||||
@@ -118,7 +120,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetPackageInfo_setFlagsNone() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -127,7 +129,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetActivePackages() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, true));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, true));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -136,7 +138,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetActivePackages_noneActivePackages() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -145,7 +147,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetFactoryPackages() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -154,7 +156,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetFactoryPackages_noneFactoryPackages() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -163,7 +165,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetInactivePackages() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -172,7 +174,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetInactivePackages_noneInactivePackages() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -181,7 +183,7 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testIsApexPackage() throws RemoteException {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(false, true));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -276,11 +278,11 @@ public class ApexManagerTest {
|
||||
|
||||
@Test
|
||||
public void testReportErrorWithApkInApex() throws RemoteException {
|
||||
when(mApexService.getActivePackages()).thenReturn(createApexInfo(true, true));
|
||||
when(mApexService.getActivePackages()).thenReturn(createApexInfoForTestPkg(true, true));
|
||||
final ApexManager.ActiveApexInfo activeApex = mApexManager.getActiveApexInfos().get(0);
|
||||
assertThat(activeApex.apexModuleName).isEqualTo(TEST_APEX_PKG);
|
||||
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, true));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, true));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -297,7 +299,7 @@ public class ApexManagerTest {
|
||||
*/
|
||||
@Test
|
||||
public void testRegisterApkInApexDoesNotRegisterSimilarPrefix() throws RemoteException {
|
||||
when(mApexService.getActivePackages()).thenReturn(createApexInfo(true, true));
|
||||
when(mApexService.getActivePackages()).thenReturn(createApexInfoForTestPkg(true, true));
|
||||
final ApexManager.ActiveApexInfo activeApex = mApexManager.getActiveApexInfos().get(0);
|
||||
assertThat(activeApex.apexModuleName).isEqualTo(TEST_APEX_PKG);
|
||||
|
||||
@@ -305,7 +307,7 @@ public class ApexManagerTest {
|
||||
when(fakeApkInApex.getBaseApkPath()).thenReturn("/apex/" + TEST_APEX_PKG + "randomSuffix");
|
||||
when(fakeApkInApex.getPackageName()).thenReturn("randomPackageName");
|
||||
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, true));
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, true));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
@@ -314,7 +316,112 @@ public class ApexManagerTest {
|
||||
assertThat(mApexManager.getApksInApex(activeApex.apexModuleName)).isEmpty();
|
||||
}
|
||||
|
||||
private ApexInfo[] createApexInfo(boolean isActive, boolean isFactory) {
|
||||
@Test
|
||||
public void testInstallPackageFailsToInstallNewApex() throws Exception {
|
||||
when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false));
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
File apex = extractResource("test.apex_rebootless_v1", "test.rebootless_apex_v1.apex");
|
||||
PackageManagerException e = expectThrows(PackageManagerException.class,
|
||||
() -> mApexManager.installPackage(apex, mPackageParser2));
|
||||
assertThat(e).hasMessageThat().contains("It is forbidden to install new APEX packages");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstallPackageDowngrade() throws Exception {
|
||||
File activeApex = extractResource("test.apex_rebootless_v2",
|
||||
"test.rebootless_apex_v2.apex");
|
||||
ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true,
|
||||
/* isFactory= */ false, activeApex);
|
||||
when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
File installedApex = extractResource("test.apex_rebootless_v1",
|
||||
"test.rebootless_apex_v1.apex");
|
||||
PackageManagerException e = expectThrows(PackageManagerException.class,
|
||||
() -> mApexManager.installPackage(installedApex, mPackageParser2));
|
||||
assertThat(e).hasMessageThat().contains(
|
||||
"Downgrade of APEX package test.apex.rebootless is not allowed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstallPackage() throws Exception {
|
||||
ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true,
|
||||
/* isFactory= */ false, extractResource("test.apex_rebootless_v1",
|
||||
"test.rebootless_apex_v1.apex"));
|
||||
when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
File finalApex = extractResource("test.rebootles_apex_v2", "test.rebootless_apex_v2.apex");
|
||||
ApexInfo newApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true,
|
||||
/* isFactory= */ false, finalApex);
|
||||
when(mApexService.installAndActivatePackage(anyString())).thenReturn(newApexInfo);
|
||||
|
||||
File installedApex = extractResource("installed", "test.rebootless_apex_v2.apex");
|
||||
mApexManager.installPackage(installedApex, mPackageParser2);
|
||||
|
||||
PackageInfo newInfo = mApexManager.getPackageInfo("test.apex.rebootless",
|
||||
ApexManager.MATCH_ACTIVE_PACKAGE);
|
||||
assertThat(newInfo.applicationInfo.sourceDir).isEqualTo(finalApex.getAbsolutePath());
|
||||
assertThat(newInfo.applicationInfo.longVersionCode).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstallPackageBinderCallFails() throws Exception {
|
||||
ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true,
|
||||
/* isFactory= */ false, extractResource("test.apex_rebootless_v1",
|
||||
"test.rebootless_apex_v1.apex"));
|
||||
when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
when(mApexService.installAndActivatePackage(anyString())).thenThrow(
|
||||
new RuntimeException("install failed :("));
|
||||
|
||||
File installedApex = extractResource("test.apex_rebootless_v1",
|
||||
"test.rebootless_apex_v1.apex");
|
||||
assertThrows(PackageManagerException.class,
|
||||
() -> mApexManager.installPackage(installedApex, mPackageParser2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstallPackageSignedWithWrongCertificate() throws Exception {
|
||||
File activeApex = extractResource("shim_v1", "com.android.apex.cts.shim.apex");
|
||||
ApexInfo activeApexInfo = createApexInfo("com.android.apex.cts.shim", 1,
|
||||
/* isActive= */ true, /* isFactory= */ false, activeApex);
|
||||
when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
File installedApex = extractResource("shim_different_certificate",
|
||||
"com.android.apex.cts.shim.v2_different_certificate.apex");
|
||||
PackageManagerException e = expectThrows(PackageManagerException.class,
|
||||
() -> mApexManager.installPackage(installedApex, mPackageParser2));
|
||||
assertThat(e).hasMessageThat().contains("APK container signature of ");
|
||||
assertThat(e).hasMessageThat().contains(
|
||||
"is not compatible with currently installed on device");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstallPackageUnsignedApexContainer() throws Exception {
|
||||
File activeApex = extractResource("shim_v1", "com.android.apex.cts.shim.apex");
|
||||
ApexInfo activeApexInfo = createApexInfo("com.android.apex.cts.shim", 1,
|
||||
/* isActive= */ true, /* isFactory= */ false, activeApex);
|
||||
when(mApexService.getAllPackages()).thenReturn(new ApexInfo[]{activeApexInfo});
|
||||
mApexManager.scanApexPackagesTraced(mPackageParser2,
|
||||
ParallelPackageParser.makeExecutorService());
|
||||
|
||||
File installedApex = extractResource("shim_unsigned_apk_container",
|
||||
"com.android.apex.cts.shim.v2_unsigned_apk_container.apex");
|
||||
PackageManagerException e = expectThrows(PackageManagerException.class,
|
||||
() -> mApexManager.installPackage(installedApex, mPackageParser2));
|
||||
assertThat(e).hasMessageThat().contains("Failed to collect certificates from ");
|
||||
}
|
||||
|
||||
private ApexInfo[] createApexInfoForTestPkg(boolean isActive, boolean isFactory) {
|
||||
File apexFile = extractResource(TEST_APEX_PKG, TEST_APEX_FILE_NAME);
|
||||
ApexInfo apexInfo = new ApexInfo();
|
||||
apexInfo.isActive = isActive;
|
||||
@@ -327,6 +434,17 @@ public class ApexManagerTest {
|
||||
return new ApexInfo[]{apexInfo};
|
||||
}
|
||||
|
||||
private ApexInfo createApexInfo(String moduleName, int versionCode, boolean isActive,
|
||||
boolean isFactory, File apexFile) {
|
||||
ApexInfo apexInfo = new ApexInfo();
|
||||
apexInfo.moduleName = moduleName;
|
||||
apexInfo.versionCode = versionCode;
|
||||
apexInfo.isActive = isActive;
|
||||
apexInfo.isFactory = isFactory;
|
||||
apexInfo.modulePath = apexFile.getPath();
|
||||
return apexInfo;
|
||||
}
|
||||
|
||||
private ApexSessionInfo getFakeStagedSessionInfo() {
|
||||
ApexSessionInfo stagedSessionInfo = new ApexSessionInfo();
|
||||
stagedSessionInfo.sessionId = TEST_SESSION_ID;
|
||||
@@ -358,6 +476,7 @@ public class ApexManagerTest {
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError("CreateTempFile IOException" + e);
|
||||
}
|
||||
|
||||
try (
|
||||
InputStream in = ApexManager.class.getClassLoader()
|
||||
.getResourceAsStream(fullResourceName);
|
||||
|
||||
Reference in New Issue
Block a user