Merge "Fix an exception while scanning apex packages" into rvc-dev am: 2aab1a4d49 am: c74e158db3

Change-Id: I97b8cd8071348d40531373b2a0c1a77164eb5594
This commit is contained in:
Rhed Jao
2020-04-07 09:17:35 +00:00
committed by Automerger Merge Worker
6 changed files with 52 additions and 16 deletions

View File

@@ -1542,6 +1542,14 @@ public abstract class PackageManager {
*/ */
public static final int INSTALL_FAILED_PROCESS_NOT_DEFINED = -122; public static final int INSTALL_FAILED_PROCESS_NOT_DEFINED = -122;
/**
* Installation parse return code: system is in a minimal boot state, and the parser only
* allows the package with {@code coreApp} manifest attribute to be a valid application.
*
* @hide
*/
public static final int INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED = -123;
/** @hide */ /** @hide */
@IntDef(flag = true, prefix = { "DELETE_" }, value = { @IntDef(flag = true, prefix = { "DELETE_" }, value = {
DELETE_KEEP_DATA, DELETE_KEEP_DATA,

View File

@@ -22,6 +22,7 @@ import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
import static android.os.Build.VERSION_CODES.DONUT; import static android.os.Build.VERSION_CODES.DONUT;
import static android.os.Build.VERSION_CODES.O; import static android.os.Build.VERSION_CODES.O;
@@ -229,7 +230,8 @@ public class ParsingPackageUtils {
final PackageParser.PackageLite lite = ApkLiteParseUtils.parseClusterPackageLite(packageDir, final PackageParser.PackageLite lite = ApkLiteParseUtils.parseClusterPackageLite(packageDir,
0); 0);
if (mOnlyCoreApps && !lite.coreApp) { if (mOnlyCoreApps && !lite.coreApp) {
return input.error("Not a coreApp: " + packageDir); return input.error(INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED,
"Not a coreApp: " + packageDir);
} }
// Build the split dependency tree. // Build the split dependency tree.
@@ -291,7 +293,8 @@ public class ParsingPackageUtils {
final PackageParser.PackageLite lite = ApkLiteParseUtils.parseMonolithicPackageLite(apkFile, final PackageParser.PackageLite lite = ApkLiteParseUtils.parseMonolithicPackageLite(apkFile,
flags); flags);
if (mOnlyCoreApps && !lite.coreApp) { if (mOnlyCoreApps && !lite.coreApp) {
return input.error("Not a coreApp: " + apkFile); return input.error(INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED,
"Not a coreApp: " + apkFile);
} }
final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags); final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);

View File

@@ -30,7 +30,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller; import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageParser; import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.parsing.PackageInfoWithoutStateUtils; import android.content.pm.parsing.PackageInfoWithoutStateUtils;
import android.os.Binder; import android.os.Binder;
import android.os.Environment; import android.os.Environment;
@@ -137,7 +137,8 @@ public abstract class ApexManager {
/** /**
* Called by package manager service to scan apex package files when device boots up. * Called by package manager service to scan apex package files when device boots up.
* *
* @param packageParser The package parser which supports caches. * @param packageParser The package parser to support apex package parsing and caching parsed
* results.
* @param executorService An executor to support parallel package parsing. * @param executorService An executor to support parallel package parsing.
*/ */
abstract void scanApexPackagesTraced(@NonNull PackageParser2 packageParser, abstract void scanApexPackagesTraced(@NonNull PackageParser2 packageParser,
@@ -505,7 +506,13 @@ public abstract class ApexManager {
} }
factoryPackagesSet.add(packageInfo.packageName); factoryPackagesSet.add(packageInfo.packageName);
} }
} else if (throwable instanceof PackageParser.PackageParserException) { } else if (throwable instanceof PackageParserException) {
final PackageParserException e = (PackageParserException) throwable;
// Skip parsing non-coreApp apex file if system is in minimal boot state.
if (e.error == PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED) {
Slog.w(TAG, "Scan apex failed, not a coreApp:" + ai.modulePath);
continue;
}
throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable); throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable);
} else { } else {
throw new IllegalStateException("Unexpected exception occurred while parsing " throw new IllegalStateException("Unexpected exception occurred while parsing "

View File

@@ -82,6 +82,7 @@ import com.android.internal.util.ImageUtils;
import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.IndentingPrintWriter;
import com.android.server.IoThread; import com.android.server.IoThread;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.permission.PermissionManagerServiceInternal; import com.android.server.pm.permission.PermissionManagerServiceInternal;
import libcore.io.IoUtils; import libcore.io.IoUtils;
@@ -105,6 +106,7 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Random; import java.util.Random;
import java.util.function.IntPredicate; import java.util.function.IntPredicate;
import java.util.function.Supplier;
/** The service responsible for installing packages. */ /** The service responsible for installing packages. */
public class PackageInstallerService extends IPackageInstaller.Stub implements public class PackageInstallerService extends IPackageInstaller.Stub implements
@@ -194,7 +196,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
} }
}; };
public PackageInstallerService(Context context, PackageManagerService pm) { public PackageInstallerService(Context context, PackageManagerService pm,
Supplier<PackageParser2> apexParserSupplier) {
mContext = context; mContext = context;
mPm = pm; mPm = pm;
mPermissionManager = LocalServices.getService(PermissionManagerServiceInternal.class); mPermissionManager = LocalServices.getService(PermissionManagerServiceInternal.class);
@@ -213,7 +216,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
mSessionsDir.mkdirs(); mSessionsDir.mkdirs();
mApexManager = ApexManager.getInstance(); mApexManager = ApexManager.getInstance();
mStagingManager = new StagingManager(this, context); mStagingManager = new StagingManager(this, context, apexParserSupplier);
} }
boolean okToSendBroadcasts() { boolean okToSendBroadcasts() {

View File

@@ -417,6 +417,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier;
/** /**
* Keep track of all those APKs everywhere. * Keep track of all those APKs everywhere.
@@ -3571,7 +3572,11 @@ public class PackageManagerService extends IPackageManager.Stub
} }
} }
mInstallerService = new PackageInstallerService(mContext, this); // Prepare a supplier of package parser for the staging manager to parse apex file
// during the staging installation.
final Supplier<PackageParser2> apexParserSupplier = () -> new PackageParser2(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mPackageParserCallback);
mInstallerService = new PackageInstallerService(mContext, this, apexParserSupplier);
final Pair<ComponentName, String> instantAppResolverComponent = final Pair<ComponentName, String> instantAppResolverComponent =
getInstantAppResolverLPr(); getInstantAppResolverLPr();
if (instantAppResolverComponent != null) { if (instantAppResolverComponent != null) {

View File

@@ -35,11 +35,11 @@ import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException; import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageParser.SigningDetails; import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion; import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
import android.content.rollback.IRollbackManager; import android.content.rollback.IRollbackManager;
import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager; import android.content.rollback.RollbackManager;
@@ -68,8 +68,10 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageHelper; import com.android.internal.content.PackageHelper;
import com.android.internal.os.BackgroundThread; import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils; import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.rollback.WatchdogRollbackLogger; import com.android.server.rollback.WatchdogRollbackLogger;
import java.io.File; import java.io.File;
@@ -80,6 +82,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier;
/** /**
* This class handles staged install sessions, i.e. install sessions that require packages to * This class handles staged install sessions, i.e. install sessions that require packages to
@@ -94,6 +97,7 @@ public class StagingManager {
private final PowerManager mPowerManager; private final PowerManager mPowerManager;
private final Context mContext; private final Context mContext;
private final PreRebootVerificationHandler mPreRebootVerificationHandler; private final PreRebootVerificationHandler mPreRebootVerificationHandler;
private final Supplier<PackageParser2> mPackageParserSupplier;
@GuardedBy("mStagedSessions") @GuardedBy("mStagedSessions")
private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>(); private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>();
@@ -105,9 +109,11 @@ public class StagingManager {
private final List<String> mFailedPackageNames = new ArrayList<>(); private final List<String> mFailedPackageNames = new ArrayList<>();
private String mNativeFailureReason; private String mNativeFailureReason;
StagingManager(PackageInstallerService pi, Context context) { StagingManager(PackageInstallerService pi, Context context,
Supplier<PackageParser2> packageParserSupplier) {
mPi = pi; mPi = pi;
mContext = context; mContext = context;
mPackageParserSupplier = packageParserSupplier;
mApexManager = ApexManager.getInstance(); mApexManager = ApexManager.getInstance();
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@@ -223,17 +229,21 @@ public class StagingManager {
final List<String> apexPackageNames = new ArrayList<>(); final List<String> apexPackageNames = new ArrayList<>();
for (ApexInfo apexInfo : apexInfoList.apexInfos) { for (ApexInfo apexInfo : apexInfoList.apexInfos) {
final PackageInfo packageInfo; final PackageInfo packageInfo;
int flags = PackageManager.GET_META_DATA; final int flags = PackageManager.GET_META_DATA;
PackageParser.Package pkg; try (PackageParser2 packageParser = mPackageParserSupplier.get()) {
try {
File apexFile = new File(apexInfo.modulePath); File apexFile = new File(apexInfo.modulePath);
PackageParser pp = new PackageParser(); final ParsedPackage parsedPackage = packageParser.parsePackage(
pkg = pp.parsePackage(apexFile, flags, false); apexFile, flags, false);
packageInfo = PackageInfoWithoutStateUtils.generate(parsedPackage, apexInfo, flags);
if (packageInfo == null) {
throw new PackageManagerException(
SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Unable to generate package info: " + apexInfo.modulePath);
}
} catch (PackageParserException e) { } catch (PackageParserException e) {
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Failed to parse APEX package " + apexInfo.modulePath, e); "Failed to parse APEX package " + apexInfo.modulePath, e);
} }
packageInfo = PackageParser.generatePackageInfo(pkg, apexInfo, flags);
final PackageInfo activePackage = mApexManager.getPackageInfo(packageInfo.packageName, final PackageInfo activePackage = mApexManager.getPackageInfo(packageInfo.packageName,
ApexManager.MATCH_ACTIVE_PACKAGE); ApexManager.MATCH_ACTIVE_PACKAGE);
if (activePackage == null) { if (activePackage == null) {