Merge "Finalize ENABLE_FEATURE_SCAN_APEX"
diff --git a/services/core/java/com/android/server/pm/ApexPackageInfo.java b/services/core/java/com/android/server/pm/ApexPackageInfo.java
deleted file mode 100644
index 672ae2e..0000000
--- a/services/core/java/com/android/server/pm/ApexPackageInfo.java
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (C) 2022 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.pm;
-
-import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE;
-import static com.android.server.pm.ApexManager.MATCH_FACTORY_PACKAGE;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.apex.ApexInfo;
-import android.content.pm.PackageManager;
-import android.util.ArrayMap;
-import android.util.Pair;
-import android.util.PrintWriterPrinter;
-
-import com.android.internal.annotations.GuardedBy;
-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.AndroidPackageUtils;
-import com.android.server.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.PackageStateInternal;
-import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-
-/**
- * A temporary holder to store PackageInfo for scanned apex packages. We will unify the scan/install
- * flows of APK and APEX and PMS will be the only source of truth for all package information
- * including both APK and APEX. This class will no longer be needed when the migration is done.
- */
-class ApexPackageInfo {
- public static final boolean ENABLE_FEATURE_SCAN_APEX = true;
-
- private static final String TAG = "ApexManager";
- private static final String VNDK_APEX_MODULE_NAME_PREFIX = "com.android.vndk.";
-
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private List<Pair<ApexInfo, AndroidPackage>> mAllPackagesCache;
-
- @Nullable
- private final PackageManagerService mPackageManager;
-
- ApexPackageInfo() {
- mPackageManager = null;
- }
-
- ApexPackageInfo(@NonNull PackageManagerService pms) {
- mPackageManager = pms;
- }
-
- /**
- * Called by package manager service to scan apex package files when device boots up.
- *
- * @param allPackages All apex packages to scan.
- * @param packageParser The package parser to support apex package parsing and caching parsed
- * results.
- * @param executorService An executor to support parallel package parsing.
- */
- List<ApexManager.ScanResult> scanApexPackages(ApexInfo[] allPackages,
- @NonNull PackageParser2 packageParser, @NonNull ExecutorService executorService) {
- synchronized (mLock) {
- return scanApexPackagesInternalLocked(allPackages, packageParser, executorService);
- }
- }
-
- void notifyScanResult(List<ApexManager.ScanResult> scanResults) {
- synchronized (mLock) {
- notifyScanResultLocked(scanResults);
- }
- }
-
- /**
- * Retrieves information about an APEX package.
- *
- * @param packageName the package name to look for. Note that this is the package name reported
- * in the APK container manifest (i.e. AndroidManifest.xml), which might
- * differ from the one reported in the APEX manifest (i.e.
- * apex_manifest.json).
- * @param flags the type of package to return. This may match to active packages
- * and factory (pre-installed) packages.
- * @return a PackageInfo object with the information about the package, or null if the package
- * is not found.
- */
- @Nullable
- Pair<ApexInfo, AndroidPackage> getPackageInfo(String packageName,
- @ApexManager.PackageInfoFlags int flags) {
- synchronized (mLock) {
- Preconditions.checkState(mAllPackagesCache != null,
- "APEX packages have not been scanned");
- boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0;
- boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0;
- for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) {
- final Pair<ApexInfo, AndroidPackage> pair = mAllPackagesCache.get(i);
- var apexInfo = pair.first;
- var pkg = pair.second;
- if (!pkg.getPackageName().equals(packageName)) {
- continue;
- }
- if ((matchActive && apexInfo.isActive)
- || (matchFactory && apexInfo.isFactory)) {
- return pair;
- }
- }
- return null;
- }
- }
-
- /**
- * Retrieves information about all active APEX packages.
- *
- * @return list containing information about different active packages.
- */
- @NonNull
- List<Pair<ApexInfo, AndroidPackage>> getActivePackages() {
- synchronized (mLock) {
- Preconditions.checkState(mAllPackagesCache != null,
- "APEX packages have not been scanned");
- final List<Pair<ApexInfo, AndroidPackage>> activePackages = new ArrayList<>();
- for (int i = 0; i < mAllPackagesCache.size(); i++) {
- final var pair = mAllPackagesCache.get(i);
- if (pair.first.isActive) {
- activePackages.add(pair);
- }
- }
- return activePackages;
- }
- }
-
- /**
- * Retrieves information about all pre-installed APEX packages.
- *
- * @return list containing information about different pre-installed packages.
- */
- @NonNull
- List<Pair<ApexInfo, AndroidPackage>> getFactoryPackages() {
- synchronized (mLock) {
- Preconditions.checkState(mAllPackagesCache != null,
- "APEX packages have not been scanned");
- final List<Pair<ApexInfo, AndroidPackage>> factoryPackages = new ArrayList<>();
- for (int i = 0; i < mAllPackagesCache.size(); i++) {
- final var pair = mAllPackagesCache.get(i);
- if (pair.first.isFactory) {
- factoryPackages.add(pair);
- }
- }
- return factoryPackages;
- }
- }
-
- /**
- * Retrieves information about all inactive APEX packages.
- *
- * @return list containing information about different inactive packages.
- */
- @NonNull
- List<Pair<ApexInfo, AndroidPackage>> getInactivePackages() {
- synchronized (mLock) {
- Preconditions.checkState(mAllPackagesCache != null,
- "APEX packages have not been scanned");
- final List<Pair<ApexInfo, AndroidPackage>> inactivePackages = new ArrayList<>();
- for (int i = 0; i < mAllPackagesCache.size(); i++) {
- final var pair = mAllPackagesCache.get(i);
- if (!pair.first.isActive) {
- inactivePackages.add(pair);
- }
- }
- return inactivePackages;
- }
- }
-
- /**
- * Checks if {@code packageName} is an apex package.
- *
- * @param packageName package to check.
- * @return {@code true} if {@code packageName} is an apex package.
- */
- boolean isApexPackage(String packageName) {
- synchronized (mLock) {
- Preconditions.checkState(mAllPackagesCache != null,
- "APEX packages have not been scanned");
- for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) {
- final var pair = mAllPackagesCache.get(i);
- if (pair.second.getPackageName().equals(packageName)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Called to update cached PackageInfo when installing rebootless APEX.
- */
- void notifyPackageInstalled(ApexInfo apexInfo, PackageParser2 packageParser)
- throws PackageManagerException {
- final int flags = PackageManager.GET_META_DATA
- | PackageManager.GET_SIGNING_CERTIFICATES
- | PackageManager.GET_SIGNATURES;
- final ParsedPackage parsedPackage = packageParser.parsePackage(
- new File(apexInfo.modulePath), flags, /* useCaches= */ false);
- notifyPackageInstalled(apexInfo, parsedPackage.hideAsFinal());
- }
-
- void notifyPackageInstalled(ApexInfo apexInfo, AndroidPackage pkg) {
- final String packageName = pkg.getPackageName();
- synchronized (mLock) {
- for (int i = 0, size = mAllPackagesCache.size(); i < size; i++) {
- var pair = mAllPackagesCache.get(i);
- var oldApexInfo = pair.first;
- var oldApexPkg = pair.second;
- if (oldApexInfo.isActive && oldApexPkg.getPackageName().equals(packageName)) {
- if (oldApexInfo.isFactory) {
- oldApexInfo.isActive = false;
- mAllPackagesCache.add(Pair.create(apexInfo, pkg));
- } else {
- mAllPackagesCache.set(i, Pair.create(apexInfo, pkg));
- }
- break;
- }
- }
- }
- }
-
- /**
- * Dumps various state information to the provided {@link PrintWriter} object.
- *
- * @param pw the {@link PrintWriter} object to send information to.
- * @param packageName a {@link String} containing a package name, or {@code null}. If set, only
- * information about that specific package will be dumped.
- */
- void dump(PrintWriter pw, @Nullable String packageName) {
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
- synchronized (mLock) {
- if (mAllPackagesCache == null) {
- ipw.println("APEX packages have not been scanned");
- return;
- }
- }
- ipw.println("Active APEX packages:");
- dumpPackages(getActivePackages(), packageName, ipw);
- ipw.println("Inactive APEX packages:");
- dumpPackages(getInactivePackages(), packageName, ipw);
- ipw.println("Factory APEX packages:");
- dumpPackages(getFactoryPackages(), packageName, ipw);
- }
-
- @GuardedBy("mLock")
- private void notifyScanResultLocked(List<ApexManager.ScanResult> scanResults) {
- mAllPackagesCache = new ArrayList<>();
- final int flags = PackageManager.GET_META_DATA
- | PackageManager.GET_SIGNING_CERTIFICATES
- | PackageManager.GET_SIGNATURES;
-
- HashSet<String> activePackagesSet = new HashSet<>();
- HashSet<String> factoryPackagesSet = new HashSet<>();
- for (ApexManager.ScanResult result : scanResults) {
- ApexInfo ai = result.apexInfo;
- String packageName = result.pkg.getPackageName();
- if (!packageName.equals(result.packageName)) {
- throw new IllegalStateException("Unmatched package name: "
- + result.packageName + " != " + packageName
- + ", path=" + ai.modulePath);
- }
- mAllPackagesCache.add(Pair.create(ai, result.pkg));
- if (ai.isActive) {
- if (!activePackagesSet.add(packageName)) {
- throw new IllegalStateException(
- "Two active packages have the same name: " + packageName);
- }
- }
- if (ai.isFactory) {
- // Don't throw when the duplicating APEX is VNDK APEX
- if (!factoryPackagesSet.add(packageName)
- && !ai.moduleName.startsWith(VNDK_APEX_MODULE_NAME_PREFIX)) {
- throw new IllegalStateException(
- "Two factory packages have the same name: " + packageName);
- }
- }
- }
- }
-
- @GuardedBy("mLock")
- private List<ApexManager.ScanResult> scanApexPackagesInternalLocked(final ApexInfo[] allPkgs,
- PackageParser2 packageParser, ExecutorService executorService) {
- if (allPkgs == null || allPkgs.length == 0) {
- notifyScanResultLocked(Collections.EMPTY_LIST);
- return Collections.EMPTY_LIST;
- }
-
- ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>();
- ParallelPackageParser parallelPackageParser =
- new ParallelPackageParser(packageParser, executorService);
- for (ApexInfo ai : allPkgs) {
- File apexFile = new File(ai.modulePath);
- parallelPackageParser.submit(apexFile,
- ParsingPackageUtils.PARSE_COLLECT_CERTIFICATES);
- parsingApexInfo.put(apexFile, ai);
- }
-
- List<ApexManager.ScanResult> results = new ArrayList<>(parsingApexInfo.size());
- // Process results one by one
- for (int i = 0; i < parsingApexInfo.size(); i++) {
- ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
- Throwable throwable = parseResult.throwable;
- ApexInfo ai = parsingApexInfo.get(parseResult.scanFile);
-
- if (throwable == null) {
- // TODO: When ENABLE_FEATURE_SCAN_APEX is finalized, remove this and the entire
- // calling path code
- ScanPackageUtils.applyPolicy(parseResult.parsedPackage,
- PackageManagerService.SCAN_AS_SYSTEM,
- mPackageManager == null ? null : mPackageManager.getPlatformPackage(),
- false);
- // Calling hideAsFinal to assign derived fields for the app info flags.
- AndroidPackage finalPkg = parseResult.parsedPackage.hideAsFinal();
- results.add(new ApexManager.ScanResult(ai, finalPkg, finalPkg.getPackageName()));
- } else if (throwable instanceof PackageManagerException) {
- throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable);
- } else {
- throw new IllegalStateException("Unexpected exception occurred while parsing "
- + ai.modulePath, throwable);
- }
- }
-
- notifyScanResultLocked(results);
- return results;
- }
-
- /**
- * @see #dumpPackages(List, String, IndentingPrintWriter)
- */
- static void dumpPackageStates(List<PackageStateInternal> packageStates, boolean isActive,
- @Nullable String packageName, IndentingPrintWriter ipw) {
- ipw.println();
- ipw.increaseIndent();
- for (int i = 0, size = packageStates.size(); i < size; i++) {
- final var packageState = packageStates.get(i);
- var pkg = packageState.getPkg();
- if (packageName != null && !packageName.equals(pkg.getPackageName())) {
- continue;
- }
- ipw.println(pkg.getPackageName());
- ipw.increaseIndent();
- ipw.println("Version: " + pkg.getLongVersionCode());
- ipw.println("Path: " + pkg.getBaseApkPath());
- ipw.println("IsActive: " + isActive);
- ipw.println("IsFactory: " + !packageState.isUpdatedSystemApp());
- ipw.println("ApplicationInfo: ");
- ipw.increaseIndent();
- // TODO: Dump the package manually
- AndroidPackageUtils.generateAppInfoWithoutState(pkg)
- .dump(new PrintWriterPrinter(ipw), "");
- ipw.decreaseIndent();
- ipw.decreaseIndent();
- }
- ipw.decreaseIndent();
- ipw.println();
- }
-
- /**
- * Dump information about the packages contained in a particular cache
- * @param packagesCache the cache to print information about.
- * @param packageName a {@link String} containing a package name, or {@code null}. If set,
- * only information about that specific package will be dumped.
- * @param ipw the {@link IndentingPrintWriter} object to send information to.
- */
- static void dumpPackages(List<Pair<ApexInfo, AndroidPackage>> packagesCache,
- @Nullable String packageName, IndentingPrintWriter ipw) {
- ipw.println();
- ipw.increaseIndent();
- for (int i = 0, size = packagesCache.size(); i < size; i++) {
- final var pair = packagesCache.get(i);
- var apexInfo = pair.first;
- var pkg = pair.second;
- if (packageName != null && !packageName.equals(pkg.getPackageName())) {
- continue;
- }
- ipw.println(pkg.getPackageName());
- ipw.increaseIndent();
- ipw.println("Version: " + pkg.getLongVersionCode());
- ipw.println("Path: " + pkg.getBaseApkPath());
- ipw.println("IsActive: " + apexInfo.isActive);
- ipw.println("IsFactory: " + apexInfo.isFactory);
- ipw.println("ApplicationInfo: ");
- ipw.increaseIndent();
- // TODO: Dump the package manually
- AndroidPackageUtils.generateAppInfoWithoutState(pkg)
- .dump(new PrintWriterPrinter(ipw), "");
- ipw.decreaseIndent();
- ipw.decreaseIndent();
- }
- ipw.decreaseIndent();
- ipw.println();
- }
-}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index b8e1e9a..f3cfa95 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -61,7 +61,7 @@
/**
* Prepares app data for users
*/
-final class AppDataHelper {
+public class AppDataHelper {
private static final boolean DEBUG_APP_DATA = false;
private final PackageManagerService mPm;
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index b9967f9..d381e32 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -63,7 +63,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
-import android.apex.ApexInfo;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -112,6 +111,7 @@
import android.util.LongSparseLongArray;
import android.util.MathUtils;
import android.util.Pair;
+import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
@@ -396,7 +396,6 @@
private final UserManagerService mUserManager;
private final PermissionManagerServiceInternal mPermissionManager;
private final ApexManager mApexManager;
- private final ApexPackageInfo mApexPackageInfo;
private final PackageManagerServiceInjector mInjector;
private final ComponentResolverApi mComponentResolver;
private final InstantAppResolverConnection mInstantAppResolverConnection;
@@ -452,7 +451,6 @@
mContext = args.service.mContext;
mInjector = args.service.mInjector;
mApexManager = args.service.mApexManager;
- mApexPackageInfo = args.service.mApexPackageInfo;
mInstantAppResolverConnection = args.service.mInstantAppResolverConnection;
mDefaultAppProvider = args.service.getDefaultAppProvider();
mDomainVerificationManager = args.service.mDomainVerificationManager;
@@ -968,10 +966,8 @@
if (p != null) {
PackageStateInternal ps = mSettings.getPackage(packageName);
if (ps == null) return null;
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (!matchApex && p.isApex()) {
- return null;
- }
+ if (!matchApex && p.isApex()) {
+ return null;
}
if (filterSharedLibPackage(ps, filterCallingUid, userId, flags)) {
return null;
@@ -987,24 +983,6 @@
}
return ai;
}
- if (!ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (matchApex) {
- // For APKs, PackageInfo.applicationInfo is not exactly the same as ApplicationInfo
- // returned from getApplicationInfo, but for APEX packages difference shouldn't be
- // very big.
- // TODO(b/155328545): generate proper application info for APEXes as well.
- int apexFlags = ApexManager.MATCH_ACTIVE_PACKAGE;
- if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
- apexFlags = ApexManager.MATCH_FACTORY_PACKAGE;
- }
- final var pair = mApexPackageInfo.getPackageInfo(packageName, apexFlags);
- if (pair == null) {
- return null;
- }
- return PackageInfoUtils.generateApplicationInfo(pair.second, flags,
- PackageUserStateInternal.DEFAULT, userId, null);
- }
- }
if ("android".equals(packageName) || "system".equals(packageName)) {
return androidApplication();
}
@@ -1553,22 +1531,10 @@
final boolean matchApex = (flags & MATCH_APEX) != 0;
if (matchFactoryOnly) {
// Instant app filtering for APEX modules is ignored
- if (!ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (matchApex) {
- final var pair = mApexPackageInfo.getPackageInfo(packageName,
- ApexManager.MATCH_FACTORY_PACKAGE);
- if (pair == null) {
- return null;
- }
- return PackageInfoUtils.generate(pair.second, pair.first, flags, null, userId);
- }
- }
final PackageStateInternal ps = mSettings.getDisabledSystemPkg(packageName);
if (ps != null) {
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (!matchApex && ps.getPkg() != null && ps.getPkg().isApex()) {
- return null;
- }
+ if (!matchApex && ps.getPkg() != null && ps.getPkg().isApex()) {
+ return null;
}
if (filterSharedLibPackage(ps, filterCallingUid, userId, flags)) {
return null;
@@ -1589,10 +1555,8 @@
}
if (p != null) {
final PackageStateInternal ps = getPackageStateInternal(p.getPackageName());
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (!matchApex && p.isApex()) {
- return null;
- }
+ if (!matchApex && p.isApex()) {
+ return null;
}
if (filterSharedLibPackage(ps, filterCallingUid, userId, flags)) {
return null;
@@ -1614,16 +1578,6 @@
}
return generatePackageInfo(ps, flags, userId);
}
- if (!ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (matchApex) {
- final var pair = mApexPackageInfo.getPackageInfo(packageName,
- ApexManager.MATCH_ACTIVE_PACKAGE);
- if (pair == null) {
- return null;
- }
- return PackageInfoUtils.generate(pair.second, pair.first, flags, null, userId);
- }
- }
return null;
}
@@ -1692,10 +1646,8 @@
ps = psDisabled;
}
}
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (!listApex && ps.getPkg() != null && ps.getPkg().isApex()) {
- continue;
- }
+ if (!listApex && ps.getPkg() != null && ps.getPkg().isApex()) {
+ continue;
}
if (filterSharedLibPackage(ps, callingUid, userId, flags)) {
continue;
@@ -1722,10 +1674,8 @@
ps = psDisabled;
}
}
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (!listApex && p.isApex()) {
- continue;
- }
+ if (!listApex && p.isApex()) {
+ continue;
}
if (filterSharedLibPackage(ps, callingUid, userId, flags)) {
continue;
@@ -1739,22 +1689,6 @@
}
}
}
- if (!ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (listApex) {
- List<Pair<ApexInfo, AndroidPackage>> pairs;
- if (listFactory) {
- pairs = mApexPackageInfo.getFactoryPackages();
- } else {
- pairs = mApexPackageInfo.getActivePackages();
- }
-
- for (int index = 0; index < pairs.size(); index++) {
- var pair = pairs.get(index);
- list.add(PackageInfoUtils.generate(pair.second, pair.first, flags, null,
- userId));
- }
- }
- }
return new ParceledListSlice<>(list);
}
@@ -3155,24 +3089,56 @@
}
private void dumpApex(PrintWriter pw, String packageName) {
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
- List<PackageStateInternal> activePackages = new ArrayList<>();
- List<PackageStateInternal> inactivePackages = new ArrayList<>();
- List<PackageStateInternal> factoryActivePackages = new ArrayList<>();
- List<PackageStateInternal> factoryInactivePackages = new ArrayList<>();
- generateApexPackageInfo(activePackages, inactivePackages, factoryActivePackages,
- factoryInactivePackages);
- ipw.println("Active APEX packages:");
- ApexPackageInfo.dumpPackageStates(activePackages, true, packageName, ipw);
- ipw.println("Inactive APEX packages:");
- ApexPackageInfo.dumpPackageStates(inactivePackages, false, packageName, ipw);
- ipw.println("Factory APEX packages:");
- ApexPackageInfo.dumpPackageStates(factoryActivePackages, true, packageName, ipw);
- ApexPackageInfo.dumpPackageStates(factoryInactivePackages, false, packageName, ipw);
- } else {
- mApexPackageInfo.dump(pw, packageName);
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ List<PackageStateInternal> activePackages = new ArrayList<>();
+ List<PackageStateInternal> inactivePackages = new ArrayList<>();
+ List<PackageStateInternal> factoryActivePackages = new ArrayList<>();
+ List<PackageStateInternal> factoryInactivePackages = new ArrayList<>();
+ generateApexPackageInfo(activePackages, inactivePackages, factoryActivePackages,
+ factoryInactivePackages);
+ ipw.println("Active APEX packages:");
+ dumpApexPackageStates(activePackages, true, packageName, ipw);
+ ipw.println("Inactive APEX packages:");
+ dumpApexPackageStates(inactivePackages, false, packageName, ipw);
+ ipw.println("Factory APEX packages:");
+ dumpApexPackageStates(factoryActivePackages, true, packageName, ipw);
+ dumpApexPackageStates(factoryInactivePackages, false, packageName, ipw);
+ }
+
+
+ /**
+ * Dump information about the packages contained in a particular cache
+ * @param packageStates the states to print information about.
+ * @param packageName a {@link String} containing a package name, or {@code null}. If set,
+ * only information about that specific package will be dumped.
+ * @param ipw the {@link IndentingPrintWriter} object to send information to.
+ */
+ private static void dumpApexPackageStates(List<PackageStateInternal> packageStates,
+ boolean isActive, @Nullable String packageName, IndentingPrintWriter ipw) {
+ ipw.println();
+ ipw.increaseIndent();
+ for (int i = 0, size = packageStates.size(); i < size; i++) {
+ final var packageState = packageStates.get(i);
+ var pkg = packageState.getPkg();
+ if (packageName != null && !packageName.equals(pkg.getPackageName())) {
+ continue;
+ }
+ ipw.println(pkg.getPackageName());
+ ipw.increaseIndent();
+ ipw.println("Version: " + pkg.getLongVersionCode());
+ ipw.println("Path: " + pkg.getBaseApkPath());
+ ipw.println("IsActive: " + isActive);
+ ipw.println("IsFactory: " + !packageState.isUpdatedSystemApp());
+ ipw.println("ApplicationInfo: ");
+ ipw.increaseIndent();
+ // TODO: Dump the package manually
+ AndroidPackageUtils.generateAppInfoWithoutState(pkg)
+ .dump(new PrintWriterPrinter(ipw), "");
+ ipw.decreaseIndent();
+ ipw.decreaseIndent();
}
+ ipw.decreaseIndent();
+ ipw.println();
}
// The body of findPreferredActivity.
@@ -3551,12 +3517,8 @@
@Override
public boolean isApexPackage(String packageName) {
- if (!ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- return mApexPackageInfo.isApexPackage(packageName);
- } else {
- final AndroidPackage pkg = mPackages.get(packageName);
- return pkg != null && pkg.isApex();
- }
+ final AndroidPackage pkg = mPackages.get(packageName);
+ return pkg != null && pkg.isApex();
}
@Override
@@ -4563,10 +4525,8 @@
effectiveFlags |= PackageManager.MATCH_ANY_USER;
}
if (ps.getPkg() != null) {
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (!listApex && ps.getPkg().isApex()) {
- continue;
- }
+ if (!listApex && ps.getPkg().isApex()) {
+ continue;
}
if (filterSharedLibPackage(ps, callingUid, userId, flags)) {
continue;
@@ -4596,10 +4556,8 @@
if (pkg == null) {
continue;
}
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- if (!listApex && pkg.isApex()) {
- continue;
- }
+ if (!listApex && pkg.isApex()) {
+ continue;
}
if (filterSharedLibPackage(packageState, Binder.getCallingUid(), userId, flags)) {
continue;
diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java
index 6f59096..12b5ab8 100644
--- a/services/core/java/com/android/server/pm/InitAppsHelper.java
+++ b/services/core/java/com/android/server/pm/InitAppsHelper.java
@@ -72,7 +72,6 @@
private final int mSystemScanFlags;
private final InstallPackageHelper mInstallPackageHelper;
private final ApexManager mApexManager;
- private final ApexPackageInfo mApexPackageInfo;
private final ExecutorService mExecutorService;
/* Tracks how long system scan took */
private long mSystemScanTime;
@@ -96,13 +95,11 @@
private final List<String> mStubSystemApps = new ArrayList<>();
// TODO(b/198166813): remove PMS dependency
- InitAppsHelper(PackageManagerService pm,
- ApexManager apexManager, ApexPackageInfo apexPackageInfo,
+ InitAppsHelper(PackageManagerService pm, ApexManager apexManager,
InstallPackageHelper installPackageHelper,
List<ScanPartition> systemPartitions) {
mPm = pm;
mApexManager = apexManager;
- mApexPackageInfo = apexPackageInfo;
mInstallPackageHelper = installPackageHelper;
mSystemPartitions = systemPartitions;
mDirsToScanAsSystem = getSystemScanPartitions();
@@ -165,16 +162,8 @@
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanApexPackages");
try {
- final List<ApexManager.ScanResult> apexScanResults;
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- apexScanResults = mInstallPackageHelper.scanApexPackages(
- mApexManager.getAllApexInfos(), mSystemParseFlags, mSystemScanFlags,
- packageParser, mExecutorService);
- } else {
- apexScanResults = mApexPackageInfo.scanApexPackages(
- mApexManager.getAllApexInfos(), packageParser, mExecutorService);
- }
- return apexScanResults;
+ return mInstallPackageHelper.scanApexPackages(mApexManager.getAllApexInfos(),
+ mSystemParseFlags, mSystemScanFlags, packageParser, mExecutorService);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java
index 16b3a81..88469f5 100644
--- a/services/core/java/com/android/server/pm/InstallingSession.java
+++ b/services/core/java/com/android/server/pm/InstallingSession.java
@@ -572,19 +572,15 @@
}
try (PackageParser2 packageParser = mPm.mInjector.getScanningPackageParser()) {
ApexInfo apexInfo = mPm.mApexManager.installPackage(apexes[0]);
- if (ApexPackageInfo.ENABLE_FEATURE_SCAN_APEX) {
- // APEX has been handled successfully by apexd. Let's continue the install flow
- // so it will be scanned and registered with the system.
- // TODO(b/225756739): Improve atomicity of rebootless APEX install.
- // The newly installed APEX will not be reverted even if
- // processApkInstallRequests() fails. Need a way to keep info stored in apexd
- // and PMS in sync in the face of install failures.
- request.setApexInfo(apexInfo);
- mPm.mHandler.post(() -> processApkInstallRequests(true, requests));
- return;
- } else {
- mPm.mApexPackageInfo.notifyPackageInstalled(apexInfo, packageParser);
- }
+ // APEX has been handled successfully by apexd. Let's continue the install flow
+ // so it will be scanned and registered with the system.
+ // TODO(b/225756739): Improve atomicity of rebootless APEX install.
+ // The newly installed APEX will not be reverted even if
+ // processApkInstallRequests() fails. Need a way to keep info stored in apexd
+ // and PMS in sync in the face of install failures.
+ request.setApexInfo(apexInfo);
+ mPm.mHandler.post(() -> processApkInstallRequests(true, requests));
+ return;
}
} catch (PackageManagerException e) {
request.setError("APEX installation failed", e);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 23cf262..b979e7a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -690,7 +690,6 @@
private final ModuleInfoProvider mModuleInfoProvider;
final ApexManager mApexManager;
- final ApexPackageInfo mApexPackageInfo;
final PackageManagerServiceInjector mInjector;
@@ -1641,7 +1640,6 @@
mSharedLibraries = injector.getSharedLibrariesImpl();
mApexManager = testParams.apexManager;
- mApexPackageInfo = new ApexPackageInfo(this);
mArtManagerService = testParams.artManagerService;
mAvailableFeatures = testParams.availableFeatures;
mBackgroundDexOptService = testParams.backgroundDexOptService;
@@ -1841,7 +1839,6 @@
mProtectedPackages = new ProtectedPackages(mContext);
mApexManager = injector.getApexManager();
- mApexPackageInfo = new ApexPackageInfo(this);
mAppsFilter = mInjector.getAppsFilter();
mInstantAppRegistry = new InstantAppRegistry(mContext, mPermissionManager,
@@ -1979,8 +1976,8 @@
+ ver.fingerprint + " to " + PackagePartitions.FINGERPRINT);
}
- mInitAppsHelper = new InitAppsHelper(this, mApexManager, mApexPackageInfo,
- mInstallPackageHelper, mInjector.getSystemPartitions());
+ mInitAppsHelper = new InitAppsHelper(this, mApexManager, mInstallPackageHelper,
+ mInjector.getSystemPartitions());
// when upgrading from pre-M, promote system app permissions from install to runtime
mPromoteSystemApps =
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 16317fe..73b1907c 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -78,6 +78,12 @@
"servicestests-core-utils",
],
+ java_resources: [
+ ":apex.test",
+ ":test.rebootless_apex_v1",
+ ":test.rebootless_apex_v2",
+ ],
+
jni_libs: [
"libpsi",
],
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
similarity index 64%
rename from services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
rename to services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
index a7739ed..aabec22 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -31,25 +31,29 @@
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.apex.ApexInfo;
import android.apex.ApexSessionInfo;
import android.apex.ApexSessionParams;
import android.apex.IApexService;
-import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.pm.parsing.PackageParser2;
-import com.android.server.pm.parsing.TestPackageParser2;
import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -60,88 +64,139 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
+import java.util.Objects;
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public class ApexManagerTest {
+
+ @Rule
+ public final MockSystemRule mMockSystem = new MockSystemRule();
+
private static final String TEST_APEX_PKG = "com.android.apex.test";
private static final String TEST_APEX_FILE_NAME = "apex.test.apex";
private static final int TEST_SESSION_ID = 99999999;
private static final int[] TEST_CHILD_SESSION_ID = {8888, 7777};
private ApexManager mApexManager;
- private Context mContext;
private PackageParser2 mPackageParser2;
private IApexService mApexService = mock(IApexService.class);
+ private PackageManagerService mPmService;
+
+ private InstallPackageHelper mInstallPackageHelper;
+
@Before
- public void setUp() throws RemoteException {
- mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ public void setUp() throws Exception {
ApexManager.ApexManagerImpl managerImpl = spy(new ApexManager.ApexManagerImpl());
doReturn(mApexService).when(managerImpl).waitForApexService();
+ when(mApexService.getActivePackages()).thenReturn(new ApexInfo[0]);
mApexManager = managerImpl;
- mPackageParser2 = new TestPackageParser2();
+ mPackageParser2 = new PackageParser2(null, null, null, new PackageParser2.Callback() {
+ @Override
+ public boolean isChangeEnabled(long changeId, @NonNull ApplicationInfo appInfo) {
+ return true;
+ }
+
+ @Override
+ public boolean hasFeature(String feature) {
+ return true;
+ }
+ });
+
+ mMockSystem.system().stageNominalSystemState();
+ mPmService = new PackageManagerService(mMockSystem.mocks().getInjector(),
+ false /*factoryTest*/,
+ MockSystem.Companion.getDEFAULT_VERSION_INFO().fingerprint,
+ false /*isEngBuild*/,
+ false /*isUserDebugBuild*/,
+ Build.VERSION_CODES.CUR_DEVELOPMENT,
+ Build.VERSION.INCREMENTAL);
+ mMockSystem.system().validateFinalState();
+ mInstallPackageHelper = new InstallPackageHelper(mPmService, mock(AppDataHelper.class));
+ }
+
+ @NonNull
+ private List<ApexManager.ScanResult> scanApexInfos(ApexInfo[] apexInfos) {
+ return mInstallPackageHelper.scanApexPackages(apexInfos,
+ ParsingPackageUtils.PARSE_IS_SYSTEM_DIR,
+ PackageManagerService.SCAN_AS_SYSTEM, mPackageParser2,
+ ParallelPackageParser.makeExecutorService());
+ }
+
+ @Nullable
+ private ApexManager.ScanResult findActive(@NonNull List<ApexManager.ScanResult> results) {
+ return results.stream()
+ .filter(it -> it.apexInfo.isActive)
+ .filter(it -> Objects.equals(it.packageName, TEST_APEX_PKG))
+ .findFirst()
+ .orElse(null);
+ }
+
+ @Nullable
+ private ApexManager.ScanResult findFactory(@NonNull List<ApexManager.ScanResult> results,
+ @NonNull String packageName) {
+ return results.stream()
+ .filter(it -> it.apexInfo.isFactory)
+ .filter(it -> Objects.equals(it.packageName, packageName))
+ .findFirst()
+ .orElse(null);
+ }
+
+ @NonNull
+ private AndroidPackage mockParsePackage(@NonNull PackageParser2 parser,
+ @NonNull ApexInfo apexInfo) {
+ var flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES;
+ try {
+ var parsedPackage = parser.parsePackage(new File(apexInfo.modulePath), flags,
+ /* useCaches= */ false);
+ ScanPackageUtils.applyPolicy(parsedPackage,
+ PackageManagerService.SCAN_AS_APEX | PackageManagerService.SCAN_AS_SYSTEM,
+ mPmService.getPlatformPackage(), /* isUpdatedSystemApp */ false);
+ // isUpdatedSystemApp is ignoreable above, only used for shared library adjustment
+ return parsedPackage.hideAsFinal();
+ } catch (PackageManagerException e) {
+ throw new RuntimeException(e);
+ }
}
@Test
- public void testGetPackageInfo_setFlagsMatchActivePackage() throws RemoteException {
- ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
- final var activePair = apexPackageInfo.getPackageInfo(TEST_APEX_PKG,
- ApexManager.MATCH_ACTIVE_PACKAGE);
+ public void testScanActivePackage() {
+ var apexInfos = createApexInfoForTestPkg(true, false);
+ var results = scanApexInfos(apexInfos);
+ var active = findActive(results);
+ var factory = findFactory(results, TEST_APEX_PKG);
- assertThat(activePair).isNotNull();
- assertThat(activePair.second.getPackageName()).contains(TEST_APEX_PKG);
+ assertThat(active).isNotNull();
+ assertThat(active.packageName).isEqualTo(TEST_APEX_PKG);
- final var factoryPair = apexPackageInfo.getPackageInfo(TEST_APEX_PKG,
- ApexManager.MATCH_FACTORY_PACKAGE);
-
- assertThat(factoryPair).isNull();
+ assertThat(factory).isNull();
}
@Test
- public void testGetPackageInfo_setFlagsMatchFactoryPackage() throws RemoteException {
- ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
- var factoryPair = apexPackageInfo.getPackageInfo(TEST_APEX_PKG,
- ApexManager.MATCH_FACTORY_PACKAGE);
+ public void testScanFactoryPackage() {
+ var apexInfos = createApexInfoForTestPkg(false, true);
+ var results = scanApexInfos(apexInfos);
+ var active = findActive(results);
+ var factory = findFactory(results, TEST_APEX_PKG);
- assertThat(factoryPair).isNotNull();
- assertThat(factoryPair.second.getPackageName()).contains(TEST_APEX_PKG);
+ assertThat(factory).isNotNull();
+ assertThat(factory.packageName).contains(TEST_APEX_PKG);
- final var activePair = apexPackageInfo.getPackageInfo(TEST_APEX_PKG,
- ApexManager.MATCH_ACTIVE_PACKAGE);
-
- assertThat(activePair).isNull();
+ assertThat(active).isNull();
}
@Test
- public void testGetPackageInfo_setFlagsNone() throws RemoteException {
- ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
-
- assertThat(apexPackageInfo.getPackageInfo(TEST_APEX_PKG, 0)).isNull();
- }
-
- @Test
- public void testGetApexSystemServices() throws RemoteException {
- ApexInfo[] apexInfo = new ApexInfo[] {
+ public void testGetApexSystemServices() {
+ ApexInfo[] apexInfo = new ApexInfo[]{
createApexInfoForTestPkg(false, true, 1),
// only active apex reports apex-system-service
createApexInfoForTestPkg(true, false, 2),
};
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- List<ApexManager.ScanResult> scanResults = apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
+ List<ApexManager.ScanResult> scanResults = scanApexInfos(apexInfo);
mApexManager.notifyScanResult(scanResults);
List<ApexSystemServiceInfo> services = mApexManager.getApexSystemServices();
@@ -151,73 +206,11 @@
}
@Test
- public void testGetActivePackages() throws RemoteException {
- ApexInfo[] apexInfo = createApexInfoForTestPkg(true, true);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
-
- assertThat(apexPackageInfo.getActivePackages()).isNotEmpty();
- }
-
- @Test
- public void testGetActivePackages_noneActivePackages() throws RemoteException {
- ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
-
- assertThat(apexPackageInfo.getActivePackages()).isEmpty();
- }
-
- @Test
- public void testGetFactoryPackages() throws RemoteException {
- ApexInfo [] apexInfo = createApexInfoForTestPkg(false, true);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
-
- assertThat(apexPackageInfo.getFactoryPackages()).isNotEmpty();
- }
-
- @Test
- public void testGetFactoryPackages_noneFactoryPackages() throws RemoteException {
- ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
-
- assertThat(apexPackageInfo.getFactoryPackages()).isEmpty();
- }
-
- @Test
- public void testGetInactivePackages() throws RemoteException {
- ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
-
- assertThat(apexPackageInfo.getInactivePackages()).isNotEmpty();
- }
-
- @Test
- public void testGetInactivePackages_noneInactivePackages() throws RemoteException {
- ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
-
- assertThat(apexPackageInfo.getInactivePackages()).isEmpty();
- }
-
- @Test
- public void testIsApexPackage() throws RemoteException {
- ApexInfo[] apexInfo = createApexInfoForTestPkg(false, true);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
-
- assertThat(apexPackageInfo.isApexPackage(TEST_APEX_PKG)).isTrue();
+ public void testIsApexPackage() {
+ var apexInfos = createApexInfoForTestPkg(false, true);
+ var results = scanApexInfos(apexInfos);
+ var factory = findFactory(results, TEST_APEX_PKG);
+ assertThat(factory.pkg.isApex()).isTrue();
}
@Test
@@ -328,16 +321,14 @@
assertThat(activeApex.apexModuleName).isEqualTo(TEST_APEX_PKG);
ApexInfo[] apexInfo = createApexInfoForTestPkg(true, true);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- List<ApexManager.ScanResult> scanResults = apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
+ List<ApexManager.ScanResult> scanResults = scanApexInfos(apexInfo);
mApexManager.notifyScanResult(scanResults);
assertThat(mApexManager.getApkInApexInstallError(activeApex.apexModuleName)).isNull();
mApexManager.reportErrorWithApkInApex(activeApex.apexDirectory.getAbsolutePath(),
"Some random error");
assertThat(mApexManager.getApkInApexInstallError(activeApex.apexModuleName))
- .isEqualTo("Some random error");
+ .isEqualTo("Some random error");
}
/**
@@ -357,9 +348,7 @@
when(fakeApkInApex.getPackageName()).thenReturn("randomPackageName");
ApexInfo[] apexInfo = createApexInfoForTestPkg(true, true);
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- List<ApexManager.ScanResult> scanResults = apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
+ List<ApexManager.ScanResult> scanResults = scanApexInfos(apexInfo);
mApexManager.notifyScanResult(scanResults);
assertThat(mApexManager.getApksInApex(activeApex.apexModuleName)).isEmpty();
@@ -371,11 +360,9 @@
public void testInstallPackage_activeOnSystem() throws Exception {
ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true,
/* isFactory= */ true, extractResource("test.apex_rebootless_v1",
- "test.rebootless_apex_v1.apex"));
+ "test.rebootless_apex_v1.apex"));
ApexInfo[] apexInfo = new ApexInfo[]{activeApexInfo};
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
+ var results = scanApexInfos(apexInfo);
File finalApex = extractResource("test.rebootles_apex_v2", "test.rebootless_apex_v2.apex");
ApexInfo newApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true,
@@ -384,32 +371,28 @@
File installedApex = extractResource("installed", "test.rebootless_apex_v2.apex");
newApexInfo = mApexManager.installPackage(installedApex);
- apexPackageInfo.notifyPackageInstalled(newApexInfo, mPackageParser2);
- var newInfo = apexPackageInfo.getPackageInfo("test.apex.rebootless",
- ApexManager.MATCH_ACTIVE_PACKAGE);
- assertThat(newInfo.second.getBaseApkPath()).isEqualTo(finalApex.getAbsolutePath());
- assertThat(newInfo.second.getLongVersionCode()).isEqualTo(2);
+ var newPkg = mockParsePackage(mPackageParser2, newApexInfo);
+ assertThat(newPkg.getBaseApkPath()).isEqualTo(finalApex.getAbsolutePath());
+ assertThat(newPkg.getLongVersionCode()).isEqualTo(2);
- var factoryInfo = apexPackageInfo.getPackageInfo("test.apex.rebootless",
- ApexManager.MATCH_FACTORY_PACKAGE);
- assertThat(factoryInfo.second.getBaseApkPath()).isEqualTo(activeApexInfo.modulePath);
- assertThat(factoryInfo.second.getLongVersionCode()).isEqualTo(1);
- assertThat(factoryInfo.second.isSystem()).isTrue();
+ var factoryPkg = mockParsePackage(mPackageParser2,
+ findFactory(results, "test.apex.rebootless").apexInfo);
+ assertThat(factoryPkg.getBaseApkPath()).isEqualTo(activeApexInfo.modulePath);
+ assertThat(factoryPkg.getLongVersionCode()).isEqualTo(1);
+ assertThat(factoryPkg.isSystem()).isTrue();
}
@Test
public void testInstallPackage_activeOnData() throws Exception {
ApexInfo factoryApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ false,
/* isFactory= */ true, extractResource("test.apex_rebootless_v1",
- "test.rebootless_apex_v1.apex"));
+ "test.rebootless_apex_v1.apex"));
ApexInfo activeApexInfo = createApexInfo("test.apex_rebootless", 1, /* isActive= */ true,
/* isFactory= */ false, extractResource("test.apex.rebootless@1",
- "test.rebootless_apex_v1.apex"));
+ "test.rebootless_apex_v1.apex"));
ApexInfo[] apexInfo = new ApexInfo[]{factoryApexInfo, activeApexInfo};
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
+ var results = scanApexInfos(apexInfo);
File finalApex = extractResource("test.rebootles_apex_v2", "test.rebootless_apex_v2.apex");
ApexInfo newApexInfo = createApexInfo("test.apex_rebootless", 2, /* isActive= */ true,
@@ -418,30 +401,20 @@
File installedApex = extractResource("installed", "test.rebootless_apex_v2.apex");
newApexInfo = mApexManager.installPackage(installedApex);
- apexPackageInfo.notifyPackageInstalled(newApexInfo, mPackageParser2);
- var newInfo = apexPackageInfo.getPackageInfo("test.apex.rebootless",
- ApexManager.MATCH_ACTIVE_PACKAGE);
- assertThat(newInfo.second.getBaseApkPath()).isEqualTo(finalApex.getAbsolutePath());
- assertThat(newInfo.second.getLongVersionCode()).isEqualTo(2);
+ var newPkg = mockParsePackage(mPackageParser2, newApexInfo);
+ assertThat(newPkg.getBaseApkPath()).isEqualTo(finalApex.getAbsolutePath());
+ assertThat(newPkg.getLongVersionCode()).isEqualTo(2);
- var factoryInfo = apexPackageInfo.getPackageInfo("test.apex.rebootless",
- ApexManager.MATCH_FACTORY_PACKAGE);
- assertThat(factoryInfo.second.getBaseApkPath()).isEqualTo(factoryApexInfo.modulePath);
- assertThat(factoryInfo.second.getLongVersionCode()).isEqualTo(1);
- assertThat(factoryInfo.second.isSystem()).isTrue();
+ var factoryPkg = mockParsePackage(mPackageParser2,
+ findFactory(results, "test.apex.rebootless").apexInfo);
+ assertThat(factoryPkg.getBaseApkPath()).isEqualTo(factoryApexInfo.modulePath);
+ assertThat(factoryPkg.getLongVersionCode()).isEqualTo(1);
+ assertThat(factoryPkg.isSystem()).isTrue();
}
@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"));
- ApexInfo[] apexInfo = new ApexInfo[]{activeApexInfo};
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
-
when(mApexService.installAndActivatePackage(anyString())).thenThrow(
new RuntimeException("install failed :("));
@@ -452,14 +425,12 @@
}
@Test
- public void testGetActivePackageNameForApexModuleName() throws Exception {
+ public void testGetActivePackageNameForApexModuleName() {
final String moduleName = "com.android.module_name";
ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false);
apexInfo[0].moduleName = moduleName;
- ApexPackageInfo apexPackageInfo = new ApexPackageInfo();
- List<ApexManager.ScanResult> scanResults = apexPackageInfo.scanApexPackages(
- apexInfo, mPackageParser2, ParallelPackageParser.makeExecutorService());
+ List<ApexManager.ScanResult> scanResults = scanApexInfos(apexInfo);
mApexManager.notifyScanResult(scanResults);
assertThat(mApexManager.getActivePackageNameForApexModuleName(moduleName))
@@ -472,12 +443,13 @@
when(mApexService.getActivePackages()).thenReturn(new ApexInfo[]{apex});
final File backingApexFile = mApexManager.getBackingApexFile(
- new File("/apex/" + TEST_APEX_PKG + "/apk/App/App.apk"));
+ new File(mMockSystem.system().getApexDirectory(),
+ TEST_APEX_PKG + "/apk/App/App.apk"));
assertThat(backingApexFile.getAbsolutePath()).isEqualTo(apex.modulePath);
}
@Test
- public void testGetBackingApexFile_fileNotOnApexMountPoint_returnsNull() throws Exception {
+ public void testGetBackingApexFile_fileNotOnApexMountPoint_returnsNull() {
File result = mApexManager.getBackingApexFile(
new File("/data/local/tmp/whatever/does-not-matter"));
assertThat(result).isNull();
@@ -489,22 +461,23 @@
when(mApexService.getActivePackages()).thenReturn(new ApexInfo[]{apex});
final File backingApexFile = mApexManager.getBackingApexFile(
- new File("/apex/com.wrong.apex/apk/App"));
+ new File(mMockSystem.system().getApexDirectory(), "com.wrong.apex/apk/App"));
assertThat(backingApexFile).isNull();
}
@Test
- public void testGetBackingApexFiles_topLevelApexDir_returnsNull() throws Exception {
+ public void testGetBackingApexFiles_topLevelApexDir_returnsNull() {
assertThat(mApexManager.getBackingApexFile(Environment.getApexDirectory())).isNull();
assertThat(mApexManager.getBackingApexFile(new File("/apex/"))).isNull();
assertThat(mApexManager.getBackingApexFile(new File("/apex//"))).isNull();
}
@Test
- public void testGetBackingApexFiles_flattenedApex() throws Exception {
+ public void testGetBackingApexFiles_flattenedApex() {
ApexManager flattenedApexManager = new ApexManager.ApexManagerFlattenedApex();
final File backingApexFile = flattenedApexManager.getBackingApexFile(
- new File("/apex/com.android.apex.cts.shim/app/CtsShim/CtsShim.apk"));
+ new File(mMockSystem.system().getApexDirectory(),
+ "com.android.apex.cts.shim/app/CtsShim/CtsShim.apk"));
assertThat(backingApexFile).isNull();
}
@@ -521,7 +494,7 @@
}
private ApexInfo createApexInfoForTestPkg(boolean isActive, boolean isFactory, int version) {
- File apexFile = extractResource(TEST_APEX_PKG, TEST_APEX_FILE_NAME);
+ File apexFile = extractResource(TEST_APEX_PKG, TEST_APEX_FILE_NAME);
ApexInfo apexInfo = new ApexInfo();
apexInfo.isActive = isActive;
apexInfo.isFactory = isFactory;
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt
index 2165301..15b4975 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt
@@ -83,7 +83,7 @@
val pms = createPackageManagerService()
assertThat(pms.isFirstBoot).isEqualTo(true)
assertThat(pms.isDeviceUpgrading).isEqualTo(false)
- val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+ val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null,
listOf<ScanPartition>())
assertThat(
initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
@@ -98,7 +98,7 @@
val pms = createPackageManagerService()
assertThat(pms.isFirstBoot).isEqualTo(false)
assertThat(pms.isDeviceUpgrading).isEqualTo(true)
- val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+ val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null,
listOf<ScanPartition>())
assertThat(
initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
@@ -112,7 +112,7 @@
val pms = createPackageManagerService()
assertThat(pms.isFirstBoot).isEqualTo(false)
assertThat(pms.isDeviceUpgrading).isEqualTo(false)
- val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+ val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null,
listOf<ScanPartition>())
assertThat(
initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
@@ -126,7 +126,7 @@
val pms = createPackageManagerService()
assertThat(pms.isFirstBoot).isEqualTo(false)
assertThat(pms.isDeviceUpgrading).isEqualTo(true)
- val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+ val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null,
listOf<ScanPartition>())
assertThat(
initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index dc7bcd6..dd6c733 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -78,14 +78,6 @@
import com.android.server.testutils.nullable
import com.android.server.testutils.whenever
import com.android.server.utils.WatchedArrayMap
-import java.io.File
-import java.io.IOException
-import java.nio.file.Files
-import java.security.PublicKey
-import java.security.cert.CertificateException
-import java.util.Arrays
-import java.util.Random
-import java.util.concurrent.FutureTask
import libcore.util.HexEncoding
import org.junit.Assert
import org.junit.rules.TestRule
@@ -94,6 +86,14 @@
import org.mockito.AdditionalMatchers.or
import org.mockito.Mockito
import org.mockito.quality.Strictness
+import java.io.File
+import java.io.IOException
+import java.nio.file.Files
+import java.security.PublicKey
+import java.security.cert.CertificateException
+import java.util.Arrays
+import java.util.Random
+import java.util.concurrent.FutureTask
/**
* A utility for mocking behavior of the system and dependencies when testing PackageManagerService
@@ -104,6 +104,9 @@
class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
private val random = Random()
val mocks = Mocks()
+
+ // TODO: getBackingApexFile does not handle paths that aren't /apex
+ val apexDirectory = File("/apex")
val packageCacheDirectory: File =
Files.createTempDirectory("packageCache").toFile()
val rootDirectory: File =
@@ -297,7 +300,9 @@
whenever(mocks.systemConfig.sharedLibraries).thenReturn(DEFAULT_SHARED_LIBRARIES_LIST)
whenever(mocks.systemConfig.defaultVrComponents).thenReturn(ArraySet())
whenever(mocks.systemConfig.hiddenApiWhitelistedApps).thenReturn(ArraySet())
+ wheneverStatic { SystemProperties.set(anyString(), anyString()) }.thenDoNothing()
wheneverStatic { SystemProperties.getBoolean("fw.free_cache_v2", true) }.thenReturn(true)
+ wheneverStatic { Environment.getApexDirectory() }.thenReturn(apexDirectory)
wheneverStatic { Environment.getPackageCacheDirectory() }.thenReturn(packageCacheDirectory)
wheneverStatic { SystemProperties.digestOf("ro.build.fingerprint") }.thenReturn("cacheName")
wheneverStatic { Environment.getRootDirectory() }.thenReturn(rootDirectory)
diff --git a/services/tests/mockingservicestests/utils-mockito/com/android/server/extendedtestutils/ExtendedMockitoUtils.kt b/services/tests/mockingservicestests/utils-mockito/com/android/server/extendedtestutils/ExtendedMockitoUtils.kt
index 72ae77e..a0a67439 100644
--- a/services/tests/mockingservicestests/utils-mockito/com/android/server/extendedtestutils/ExtendedMockitoUtils.kt
+++ b/services/tests/mockingservicestests/utils-mockito/com/android/server/extendedtestutils/ExtendedMockitoUtils.kt
@@ -33,9 +33,14 @@
override fun thenReturn(value: T) {
ExtendedMockito.doReturn(value).wheneverStatic(mockedMethod)
}
+
+ override fun thenDoNothing() {
+ ExtendedMockito.doNothing().wheneverStatic(mockedMethod)
+ }
}
interface CustomStaticStubber<T> {
fun thenAnswer(answer: Answer<T>)
fun thenReturn(value: T)
+ fun thenDoNothing()
}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 8a932f1..61bb57e 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -124,9 +124,6 @@
":PackageParserTestApp4",
":PackageParserTestApp5",
":PackageParserTestApp6",
- ":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",