Check for downgrade and signature of outer .apex certificate
This logic is very similar to the one in StagingManager. We can look into consolidating it in one place as one of follow up tasks. Bug: 188713546 Bug: 187864524 Test: atest ApexManagerTest Test: adb install --force-non-staged rebootless_v2.apex Test: adb install pm list packages --apex-only -f Change-Id: I12ff0ce121a349799062c76302de7c8f6407d8c2
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.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");
|
||||
}
|
||||
|
||||
|
||||
@@ -17120,7 +17120,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");
|
||||
@@ -17130,7 +17130,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