Merge "Finalize ENABLE_FEATURE_SCAN_APEX"
This commit is contained in:
committed by
Android (Google) Code Review
commit
fc6988fb99
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ import java.util.concurrent.Future;
|
||||
/**
|
||||
* Prepares app data for users
|
||||
*/
|
||||
final class AppDataHelper {
|
||||
public class AppDataHelper {
|
||||
private static final boolean DEBUG_APP_DATA = false;
|
||||
|
||||
private final PackageManagerService mPm;
|
||||
|
||||
@@ -63,7 +63,6 @@ import android.Manifest;
|
||||
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.LogPrinter;
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
}
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
}
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
}
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
}
|
||||
}
|
||||
}
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
}
|
||||
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
|
||||
@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 @@ public class ComputerEngine implements Computer {
|
||||
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 @@ public class ComputerEngine implements Computer {
|
||||
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;
|
||||
|
||||
@@ -72,7 +72,6 @@ final class InitAppsHelper {
|
||||
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 @@ final class InitAppsHelper {
|
||||
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 @@ final class InitAppsHelper {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -572,19 +572,15 @@ class InstallingSession {
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -690,7 +690,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
private final ModuleInfoProvider mModuleInfoProvider;
|
||||
|
||||
final ApexManager mApexManager;
|
||||
final ApexPackageInfo mApexPackageInfo;
|
||||
|
||||
final PackageManagerServiceInjector mInjector;
|
||||
|
||||
@@ -1641,7 +1640,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
mSharedLibraries = injector.getSharedLibrariesImpl();
|
||||
|
||||
mApexManager = testParams.apexManager;
|
||||
mApexPackageInfo = new ApexPackageInfo(this);
|
||||
mArtManagerService = testParams.artManagerService;
|
||||
mAvailableFeatures = testParams.availableFeatures;
|
||||
mBackgroundDexOptService = testParams.backgroundDexOptService;
|
||||
@@ -1841,7 +1839,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
mProtectedPackages = new ProtectedPackages(mContext);
|
||||
|
||||
mApexManager = injector.getApexManager();
|
||||
mApexPackageInfo = new ApexPackageInfo(this);
|
||||
mAppsFilter = mInjector.getAppsFilter();
|
||||
|
||||
mInstantAppRegistry = new InstantAppRegistry(mContext, mPermissionManager,
|
||||
@@ -1979,8 +1976,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
|
||||
+ 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 =
|
||||
|
||||
@@ -78,6 +78,12 @@ android_test {
|
||||
"servicestests-core-utils",
|
||||
],
|
||||
|
||||
java_resources: [
|
||||
":apex.test",
|
||||
":test.rebootless_apex_v1",
|
||||
":test.rebootless_apex_v2",
|
||||
],
|
||||
|
||||
jni_libs: [
|
||||
"libpsi",
|
||||
],
|
||||
|
||||
@@ -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.verify;
|
||||
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.IOException;
|
||||
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 @@ public class ApexManagerTest {
|
||||
}
|
||||
|
||||
@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 @@ public class ApexManagerTest {
|
||||
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 @@ public class ApexManagerTest {
|
||||
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 class ApexManagerTest {
|
||||
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 @@ public class ApexManagerTest {
|
||||
|
||||
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 @@ public class ApexManagerTest {
|
||||
|
||||
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 @@ public class ApexManagerTest {
|
||||
}
|
||||
|
||||
@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 @@ public class ApexManagerTest {
|
||||
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 @@ public class ApexManagerTest {
|
||||
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 @@ public class ApexManagerTest {
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -83,7 +83,7 @@ class InitAppsHelperTest {
|
||||
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 @@ class InitAppsHelperTest {
|
||||
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 @@ class InitAppsHelperTest {
|
||||
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 @@ class InitAppsHelperTest {
|
||||
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)
|
||||
|
||||
@@ -78,14 +78,6 @@ import com.android.server.testutils.mock
|
||||
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.junit.runners.model.Statement
|
||||
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 @@ import org.mockito.quality.Strictness
|
||||
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 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
|
||||
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)
|
||||
|
||||
@@ -33,9 +33,14 @@ fun <T> wheneverStatic(mockedMethod: MockedMethod<T>) = object : CustomStaticStu
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -124,9 +124,6 @@ android_test {
|
||||
":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",
|
||||
|
||||
Reference in New Issue
Block a user