Inject more dependencies into PackageManagerService
This change gets all dependencies required to execute the constructor of
PackageManagerService in a "nominal" scenario and adds a simple unit
test for that scenario.
Test: atest PackageManagerServiceBootTest
Bug: 169360984
Change-Id: If436fa3f1c7bda2498930d6a89211e368af410c4
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelper.java b/services/core/java/com/android/server/pm/PackageAbiHelper.java
index 30b1c2c..24a3e52 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelper.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelper.java
@@ -55,7 +55,7 @@
* If {@code extractLibs} is true, native libraries are extracted from the app if required.
*/
Pair<Abis, NativeLibraryPaths> derivePackageAbi(AndroidPackage pkg, boolean isUpdatedSystemApp,
- String cpuAbiOverride) throws PackageManagerException;
+ String cpuAbiOverride, File appLib32InstallDir) throws PackageManagerException;
/**
* Calculates adjusted ABIs for a set of packages belonging to a shared user so that they all
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index da4ea16..71b99bd 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -296,7 +296,7 @@
@Override
public Pair<Abis, NativeLibraryPaths> derivePackageAbi(AndroidPackage pkg,
- boolean isUpdatedSystemApp, String cpuAbiOverride)
+ boolean isUpdatedSystemApp, String cpuAbiOverride, File appLib32InstallDir)
throws PackageManagerException {
// Give ourselves some initial paths; we'll come back for another
// pass once we've determined ABI below.
@@ -304,7 +304,7 @@
String pkgRawSecondaryCpuAbi = AndroidPackageUtils.getRawSecondaryCpuAbi(pkg);
final NativeLibraryPaths initialLibraryPaths = deriveNativeLibraryPaths(
new Abis(pkgRawPrimaryCpuAbi, pkgRawSecondaryCpuAbi),
- PackageManagerService.sAppLib32InstallDir, pkg.getPath(),
+ appLib32InstallDir, pkg.getPath(),
pkg.getBaseApkPath(), pkg.isSystem(),
isUpdatedSystemApp);
@@ -452,7 +452,7 @@
final Abis abis = new Abis(primaryCpuAbi, secondaryCpuAbi);
return new Pair<>(abis,
- deriveNativeLibraryPaths(abis, PackageManagerService.sAppLib32InstallDir,
+ deriveNativeLibraryPaths(abis, appLib32InstallDir,
pkg.getPath(), pkg.getBaseApkPath(), pkg.isSystem(),
isUpdatedSystemApp));
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cd4fe57..6aa4589 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -449,7 +449,6 @@
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
-import java.util.function.Supplier;
/**
* Keep track of all those APKs everywhere.
@@ -733,8 +732,6 @@
private static final int INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS = 7000;
private static final int INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS = 60000;
- final ServiceThread mHandlerThread;
-
final Handler mHandler;
private final ProcessLoggingHandler mProcessLoggingHandler;
@@ -762,12 +759,14 @@
final Installer mInstaller;
/** Directory where installed applications are stored */
- private static final File sAppInstallDir =
- new File(Environment.getDataDirectory(), "app");
+ private final File mAppInstallDir;
/** Directory where installed application's 32-bit native libraries are copied. */
@VisibleForTesting
- static final File sAppLib32InstallDir =
- new File(Environment.getDataDirectory(), "app-lib");
+ final File mAppLib32InstallDir;
+
+ private static File getAppLib32InstallDir() {
+ return new File(Environment.getDataDirectory(), "app-lib");
+ }
// ----------------------------------------------------------------
@@ -833,6 +832,11 @@
boolean mFirstBoot;
+ private final boolean mIsEngBuild;
+ private final boolean mIsUserDebugBuild;
+ private final String mIncrementalVersion;
+
+
PackageManagerInternal.ExternalSourcesPolicy mExternalSourcesPolicy;
@GuardedBy("mAvailableFeatures")
@@ -867,6 +871,8 @@
private final Injector mInjector;
+ private final SystemWrapper mSystemWrapper;
+
/**
* The list of all system partitions that may contain packages in ascending order of
* specificity (the more generic, the earlier in the list a partition appears).
@@ -897,6 +903,10 @@
T produce(Injector injector, PackageManagerService packageManager);
}
+ interface ProducerWithArgument<T, R> {
+ T produce(Injector injector, PackageManagerService packageManager, R argument);
+ }
+
interface ServiceProducer {
<T> T produce(Class<T> c);
}
@@ -925,6 +935,8 @@
private final Object mInstallLock;
private final Handler mBackgroundHandler;
private final Executor mBackgroundExecutor;
+ private final List<ScanPartition> mSystemPartitions;
+
// ----- producers -----
private final Singleton<ComponentResolver> mComponentResolverProducer;
@@ -942,13 +954,22 @@
private final Singleton<IPermissionManager> mPermissionManagerProducer;
private final Singleton<IncrementalManager> mIncrementalManagerProducer;
private final Singleton<DefaultAppProvider> mDefaultAppProviderProducer;
+ private final Singleton<DisplayMetrics> mDisplayMetricsProducer;
+ private final Producer<PackageParser2> mScanningCachingPackageParserProducer;
+ private final Producer<PackageParser2> mScanningPackageParserProducer;
+ private final Producer<PackageParser2> mPreparingPackageParserProducer;
+ private final Singleton<PackageInstallerService> mPackageInstallerServiceProducer;
+ private final ProducerWithArgument<InstantAppResolverConnection, ComponentName>
+ mInstantAppResolverConnectionProducer;
private final SystemWrapper mSystemWrapper;
private final ServiceProducer mGetLocalServiceProducer;
private final ServiceProducer mGetSystemServiceProducer;
+ private final Singleton<ModuleInfoProvider> mModuleInfoProviderProducer;
Injector(Context context, Object lock, Installer installer,
Object installLock, PackageAbiHelper abiHelper,
Handler backgroundHandler,
+ List<ScanPartition> systemPartitions,
Producer<ComponentResolver> componentResolverProducer,
Producer<PermissionManagerServiceInternal> permissionManagerServiceProducer,
Producer<UserManagerService> userManagerProducer,
@@ -964,6 +985,14 @@
Producer<ViewCompiler> viewCompilerProducer,
Producer<IncrementalManager> incrementalManagerProducer,
Producer<DefaultAppProvider> defaultAppProviderProducer,
+ Producer<DisplayMetrics> displayMetricsProducer,
+ Producer<PackageParser2> scanningCachingPackageParserProducer,
+ Producer<PackageParser2> scanningPackageParserProducer,
+ Producer<PackageParser2> preparingPackageParserProducer,
+ Producer<PackageInstallerService> packageInstallerServiceProducer,
+ ProducerWithArgument<InstantAppResolverConnection, ComponentName>
+ instantAppResolverConnectionProducer,
+ Producer<ModuleInfoProvider> moduleInfoProviderProducer,
SystemWrapper systemWrapper,
ServiceProducer getLocalServiceProducer,
ServiceProducer getSystemServiceProducer) {
@@ -974,6 +1003,7 @@
mInstallLock = installLock;
mBackgroundHandler = backgroundHandler;
mBackgroundExecutor = new HandlerExecutor(backgroundHandler);
+ mSystemPartitions = systemPartitions;
mComponentResolverProducer = new Singleton<>(componentResolverProducer);
mPermissionManagerServiceProducer = new Singleton<>(permissionManagerServiceProducer);
mUserManagerProducer = new Singleton<>(userManagerProducer);
@@ -989,6 +1019,13 @@
mViewCompilerProducer = new Singleton<>(viewCompilerProducer);
mIncrementalManagerProducer = new Singleton<>(incrementalManagerProducer);
mDefaultAppProviderProducer = new Singleton<>(defaultAppProviderProducer);
+ mDisplayMetricsProducer = new Singleton<>(displayMetricsProducer);
+ mScanningCachingPackageParserProducer = scanningCachingPackageParserProducer;
+ mScanningPackageParserProducer = scanningPackageParserProducer;
+ mPreparingPackageParserProducer = preparingPackageParserProducer;
+ mPackageInstallerServiceProducer = new Singleton<>(packageInstallerServiceProducer);
+ mInstantAppResolverConnectionProducer = instantAppResolverConnectionProducer;
+ mModuleInfoProviderProducer = new Singleton<>(moduleInfoProviderProducer);
mSystemWrapper = systemWrapper;
mGetLocalServiceProducer = getLocalServiceProducer;
mGetSystemServiceProducer = getSystemServiceProducer;
@@ -1014,6 +1051,10 @@
return mInstallLock;
}
+ public List<ScanPartition> getSystemPartitions() {
+ return mSystemPartitions;
+ }
+
public UserManagerService getUserManagerService() {
return mUserManagerProducer.get(this, mPackageManager);
}
@@ -1086,6 +1127,10 @@
return mBackgroundExecutor;
}
+ public DisplayMetrics getDisplayMetrics() {
+ return mDisplayMetricsProducer.get(this, mPackageManager);
+ }
+
public <T> T getLocalService(Class<T> c) {
return mGetLocalServiceProducer.produce(c);
}
@@ -1105,53 +1150,59 @@
public DefaultAppProvider getDefaultAppProvider() {
return mDefaultAppProviderProducer.get(this, mPackageManager);
}
+
+ public PackageParser2 getScanningCachingPackageParser() {
+ return mScanningCachingPackageParserProducer.produce(this, mPackageManager);
+ }
+ public PackageParser2 getScanningPackageParser() {
+ return mScanningPackageParserProducer.produce(this, mPackageManager);
+ }
+ public PackageParser2 getPreparingPackageParser() {
+ return mPreparingPackageParserProducer.produce(this, mPackageManager);
+ }
+
+ public PackageInstallerService getPackageInstallerService() {
+ return mPackageInstallerServiceProducer.get(this, mPackageManager);
+ }
+
+ public InstantAppResolverConnection getInstantAppResolverConnection(
+ ComponentName instantAppResolverComponent) {
+ return mInstantAppResolverConnectionProducer.produce(
+ this, mPackageManager, instantAppResolverComponent);
+ }
+
+ public ModuleInfoProvider getModuleInfoProvider() {
+ return mModuleInfoProviderProducer.get(this, mPackageManager);
+ }
}
/** Provides an abstraction to static access to system state. */
public interface SystemWrapper {
- /** @see SystemProperties#get(String) */
- String getProperty(String key);
- /** @see SystemProperties#getInt(String, int) */
- int getPropertyInt(String key, int defValue);
- /** @see SystemProperties#getBoolean(String, boolean) */
- boolean getPropertyBoolean(String key, boolean defValue);
- /** @see SystemProperties#digestOf(String...) */
- String digestOfProperties(@NonNull String... keys);
- /** @see SystemProperties#set(String, String) */
- void setProperty(String key, String value);
- /** @see Build.VERSION#SDK_INT */
- int getSdkInt();
+ void disablePackageCaches();
+ void enablePackageCaches();
}
private static class DefaultSystemWrapper implements SystemWrapper {
+
@Override
- public String getProperty(String key) {
- return SystemProperties.get(key);
+ public void disablePackageCaches() {
+ // disable all package caches that shouldn't apply within system server
+ PackageManager.disableApplicationInfoCache();
+ PackageManager.disablePackageInfoCache();
+ ApplicationPackageManager.invalidateGetPackagesForUidCache();
+ ApplicationPackageManager.disableGetPackagesForUidCache();
+ ApplicationPackageManager.invalidateHasSystemFeatureCache();
+
+ // Avoid invalidation-thrashing by preventing cache invalidations from causing property
+ // writes if the cache isn't enabled yet. We re-enable writes later when we're
+ // done initializing.
+ PackageManager.corkPackageInfoCache();
}
@Override
- public int getPropertyInt(String key, int defValue) {
- return SystemProperties.getInt(key, defValue);
- }
-
- @Override
- public boolean getPropertyBoolean(String key, boolean defValue) {
- return SystemProperties.getBoolean(key, defValue);
- }
-
- @Override
- public String digestOfProperties(String... keys) {
- return SystemProperties.digestOf(keys);
- }
-
- @Override
- public void setProperty(String key, String value) {
- SystemProperties.set(key, value);
- }
-
- @Override
- public int getSdkInt() {
- return Build.VERSION.SDK_INT;
+ public void enablePackageCaches() {
+ // Uncork cache invalidations and allow clients to cache package information.
+ PackageManager.uncorkPackageInfoCache();
}
}
@@ -1169,7 +1220,6 @@
public boolean factoryTest;
public ArrayMap<String, FeatureInfo> availableFeatures;
public Handler handler;
- public ServiceThread handlerThread;
public @Nullable String incidentReportApproverPackage;
public IncrementalManager incrementalManager;
public PackageInstallerService installerService;
@@ -1215,6 +1265,13 @@
public ArrayMap<String, AndroidPackage> packages;
public boolean enableFreeCacheV2;
public int sdkVersion;
+ public SystemWrapper systemWrapper;
+ public File appInstallDir;
+ public File appLib32InstallDir;
+ public boolean isEngBuild;
+ public boolean isUserDebugBuild;
+ public int sdkInt = Build.VERSION.SDK_INT;
+ public String incrementalVersion = Build.VERSION.INCREMENTAL;
}
private final AppsFilter mAppsFilter;
@@ -1814,7 +1871,7 @@
for (int index = 0; i < size && index < numComponents; index++) {
packages[i] = componentsToBroadcast.keyAt(index);
components[i] = componentsToBroadcast.valueAt(index);
- final PackageSetting ps = mSettings.mPackages.get(packages[i]);
+ final PackageSetting ps = mSettings.getPackageLPr(packages[i]);
uids[i] = (ps != null)
? UserHandle.getUid(packageUserId, ps.appId)
: -1;
@@ -2321,7 +2378,7 @@
synchronized (mLock) {
newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
getPackageSettingInternal(res.name, Process.SYSTEM_UID),
- updateUserIds, mSettings.mPackages);
+ updateUserIds, mSettings.getPackagesLocked());
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
@@ -2758,6 +2815,7 @@
Injector injector = new Injector(
context, lock, installer, installLock, new PackageAbiHelperImpl(),
backgroundHandler,
+ SYSTEM_PARTITIONS,
(i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
(i, pm) -> PermissionManagerService.create(context),
(i, pm) -> new UserManagerService(context, pm,
@@ -2779,14 +2837,37 @@
(i, pm) -> (IPermissionManager) ServiceManager.getService("permissionmgr"),
(i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()),
(i, pm) -> (IncrementalManager)
- pm.mContext.getSystemService(Context.INCREMENTAL_SERVICE),
+ i.getContext().getSystemService(Context.INCREMENTAL_SERVICE),
(i, pm) -> new DefaultAppProvider(() -> context.getSystemService(RoleManager.class),
i.getPermissionManagerServiceInternal()),
+ (i, pm) -> new DisplayMetrics(),
+ (i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore,
+ i.getDisplayMetrics(), pm.mCacheDir,
+ pm.mPackageParserCallback) /* scanningCachingPackageParserProducer */,
+ (i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore,
+ i.getDisplayMetrics(), null,
+ pm.mPackageParserCallback) /* scanningPackageParserProducer */,
+ (i, pm) -> new PackageParser2(pm.mSeparateProcesses, false, i.getDisplayMetrics(),
+ null, pm.mPackageParserCallback) /* preparingPackageParserProducer */,
+ // Prepare a supplier of package parser for the staging manager to parse apex file
+ // during the staging installation.
+ (i, pm) -> new PackageInstallerService(
+ i.getContext(), pm, i::getScanningPackageParser),
+ (i, pm, cn) -> new InstantAppResolverConnection(
+ i.getContext(), cn, Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE),
+ (i, pm) -> new ModuleInfoProvider(i.getContext(), pm),
new DefaultSystemWrapper(),
LocalServices::getService,
context::getSystemService);
- PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest);
+
+ if (Build.VERSION.SDK_INT <= 0) {
+ Slog.w(TAG, "**** ro.build.version.sdk not set!");
+ }
+
+ PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,
+ Build.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT,
+ Build.VERSION.INCREMENTAL);
t.traceEnd(); // "create package manager"
final CompatChange.ChangeListener selinuxChangeListener = packageName -> {
@@ -2846,11 +2927,6 @@
}
}
- private static void getDefaultDisplayMetrics(
- DisplayManager displayManager, DisplayMetrics metrics) {
- displayManager.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(metrics);
- }
-
/**
* Requests that files preopted on a secondary system partition be copied to the data partition
* if possible. Note that the actual copying of the files is accomplished by init for security
@@ -2860,14 +2936,13 @@
private static void requestCopyPreoptedFiles(Injector injector) {
final int WAIT_TIME_MS = 100;
final String CP_PREOPT_PROPERTY = "sys.cppreopt";
- if (injector.getSystemWrapper().getPropertyInt("ro.cp_system_other_odex", 0) == 1) {
- injector.getSystemWrapper().setProperty(CP_PREOPT_PROPERTY, "requested");
+ if (SystemProperties.getInt("ro.cp_system_other_odex", 0) == 1) {
+ SystemProperties.set(CP_PREOPT_PROPERTY, "requested");
// We will wait for up to 100 seconds.
final long timeStart = SystemClock.uptimeMillis();
final long timeEnd = timeStart + 100 * 1000;
long timeNow = timeStart;
- while (!injector.getSystemWrapper()
- .getProperty(CP_PREOPT_PROPERTY).equals("finished")) {
+ while (!SystemProperties.get(CP_PREOPT_PROPERTY).equals("finished")) {
try {
Thread.sleep(WAIT_TIME_MS);
} catch (InterruptedException e) {
@@ -2875,7 +2950,7 @@
}
timeNow = SystemClock.uptimeMillis();
if (timeNow > timeEnd) {
- injector.getSystemWrapper().setProperty(CP_PREOPT_PROPERTY, "timed-out");
+ SystemProperties.set(CP_PREOPT_PROPERTY, "timed-out");
Slog.wtf(TAG, "cppreopt did not finish!");
break;
}
@@ -2952,7 +3027,6 @@
mPermissionManager = injector.getPermissionManagerServiceInternal();
mSettings = injector.getSettings();
mUserManager = injector.getUserManagerService();
-
mApexManager = testParams.apexManager;
mArtManagerService = testParams.artManagerService;
mAvailableFeatures = testParams.availableFeatures;
@@ -2962,7 +3036,6 @@
mDirsToScanAsSystem = testParams.dirsToScanAsSystem;
mFactoryTest = testParams.factoryTest;
mHandler = testParams.handler;
- mHandlerThread = testParams.handlerThread;
mIncrementalManager = testParams.incrementalManager;
mInstallerService = testParams.installerService;
mInstantAppRegistry = testParams.instantAppRegistry;
@@ -3007,49 +3080,46 @@
mServicesExtensionPackageName = testParams.servicesExtensionPackageName;
mSharedSystemSharedLibraryPackageName = testParams.sharedSystemSharedLibraryPackageName;
mOverlayConfigSignaturePackage = testParams.overlayConfigSignaturePackage;
-
mResolveComponentName = testParams.resolveComponentName;
mPackages.putAll(testParams.packages);
mEnableFreeCacheV2 = testParams.enableFreeCacheV2;
mSdkVersion = testParams.sdkVersion;
+ mSystemWrapper = testParams.systemWrapper;
+ mAppInstallDir = testParams.appInstallDir;
+ mAppLib32InstallDir = testParams.appLib32InstallDir;
+ mIsEngBuild = testParams.isEngBuild;
+ mIsUserDebugBuild = testParams.isUserDebugBuild;
+ mIncrementalVersion = testParams.incrementalVersion;
}
- public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
- PackageManager.disableApplicationInfoCache();
- PackageManager.disablePackageInfoCache();
- ApplicationPackageManager.invalidateGetPackagesForUidCache();
- ApplicationPackageManager.disableGetPackagesForUidCache();
- ApplicationPackageManager.invalidateHasSystemFeatureCache();
-
- // Avoid invalidation-thrashing by preventing cache invalidations from causing property
- // writes if the cache isn't enabled yet. We re-enable writes later when we're
- // done initializing.
- PackageManager.corkPackageInfoCache();
+ public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
+ final String buildFingerprint, final boolean isEngBuild,
+ final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {
+ mIsEngBuild = isEngBuild;
+ mIsUserDebugBuild = isUserDebugBuild;
+ mSdkVersion = sdkVersion;
+ mIncrementalVersion = incrementalVersion;
+ mInjector = injector;
+ mInjector.getSystemWrapper().disablePackageCaches();
final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
Trace.TRACE_TAG_PACKAGE_MANAGER);
mPendingBroadcasts = new PendingPackageBroadcasts();
- mInjector = injector;
mInjector.bootstrap(this);
mLock = injector.getLock();
mInstallLock = injector.getInstallLock();
LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
- mSdkVersion = injector.getSystemWrapper().getSdkInt();
-
- if (mSdkVersion <= 0) {
- Slog.w(TAG, "**** ro.build.version.sdk not set!");
- }
+ mSystemWrapper = injector.getSystemWrapper();
mContext = injector.getContext();
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
- mMetrics = new DisplayMetrics();
+ mMetrics = injector.getDisplayMetrics();
mInstaller = injector.getInstaller();
- mEnableFreeCacheV2 =
- injector.getSystemWrapper().getPropertyBoolean("fw.free_cache_v2", true);
+ mEnableFreeCacheV2 = SystemProperties.getBoolean("fw.free_cache_v2", true);
// Create sub-components that provide services / data. Order here is important.
t.traceBegin("createSubComponents");
@@ -3101,8 +3171,8 @@
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
t.traceEnd();
- String separateProcesses =
- injector.getSystemWrapper().getProperty("debug.separate_processes");
+ String separateProcesses = SystemProperties.get("debug.separate_processes");
+
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
@@ -3125,7 +3195,8 @@
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
mViewCompiler = injector.getViewCompiler();
- getDefaultDisplayMetrics(mInjector.getSystemService(DisplayManager.class), mMetrics);
+ mContext.getSystemService(DisplayManager.class)
+ .getDisplay(Display.DEFAULT_DISPLAY).getMetrics(mMetrics);
t.traceBegin("get system config");
SystemConfig systemConfig = injector.getSystemConfig();
@@ -3147,18 +3218,21 @@
}
mDirsToScanAsSystem = new ArrayList<>();
- mDirsToScanAsSystem.addAll(SYSTEM_PARTITIONS);
+ mDirsToScanAsSystem.addAll(injector.getSystemPartitions());
mDirsToScanAsSystem.addAll(scanPartitions);
Slog.d(TAG, "Directories scanned as system partitions: " + mDirsToScanAsSystem);
+ mAppInstallDir = new File(Environment.getDataDirectory(), "app");
+ mAppLib32InstallDir = getAppLib32InstallDir();
+
// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mLock) {
- mHandlerThread = new ServiceThread(TAG,
+ HandlerThread handlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
- mHandlerThread.start();
- mHandler = new PackageHandler(mHandlerThread.getLooper());
+ handlerThread.start();
+ mHandler = new PackageHandler(handlerThread.getLooper());
mProcessLoggingHandler = new ProcessLoggingHandler();
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
mInstantAppRegistry = new InstantAppRegistry(this, mPermissionManager);
@@ -3203,12 +3277,13 @@
// Clean up orphaned packages for which the code path doesn't exist
// and they are an update to a system app - caused by bug/32321269
- final int packageSettingCount = mSettings.mPackages.size();
+ final ArrayMap<String, PackageSetting> packageSettings = mSettings.getPackagesLocked();
+ final int packageSettingCount = packageSettings.size();
for (int i = packageSettingCount - 1; i >= 0; i--) {
- PackageSetting ps = mSettings.mPackages.valueAt(i);
+ PackageSetting ps = packageSettings.valueAt(i);
if (!isExternal(ps) && (ps.getPath() == null || !ps.getPath().exists())
&& mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
- mSettings.mPackages.removeAt(i);
+ packageSettings.removeAt(i);
mSettings.enableSystemPackageLPw(ps.name);
}
}
@@ -3243,9 +3318,10 @@
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
final VersionInfo ver = mSettings.getInternalVersion();
- mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
+ mIsUpgrade =
+ !buildFingerprint.equals(ver.fingerprint);
if (mIsUpgrade) {
- logCriticalInfo(Log.INFO,
+ PackageManagerServiceUtils.logCriticalInfo(Log.INFO,
"Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
}
@@ -3263,13 +3339,13 @@
// Save the names of pre-existing packages prior to scanning, so we can determine
// which system packages are completely new due to an upgrade.
if (isDeviceUpgrading()) {
- mExistingPackages = new ArraySet<>(mSettings.mPackages.size());
- for (PackageSetting ps : mSettings.mPackages.values()) {
+ mExistingPackages = new ArraySet<>(packageSettings.size());
+ for (PackageSetting ps : packageSettings.values()) {
mExistingPackages.add(ps.name);
}
}
- mCacheDir = preparePackageParserCache(injector);
+ mCacheDir = preparePackageParserCache(mIsEngBuild);
// Set flag to monitor and not change apk file paths when
// scanning install directories.
@@ -3282,8 +3358,7 @@
final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;
- PackageParser2 packageParser = new PackageParser2(mSeparateProcesses, mOnlyCore,
- mMetrics, mCacheDir, mPackageParserCallback);
+ PackageParser2 packageParser = injector.getScanningCachingPackageParser();
ExecutorService executorService = ParallelPackageParser.makeExecutorService();
// Prepare apex package info before scanning APKs, these information are needed when
@@ -3346,8 +3421,8 @@
// Iterates PackageSettings in reversed order because the item could be removed
// during the iteration.
- for (int index = mSettings.mPackages.size() - 1; index >= 0; index--) {
- final PackageSetting ps = mSettings.mPackages.valueAt(index);
+ for (int index = packageSettings.size() - 1; index >= 0; index--) {
+ final PackageSetting ps = packageSettings.valueAt(index);
/*
* If this is not a system app, it can't be a
@@ -3428,7 +3503,7 @@
if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
- scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,
+ scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,
packageParser, executorService);
}
@@ -3485,7 +3560,7 @@
// previously scanned and known to the system], but, we don't have
// a package [ie. there was an error scanning it from the /data
// partition], completely remove the package data.
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null && mPackages.get(packageName) == null) {
removePackageDataLIF(ps, userIds, null, 0, false);
@@ -3611,7 +3686,7 @@
// Now that we know all the packages we are keeping,
// read and update their last usage times.
- mPackageUsage.read(mSettings.mPackages);
+ mPackageUsage.read(packageSettings);
mCompilerStats.read();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
@@ -3704,8 +3779,8 @@
// profile compilation (without waiting to collect a fresh set of profiles).
if (mIsUpgrade && !mOnlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
- for (int i = 0; i < mSettings.mPackages.size(); i++) {
- final PackageSetting ps = mSettings.mPackages.valueAt(i);
+ for (int i = 0; i < packageSettings.size(); i++) {
+ final PackageSetting ps = packageSettings.valueAt(i);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
// No apps are running this early, so no need to freeze
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
@@ -3721,9 +3796,9 @@
// their icons in launcher.
if (!mOnlyCore && mIsPreQUpgrade) {
Slog.i(TAG, "Whitelisting all existing apps to hide their icons");
- int size = mSettings.mPackages.size();
+ int size = packageSettings.size();
for (int i = 0; i < size; i++) {
- final PackageSetting ps = mSettings.mPackages.valueAt(i);
+ final PackageSetting ps = packageSettings.valueAt(i);
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
continue;
}
@@ -3792,23 +3867,16 @@
}
}
- // 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, null /* cacheDir */,
- mPackageParserCallback);
- mInstallerService = new PackageInstallerService(mContext, this, apexParserSupplier);
- final Pair<ComponentName, String> instantAppResolverComponent =
- getInstantAppResolverLPr();
+ mInstallerService = mInjector.getPackageInstallerService();
+ final ComponentName instantAppResolverComponent = getInstantAppResolverLPr();
if (instantAppResolverComponent != null) {
if (DEBUG_INSTANT) {
Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
}
- mInstantAppResolverConnection = new InstantAppResolverConnection(
- mContext, instantAppResolverComponent.first,
- instantAppResolverComponent.second);
+ mInstantAppResolverConnection =
+ mInjector.getInstantAppResolverConnection(instantAppResolverComponent);
mInstantAppResolverSettingsComponent =
- getInstantAppResolverSettingsLPr(instantAppResolverComponent.first);
+ getInstantAppResolverSettingsLPr(instantAppResolverComponent);
} else {
mInstantAppResolverConnection = null;
mInstantAppResolverSettingsComponent = null;
@@ -3838,10 +3906,8 @@
} // synchronized (mInstallLock)
// CHECKSTYLE:ON IndentationCheck
- mModuleInfoProvider = new ModuleInfoProvider(mContext, this);
-
- // Uncork cache invalidations and allow clients to cache package information.
- PackageManager.uncorkPackageInfoCache();
+ mModuleInfoProvider = mInjector.getModuleInfoProvider();
+ mInjector.getSystemWrapper().enablePackageCaches();
// Now after opening every single application zip, make sure they
// are all flushed. Not really needed, but keeps things nice and
@@ -3889,7 +3955,7 @@
continue;
}
// skip if the package has been disabled by the user
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null) {
final int enabledState = ps.getEnabled(UserHandle.USER_SYSTEM);
if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
@@ -3914,7 +3980,7 @@
// disable any stub still left; these failed to install the full application
for (int i = systemStubPackageNames.size() - 1; i >= 0; --i) {
final String pkgName = systemStubPackageNames.get(i);
- final PackageSetting ps = mSettings.mPackages.get(pkgName);
+ final PackageSetting ps = mSettings.getPackageLPr(pkgName);
ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
UserHandle.USER_SYSTEM, "android");
logCriticalInfo(Log.ERROR, "Stub disabled; pkg: " + pkgName);
@@ -3971,7 +4037,7 @@
} finally {
// Disable the package; the stub by itself is not runnable
synchronized (mLock) {
- final PackageSetting stubPs = mSettings.mPackages.get(
+ final PackageSetting stubPs = mSettings.getPackageLPr(
stubPkg.getPackageName());
if (stubPs != null) {
stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED,
@@ -4091,19 +4157,18 @@
setUpInstantAppInstallerActivityLP(getInstantAppInstallerLPr());
}
- private static @Nullable File preparePackageParserCache(Injector injector) {
+ private @Nullable File preparePackageParserCache(boolean forEngBuild) {
if (!FORCE_PACKAGE_PARSED_CACHE_ENABLED) {
if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) {
return null;
}
// Disable package parsing on eng builds to allow for faster incremental development.
- if (Build.IS_ENG) {
+ if (forEngBuild) {
return null;
}
- if (injector.getSystemWrapper()
- .getPropertyBoolean("pm.boot.disable_package_cache", false)) {
+ if (SystemProperties.getBoolean("pm.boot.disable_package_cache", false)) {
Slog.i(TAG, "Disabling package parser cache due to system property.");
return null;
}
@@ -4119,8 +4184,7 @@
// identify cached items. In particular, changing the value of certain
// feature flags should cause us to invalidate any caches.
final String cacheName = FORCE_PACKAGE_PARSED_CACHE_ENABLED ? "debug"
- : injector.getSystemWrapper().digestOfProperties(
- "ro.build.fingerprint");
+ : SystemProperties.digestOf("ro.build.fingerprint");
// Reconcile cache directories, keeping only what we'd actually use.
for (File cacheDir : FileUtils.listFilesOrEmpty(cacheBaseDir)) {
@@ -4149,14 +4213,15 @@
// NOTE: When no BUILD_NUMBER is set by the build system, it defaults to a build
// that starts with "eng." to signify that this is an engineering build and not
// destined for release.
- if (Build.IS_USERDEBUG && Build.VERSION.INCREMENTAL.startsWith("eng.")) {
+ if (mIsUserDebugBuild && mIncrementalVersion.startsWith("eng.")) {
Slog.w(TAG, "Wiping cache directory because the system partition changed.");
// Heuristic: If the /system directory has been modified recently due to an "adb sync"
// or a regular make, then blow away the cache. Note that mtimes are *NOT* reliable
// in general and should not be used for production changes. In this specific case,
// we know that they will work.
- File frameworkDir = new File(Environment.getRootDirectory(), "framework");
+ File frameworkDir =
+ new File(Environment.getRootDirectory(), "framework");
if (cacheDir.lastModified() < frameworkDir.lastModified()) {
FileUtils.deleteContents(cacheBaseDir);
cacheDir = FileUtils.createDir(cacheBaseDir, cacheName);
@@ -4182,7 +4247,7 @@
public boolean isDeviceUpgrading() {
// allow instant applications
// The system property allows testing ota flow when upgraded to the same image.
- return mIsUpgrade || mInjector.getSystemWrapper().getPropertyBoolean(
+ return mIsUpgrade || SystemProperties.getBoolean(
"persist.pm.mock-upgrade", false /* default */);
}
@@ -4316,15 +4381,15 @@
return null;
}
synchronized (mLock) {
- final Pair<ComponentName, String> instantAppResolver = getInstantAppResolverLPr();
+ final ComponentName instantAppResolver = getInstantAppResolverLPr();
if (instantAppResolver == null) {
return null;
}
- return instantAppResolver.first;
+ return instantAppResolver;
}
}
- private @Nullable Pair<ComponentName, String> getInstantAppResolverLPr() {
+ private @Nullable ComponentName getInstantAppResolverLPr() {
final String[] packageArray =
mContext.getResources().getStringArray(R.array.config_ephemeralResolverPackage);
if (packageArray.length == 0 && !Build.IS_DEBUGGABLE) {
@@ -4339,8 +4404,7 @@
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE
| (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
- String actionName = Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE;
- final Intent resolverIntent = new Intent(actionName);
+ final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE);
List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
final int N = resolvers.size();
@@ -4372,7 +4436,7 @@
Slog.v(TAG, "Ephemeral resolver found;"
+ " pkg: " + packageName + ", info:" + info);
}
- return new Pair<>(new ComponentName(packageName, info.serviceInfo.name), actionName);
+ return new ComponentName(packageName, info.serviceInfo.name);
}
if (DEBUG_INSTANT) {
Slog.v(TAG, "Ephemeral resolver NOT found");
@@ -4382,7 +4446,7 @@
@GuardedBy("mLock")
private @Nullable ActivityInfo getInstantAppInstallerLPr() {
- String[] orderedActions = Build.IS_ENG
+ String[] orderedActions = mIsEngBuild
? new String[]{
Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE + "_TEST",
Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE}
@@ -4393,7 +4457,7 @@
MATCH_DIRECT_BOOT_AWARE
| MATCH_DIRECT_BOOT_UNAWARE
| Intent.FLAG_IGNORE_EPHEMERAL
- | (!Build.IS_ENG ? MATCH_SYSTEM_ONLY : 0);
+ | (mIsEngBuild ? 0 : MATCH_SYSTEM_ONLY);
final Intent intent = new Intent();
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
@@ -4413,8 +4477,9 @@
Iterator<ResolveInfo> iter = matches.iterator();
while (iter.hasNext()) {
final ResolveInfo rInfo = iter.next();
- if (checkPermission(Manifest.permission.INSTALL_PACKAGES,
- rInfo.activityInfo.packageName, 0) == PERMISSION_GRANTED || Build.IS_ENG) {
+ if (checkPermission(
+ Manifest.permission.INSTALL_PACKAGES,
+ rInfo.activityInfo.packageName, 0) == PERMISSION_GRANTED || mIsEngBuild) {
continue;
}
iter.remove();
@@ -4642,7 +4707,7 @@
enforceCrossUserPermission(callingUid, userId, false, false, "checkPackageStartable");
final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) {
throw new SecurityException("Package " + packageName + " was not found!");
}
@@ -4758,7 +4823,7 @@
return generatePackageInfo(ps, flags, userId);
}
if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null) return null;
if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
return null;
@@ -4966,7 +5031,7 @@
final int callingUserId = UserHandle.getUserId(callingUid);
final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
for (int i=names.length-1; i>=0; i--) {
- final PackageSetting ps = mSettings.mPackages.get(names[i]);
+ final PackageSetting ps = mSettings.getPackageLPr(names[i]);
boolean translateName = false;
if (ps != null && ps.realName != null) {
final boolean targetIsInstantApp = ps.getInstantApp(callingUserId);
@@ -4996,7 +5061,7 @@
final String cur = mSettings.getRenamedPackageLPr(names[i]);
boolean translateName = false;
if (cur != null) {
- final PackageSetting ps = mSettings.mPackages.get(names[i]);
+ final PackageSetting ps = mSettings.getPackageLPr(names[i]);
final boolean targetIsInstantApp =
ps != null && ps.getInstantApp(callingUserId);
translateName = !targetIsInstantApp
@@ -5032,7 +5097,7 @@
return UserHandle.getUid(userId, p.getUid());
}
if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null && ps.isMatch(flags)
&& !shouldFilterApplicationLocked(ps, callingUid, userId)) {
return UserHandle.getUid(userId, ps.appId);
@@ -5064,7 +5129,7 @@
return mPermissionManager.getGidsForUid(UserHandle.getUid(userId, ps.appId));
}
if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null && ps.isMatch(flags)
&& !shouldFilterApplicationLocked(ps, callingUid, userId)) {
return mPermissionManager.getGidsForUid(UserHandle.getUid(userId, ps.appId));
@@ -5090,7 +5155,7 @@
private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
int filterCallingUid, int userId) {
if (!mUserManager.exists(userId)) return null;
- PackageSetting ps = mSettings.mPackages.get(packageName);
+ PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null) {
if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
return null;
@@ -5148,7 +5213,7 @@
TAG, "getApplicationInfo " + packageName
+ ": " + p);
if (p != null) {
- PackageSetting ps = mSettings.mPackages.get(packageName);
+ PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null) return null;
if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
return null;
@@ -5617,7 +5682,7 @@
if (a == null) {
return false;
}
- PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+ PackageSetting ps = mSettings.getPackageLPr(component.getPackageName());
if (ps == null) {
return false;
}
@@ -5657,7 +5722,7 @@
}
if (mSettings.isEnabledAndMatchLPr(pkg, a, flags, userId)) {
- PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+ PackageSetting ps = mSettings.getPackageLPr(component.getPackageName());
if (ps == null) return null;
if (shouldFilterApplicationLocked(
ps, callingUid, component, TYPE_RECEIVER, userId)) {
@@ -5817,9 +5882,9 @@
private List<VersionedPackage> getPackagesUsingSharedLibraryLPr(
SharedLibraryInfo libInfo, int flags, int userId) {
List<VersionedPackage> versionedPackages = null;
- final int packageCount = mSettings.mPackages.size();
+ final int packageCount = mSettings.getPackagesLocked().size();
for (int i = 0; i < packageCount; i++) {
- PackageSetting ps = mSettings.mPackages.valueAt(i);
+ PackageSetting ps = mSettings.getPackagesLocked().valueAt(i);
if (ps == null) {
continue;
@@ -5878,7 +5943,7 @@
AndroidPackage pkg = mPackages.get(s.getPackageName());
if (mSettings.isEnabledAndMatchLPr(pkg, s, flags, userId)) {
- PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+ PackageSetting ps = mSettings.getPackageLPr(component.getPackageName());
if (ps == null) return null;
if (shouldFilterApplicationLocked(
ps, callingUid, component, TYPE_SERVICE, userId)) {
@@ -5912,7 +5977,7 @@
}
if (mSettings.isEnabledAndMatchLPr(pkg, p, flags, userId)) {
- PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+ PackageSetting ps = mSettings.getPackageLPr(component.getPackageName());
if (ps == null) return null;
if (shouldFilterApplicationLocked(
ps, callingUid, component, TYPE_PROVIDER, userId)) {
@@ -6049,7 +6114,7 @@
final String packageName = changedPackages.get(i);
if (packageName != null) {
// Filter out the changes if the calling package should not be able to see it.
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
continue;
}
@@ -6070,7 +6135,7 @@
res.addAll(mAvailableFeatures.values());
}
final FeatureInfo fi = new FeatureInfo();
- fi.reqGlEsVersion = mInjector.getSystemWrapper().getPropertyInt("ro.opengles.version",
+ fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
FeatureInfo.GL_ES_VERSION_UNDEFINED);
res.add(fi);
@@ -6796,7 +6861,7 @@
for (int n = 0; n < count; n++) {
final ResolveInfo info = resolvedActivities.get(n);
final String packageName = info.activityInfo.packageName;
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null) {
// only check domain verification status if the app is not a browser
if (!info.handleAllWebDataURI) {
@@ -6878,7 +6943,7 @@
// If we have an ephemeral app, use it
if (ri.activityInfo.applicationInfo.isInstantApp()) {
final String packageName = ri.activityInfo.packageName;
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
final long packedStatus = getDomainVerificationStatusLPr(ps, userId);
final int status = (int)(packedStatus >> 32);
if (status != INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
@@ -7312,7 +7377,7 @@
private List<CrossProfileIntentFilter> getMatchingCrossProfileIntentFilters(Intent intent,
String resolvedType, int userId) {
- CrossProfileIntentResolver resolver = mSettings.getCrossProfileIntentResolvers(userId);
+ CrossProfileIntentResolver resolver = mSettings.getCrossProfileIntentResolver(userId);
if (resolver != null) {
return resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId);
}
@@ -7560,7 +7625,7 @@
for (int i = instantApps.size() - 1; i >= 0; --i) {
final ResolveInfo info = instantApps.get(i);
final String packageName = info.activityInfo.packageName;
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps.getInstantApp(userId)) {
final long packedStatus = getDomainVerificationStatusLPr(ps, userId);
final int status = (int)(packedStatus >> 32);
@@ -7615,7 +7680,7 @@
if (intent.isWebIntent() && auxiliaryResponse == null) {
return result;
}
- final PackageSetting ps = mSettings.mPackages.get(mInstantAppInstallerActivity.packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(mInstantAppInstallerActivity.packageName);
if (ps == null
|| !ps.readUserState(userId).isEnabled(mInstantAppInstallerActivity, 0)) {
return result;
@@ -7675,7 +7740,7 @@
continue;
}
String packageName = riTargetUser.activityInfo.packageName;
- PackageSetting ps = mSettings.mPackages.get(packageName);
+ PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
continue;
}
@@ -7900,7 +7965,7 @@
for (int n=0; n<count; n++) {
ResolveInfo info = candidates.get(n);
String packageName = info.activityInfo.packageName;
- PackageSetting ps = mSettings.mPackages.get(packageName);
+ PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null) {
// Add to the special match all list (Browser use case)
if (info.handleAllWebDataURI) {
@@ -8764,8 +8829,8 @@
synchronized (mLock) {
ArrayList<PackageInfo> list;
if (listUninstalled) {
- list = new ArrayList<>(mSettings.mPackages.size());
- for (PackageSetting ps : mSettings.mPackages.values()) {
+ list = new ArrayList<>(mSettings.getPackagesLocked().size());
+ for (PackageSetting ps : mSettings.getPackagesLocked().values()) {
if (listFactory) {
if (!ps.isSystem()) {
continue;
@@ -8877,7 +8942,7 @@
ArrayList<PackageInfo> list = new ArrayList<>();
boolean[] tmpBools = new boolean[permissions.length];
if (listUninstalled) {
- for (PackageSetting ps : mSettings.mPackages.values()) {
+ for (PackageSetting ps : mSettings.getPackagesLocked().values()) {
addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags,
userId);
}
@@ -8922,8 +8987,8 @@
synchronized (mLock) {
ArrayList<ApplicationInfo> list;
if (listUninstalled) {
- list = new ArrayList<>(mSettings.mPackages.size());
- for (PackageSetting ps : mSettings.mPackages.values()) {
+ list = new ArrayList<>(mSettings.getPackagesLocked().size());
+ for (PackageSetting ps : mSettings.getPackagesLocked().values()) {
ApplicationInfo ai;
int effectiveFlags = flags;
if (ps.isSystem()) {
@@ -9015,7 +9080,7 @@
if (Process.isIsolated(callingUid)) {
callingUid = mIsolatedOwners.get(callingUid);
}
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
final boolean returnAllowed =
ps != null
&& (isCallerSameApp(packageName, callingUid)
@@ -9114,7 +9179,7 @@
if (p.isPersistent()
&& (!mSafeMode || p.isSystem())
&& (matchesUnaware || matchesAware)) {
- PackageSetting ps = mSettings.mPackages.get(p.getPackageName());
+ PackageSetting ps = mSettings.getPackageLPr(p.getPackageName());
if (ps != null) {
ApplicationInfo ai = PackageInfoUtils.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId, ps);
@@ -9159,7 +9224,7 @@
if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) {
return null;
}
- final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(providerInfo.packageName);
final ComponentName component =
new ComponentName(providerInfo.packageName, providerInfo.name);
if (shouldFilterApplicationLocked(ps, callingUid, component, TYPE_PROVIDER, userId)) {
@@ -9199,7 +9264,7 @@
if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) {
continue;
}
- final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(providerInfo.packageName);
final ComponentName component =
new ComponentName(providerInfo.packageName, providerInfo.name);
if (shouldFilterApplicationLocked(
@@ -9228,7 +9293,7 @@
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
String packageName = component.getPackageName();
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
AndroidPackage pkg = mPackages.get(packageName);
if (ps == null || pkg == null) return null;
if (shouldFilterApplicationLocked(
@@ -9460,8 +9525,7 @@
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final ParsedPackage parsedPackage;
- try (PackageParser2 pp = new PackageParser2(mSeparateProcesses, mOnlyCore, mMetrics, null,
- mPackageParserCallback)) {
+ try (PackageParser2 pp = mInjector.getScanningPackageParser()) {
parsedPackage = pp.parsePackage(scanFile, parseFlags, false);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
@@ -9755,7 +9819,7 @@
pkgName, getSettingsVersionForPackage(parsedPackage)),
Collections.singletonMap(pkgName,
getSharedLibLatestVersionSetting(scanResult))),
- mSettings.mKeySetManagerService, mInjector);
+ mSettings.getKeySetManagerService(), mInjector);
appIdCreated = optimisticallyRegisterAppId(scanResult);
commitReconciledScanResultLocked(
reconcileResult.get(pkgName), mUserManager.getUserIds());
@@ -10066,7 +10130,7 @@
List<PackageSetting> pkgSettings;
synchronized (mLock) {
pkgSettings = PackageManagerServiceUtils.getPackagesForDexopt(
- mSettings.mPackages.values(), this);
+ mSettings.getPackagesLocked().values(), this);
}
List<AndroidPackage> pkgs = new ArrayList<>(pkgSettings.size());
@@ -10211,7 +10275,7 @@
pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
}
- if (mInjector.getSystemWrapper().getPropertyBoolean(PRECOMPILE_LAYOUTS, false)) {
+ if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
mArtManagerService.compileLayouts(pkg);
}
@@ -10424,7 +10488,7 @@
// Package could not be found. Report failure.
return PackageDexOptimizer.DEX_OPT_FAILED;
}
- mPackageUsage.maybeWriteAsync(mSettings.mPackages);
+ mPackageUsage.maybeWriteAsync(mSettings.getPackagesLocked());
mCompilerStats.maybeWriteAsync();
}
final long callingId = Binder.clearCallingIdentity();
@@ -10654,7 +10718,7 @@
PackageWatchdog.getInstance(mContext).writeNow();
synchronized (mLock) {
- mPackageUsage.writeNow(mSettings.mPackages);
+ mPackageUsage.writeNow(mSettings.getPackagesLocked());
// This is the last chance to write out pending restriction settings
if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
@@ -10784,7 +10848,7 @@
private void clearAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(pkg.getPackageName());
+ ps = mSettings.getPackageLPr(pkg.getPackageName());
}
for (int realUserId : resolveUserIds(userId)) {
final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0;
@@ -10808,7 +10872,7 @@
private void destroyAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(pkg.getPackageName());
+ ps = mSettings.getPackageLPr(pkg.getPackageName());
}
for (int realUserId : resolveUserIds(userId)) {
final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0;
@@ -11188,7 +11252,7 @@
}
private int getVendorPartitionVersion() {
- final String version = mInjector.getSystemWrapper().getProperty("ro.vndk.version");
+ final String version = SystemProperties.get("ro.vndk.version");
if (!version.isEmpty()) {
try {
return Integer.parseInt(version);
@@ -11399,7 +11463,7 @@
// to allowlist their privileged permissions just like other
// priv-apps.
synchronized (mLock) {
- PackageSetting platformPkgSetting = mSettings.mPackages.get("android");
+ PackageSetting platformPkgSetting = mSettings.getPackageLPr("android");
if ((compareSignatures(platformPkgSetting.signatures.mSigningDetails.signatures,
pkg.getSigningDetails().signatures)
!= PackageManager.SIGNATURE_MATCH)) {
@@ -11521,6 +11585,7 @@
parsedPackage.setVersionCode(mSdkVersion)
.setVersionCodeMajor(0);
}
+
final AndroidPackage oldPkg = request.oldPkg;
final @ParseFlags int parseFlags = request.parseFlags;
final @ScanFlags int scanFlags = request.scanFlags;
@@ -11560,7 +11625,7 @@
if (reconciledPkg.installArgs != null) {
InstallSource installSource = reconciledPkg.installArgs.installSource;
if (installSource.initiatingPackageName != null) {
- final PackageSetting ips = mSettings.mPackages.get(
+ final PackageSetting ips = mSettings.getPackageLPr(
installSource.initiatingPackageName);
if (ips != null) {
installSource = installSource.setInitiatingPackageSignatures(
@@ -11590,7 +11655,7 @@
reconciledPkg.collectedSharedLibraryInfos, allUsers);
}
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ final KeySetManagerService ksms = mSettings.getKeySetManagerService();
if (reconciledPkg.removeAppKeySetData) {
ksms.removeAppKeySetDataLPw(pkg.getPackageName());
}
@@ -11952,12 +12017,13 @@
final String cpuAbiOverride = deriveAbiOverride(request.cpuAbiOverride);
final boolean isUpdatedSystemApp = pkgSetting.getPkgState().isUpdatedSystemApp();
+ final File appLib32InstallDir = getAppLib32InstallDir();
if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
if (needToDeriveAbi) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi =
packageAbiHelper.derivePackageAbi(parsedPackage, isUpdatedSystemApp,
- cpuAbiOverride);
+ cpuAbiOverride, appLib32InstallDir);
derivedAbi.first.applyTo(parsedPackage);
derivedAbi.second.applyTo(parsedPackage);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -11975,7 +12041,7 @@
abis.applyTo(pkgSetting);
final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
packageAbiHelper.deriveNativeLibraryPaths(parsedPackage,
- isUpdatedSystemApp, sAppLib32InstallDir);
+ isUpdatedSystemApp, appLib32InstallDir);
nativeLibraryPaths.applyTo(parsedPackage);
}
} else {
@@ -11987,7 +12053,7 @@
final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
packageAbiHelper.deriveNativeLibraryPaths(parsedPackage,
- isUpdatedSystemApp, sAppLib32InstallDir);
+ isUpdatedSystemApp, appLib32InstallDir);
nativeLibraryPaths.applyTo(parsedPackage);
if (DEBUG_ABI_SELECTION) {
@@ -12013,7 +12079,7 @@
// package path (after the rename away from the stage path).
final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, isUpdatedSystemApp,
- sAppLib32InstallDir);
+ appLib32InstallDir);
nativeLibraryPaths.applyTo(parsedPackage);
}
@@ -12308,7 +12374,7 @@
}
// Make sure we're not adding any bogus keyset info
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ final KeySetManagerService ksms = mSettings.getKeySetManagerService();
ksms.assertScannedPackageValid(pkg);
synchronized (mLock) {
@@ -12526,7 +12592,7 @@
}
if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
// Exempt SharedUsers signed with the platform key.
- PackageSetting platformPkgSetting = mSettings.mPackages.get("android");
+ PackageSetting platformPkgSetting = mSettings.getPackageLPr("android");
if (!comparePackageSignatures(platformPkgSetting,
pkg.getSigningDetails().signatures)) {
throw new PackageManagerException("Apps that share a user with a " +
@@ -12700,7 +12766,7 @@
continue;
}
for (VersionedPackage dependentPackage : dependents) {
- final PackageSetting ps = mSettings.mPackages.get(
+ final PackageSetting ps = mSettings.getPackageLPr(
dependentPackage.getPackageName());
if (ps != null) {
ps.setOverlayPathsForLibrary(libraryInfo.getName(), null, currentUserId);
@@ -12859,7 +12925,6 @@
synchronized (mLock) {
// We don't expect installation to fail beyond this point
-
// Add the new setting to mSettings
mSettings.insertPackageSettingLPw(pkgSetting, pkg);
// Add the new setting to mPackages
@@ -12869,7 +12934,7 @@
}
// Add the package's KeySets to the global KeySetManagerService
- KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ KeySetManagerService ksms = mSettings.getKeySetManagerService();
ksms.addScannedPackageLPw(pkg);
mComponentResolver.addAllComponents(pkg, chatty);
@@ -13344,7 +13409,7 @@
packageName, extras, 0, null, null, userIds, instantUserIds,
mAppsFilter.getVisibilityAllowList(
getPackageSettingInternal(packageName, Process.SYSTEM_UID),
- userIds, mSettings.mPackages));
+ userIds, mSettings.getPackagesLocked()));
if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) {
mHandler.post(() -> {
for (int userId : userIds) {
@@ -13415,7 +13480,7 @@
boolean sendRemoved = false;
// writer
synchronized (mLock) {
- pkgSetting = mSettings.mPackages.get(packageName);
+ pkgSetting = mSettings.getPackageLPr(packageName);
if (pkgSetting == null) {
return false;
}
@@ -13481,7 +13546,7 @@
}
synchronized (mLock) {
- final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+ final PackageSetting pkgSetting = mSettings.getPackageLPr(packageName);
if (pkgSetting == null || !pkgSetting.isSystem()) {
return;
}
@@ -13508,7 +13573,7 @@
}
synchronized (mLock) {
- final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+ final PackageSetting pkgSetting = mSettings.getPackageLPr(packageName);
// The target app should always be in system
if (pkgSetting == null || !pkgSetting.isSystem()) {
return false;
@@ -13595,7 +13660,7 @@
try {
// writer
synchronized (mLock) {
- ps = mSettings.mPackages.get(packageName);
+ ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
return true;
}
@@ -13656,7 +13721,7 @@
// writer
synchronized (mLock) {
- pkgSetting = mSettings.mPackages.get(packageName);
+ pkgSetting = mSettings.getPackageLPr(packageName);
if (pkgSetting == null) {
return PackageManager.INSTALL_FAILED_INVALID_URI;
}
@@ -13806,7 +13871,7 @@
final String packageName = packageNames[i];
final PackageSetting pkgSetting;
synchronized (mLock) {
- pkgSetting = mSettings.mPackages.get(packageName);
+ pkgSetting = mSettings.getPackageLPr(packageName);
if (pkgSetting == null
|| shouldFilterApplicationLocked(pkgSetting, callingUid, userId)) {
Slog.w(TAG, "Could not find package setting for package: " + packageName
@@ -13904,7 +13969,7 @@
}
final PackageSetting pkgSetting;
synchronized (mLock) {
- pkgSetting = mSettings.mPackages.get(packageName);
+ pkgSetting = mSettings.getPackageLPr(packageName);
if (pkgSetting == null
|| shouldFilterApplicationLocked(pkgSetting, callingUid, userId)) {
Slog.w(TAG, "Could not find package setting for package: " + packageName
@@ -13957,7 +14022,7 @@
private Bundle getSuspendedPackageAppExtrasInternal(String packageName, int userId) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
return null;
}
@@ -14012,7 +14077,7 @@
enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */,
false /* checkShell */, "isPackageSuspendedForUser for user " + userId);
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) {
throw new IllegalArgumentException("Unknown target package: " + packageName);
}
@@ -14030,7 +14095,7 @@
boolean isSuspendingAnyPackages(String suspendingPackage, int userId) {
synchronized (mLock) {
- for (final PackageSetting ps : mSettings.mPackages.values()) {
+ for (final PackageSetting ps : mSettings.getPackagesLocked().values()) {
if (ps.isSuspendedBy(suspendingPackage, userId)) {
return true;
}
@@ -14056,7 +14121,7 @@
final IntArray unsuspendedUids = new IntArray();
synchronized (mLock) {
for (String packageName : packagesToChange) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null && ps.getSuspended(userId)) {
ps.removeSuspension(suspendingPackagePredicate, userId);
if (!ps.getSuspended(userId)) {
@@ -14097,7 +14162,7 @@
final IntArray changedUids = new IntArray();
synchronized (mLock) {
for (String packageName : packagesToChange) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null && ps.getDistractionFlags(userId) != 0) {
ps.setDistractionFlags(0, userId);
changedPackages.add(ps.name);
@@ -14153,7 +14218,7 @@
continue;
}
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageNames[i]);
+ final PackageSetting ps = mSettings.getPackageLPr(packageNames[i]);
if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) {
Slog.w(TAG, "Could not find package setting for package: " + packageNames[i]);
unactionablePackages.add(packageNames[i]);
@@ -14500,7 +14565,7 @@
// Check if the developer wants to skip verification for ADB installs
if ((installFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0) {
synchronized (mLock) {
- if (mSettings.mPackages.get(pkgInfoLite.packageName) == null) {
+ if (mSettings.getPackageLPr(pkgInfoLite.packageName) == null) {
// Always verify fresh install
return true;
}
@@ -14567,7 +14632,7 @@
return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
}
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null
|| shouldFilterApplicationLocked(
ps, callingUid, UserHandle.getUserId(callingUid))) {
@@ -14584,7 +14649,7 @@
boolean result = false;
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (shouldFilterApplicationLocked(
ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
return false;
@@ -14605,7 +14670,7 @@
return ParceledListSlice.emptyList();
}
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (shouldFilterApplicationLocked(ps, callingUid, UserHandle.getUserId(callingUid))) {
return ParceledListSlice.emptyList();
}
@@ -14670,7 +14735,7 @@
}
// writer
synchronized (mLock) {
- PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
+ PackageSetting targetPackageSetting = mSettings.getPackageLPr(targetPackage);
if (targetPackageSetting == null
|| shouldFilterApplicationLocked(
targetPackageSetting, callingUid, UserHandle.getUserId(callingUid))) {
@@ -14679,7 +14744,7 @@
PackageSetting installerPackageSetting;
if (installerPackageName != null) {
- installerPackageSetting = mSettings.mPackages.get(installerPackageName);
+ installerPackageSetting = mSettings.getPackageLPr(installerPackageName);
if (installerPackageSetting == null) {
throw new IllegalArgumentException("Unknown installer package: "
+ installerPackageName);
@@ -14721,7 +14786,7 @@
String targetInstallerPackageName =
targetPackageSetting.installSource.installerPackageName;
PackageSetting targetInstallerPkgSetting = targetInstallerPackageName == null ? null :
- mSettings.mPackages.get(targetInstallerPackageName);
+ mSettings.getPackageLPr(targetInstallerPackageName);
if (targetInstallerPkgSetting != null) {
if (compareSignatures(callerSignature,
@@ -14772,7 +14837,7 @@
mInjector.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
callerPackageName);
synchronized (mLock) {
- PackageSetting ps = mSettings.mPackages.get(packageName);
+ PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
throw new IllegalArgumentException("Unknown target package " + packageName);
}
@@ -16513,7 +16578,7 @@
// For system-bundled packages, we assume that installing an upgraded version
// of the package implies that the user actually wants to run that new code,
// so we enable the package.
- final PackageSetting ps = mSettings.mPackages.get(pkgName);
+ final PackageSetting ps = mSettings.getPackageLPr(pkgName);
final int userId = installArgs.user.getIdentifier();
if (ps != null) {
if (pkg.isSystem()) {
@@ -16558,7 +16623,7 @@
// TODO(146804378): Support overlaying static shared libraries
continue;
}
- final PackageSetting libPs = mSettings.mPackages.get(
+ final PackageSetting libPs = mSettings.getPackageLPr(
sharedLib.getPackageName());
if (libPs == null) {
continue;
@@ -16971,8 +17036,7 @@
&& compareSignatures(sharedUserSignatures,
parsedPackage.getSigningDetails().signatures)
!= PackageManager.SIGNATURE_MATCH) {
- if (injector.getSystemWrapper()
- .getPropertyInt("ro.product.first_api_level", 0) <= 29) {
+ if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 29) {
// Mismatched signatures is an error and silently skipping system
// packages will likely break the device in unforeseen ways.
// However, we allow the device to boot anyway because, prior to Q,
@@ -17162,7 +17226,7 @@
reconciledPkg.pkgSetting.lastUpdateTime = System.currentTimeMillis();
res.removedInfo.broadcastAllowList = mAppsFilter.getVisibilityAllowList(
- reconciledPkg.pkgSetting, request.mAllUsers, mSettings.mPackages);
+ reconciledPkg.pkgSetting, request.mAllUsers, mSettings.getPackagesLocked());
if (reconciledPkg.prepareResult.system) {
// Remove existing system package
removePackageLI(oldPackage, true);
@@ -17186,7 +17250,7 @@
executeDeletePackageLIF(reconciledPkg.deletePackageAction, packageName,
true, request.mAllUsers, false, parsedPackage);
} catch (SystemDeleteException e) {
- if (Build.IS_ENG) {
+ if (mIsEngBuild) {
throw new RuntimeException("Unexpected failure", e);
// ignore; not possible for non-system app
}
@@ -17207,7 +17271,7 @@
}
// Update the in-memory copy of the previous code paths.
- PackageSetting ps1 = mSettings.mPackages.get(
+ PackageSetting ps1 = mSettings.getPackageLPr(
reconciledPkg.prepareResult.existingPackage.getPackageName());
if ((reconciledPkg.installArgs.installFlags & PackageManager.DONT_KILL_APP)
== 0) {
@@ -17236,7 +17300,7 @@
AndroidPackage pkg = commitReconciledScanResultLocked(reconciledPkg, request.mAllUsers);
updateSettingsLI(pkg, reconciledPkg.installArgs, request.mAllUsers, res);
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null) {
res.newUsers = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
ps.setUpdateAvailable(false /*updateAvailable*/);
@@ -17346,7 +17410,7 @@
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
reconciledPackages = reconcilePackagesLocked(
- reconcileRequest, mSettings.mKeySetManagerService, mInjector);
+ reconcileRequest, mSettings.getKeySetManagerService(), mInjector);
} catch (ReconcileFailure e) {
for (InstallRequest request : requests) {
request.installResult.setError("Reconciliation failed...", e);
@@ -17481,7 +17545,7 @@
if (performDexopt) {
// Compile the layout resources.
- if (mInjector.getSystemWrapper().getPropertyBoolean(PRECOMPILE_LAYOUTS, false)) {
+ if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");
mViewCompiler.compileLayouts(pkg);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -17824,7 +17888,7 @@
final SigningDetails sourceSigningDetails = (sourcePackageSetting == null
? SigningDetails.UNKNOWN : sourcePackageSetting.getSigningDetails());
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ final KeySetManagerService ksms = mSettings.getKeySetManagerService();
if (sourcePackageName.equals(parsedPackage.getPackageName())
&& (ksms.shouldCheckUpgradeKeySetLocked(
sourcePackageSetting, scanFlags))) {
@@ -17908,8 +17972,7 @@
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final ParsedPackage parsedPackage;
- try (PackageParser2 pp = new PackageParser2(mSeparateProcesses, false, mMetrics, null,
- mPackageParserCallback)) {
+ try (PackageParser2 pp = mInjector.getPreparingPackageParser()) {
parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
} catch (PackageParserException e) {
@@ -17958,8 +18021,8 @@
if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) {
parsedPackage.setSigningDetails(args.signingDetails);
} else {
- parsedPackage.setSigningDetails(
- ParsingPackageUtils.getSigningDetails(parsedPackage, false /* skipVerify */));
+ parsedPackage.setSigningDetails(ParsingPackageUtils.getSigningDetails(
+ parsedPackage, false /* skipVerify */));
}
} catch (PackageParserException e) {
throw new PrepareFailure("Failed collect during installPackageLI", e);
@@ -18023,7 +18086,7 @@
}
}
- PackageSetting ps = mSettings.mPackages.get(pkgName);
+ PackageSetting ps = mSettings.getPackageLPr(pkgName);
if (ps != null) {
if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
@@ -18042,7 +18105,7 @@
// Quick validity check that we're signed correctly if updating;
// we'll check this again later when scanning, but we want to
// bail early here before tripping over redefined permissions.
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ final KeySetManagerService ksms = mSettings.getKeySetManagerService();
if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) {
throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
@@ -18223,7 +18286,7 @@
scanFlags |= SCAN_MOVE;
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(pkgName);
+ final PackageSetting ps = mSettings.getPackageLPr(pkgName);
if (ps == null) {
res.setError(INSTALL_FAILED_INTERNAL_ERROR,
"Missing settings for moved package " + pkgName);
@@ -18252,7 +18315,7 @@
final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
derivedAbi = mInjector.getAbiHelper().derivePackageAbi(parsedPackage,
isUpdatedSystemAppFromExistingSetting || isUpdatedSystemAppInferred,
- abiOverride);
+ abiOverride, mAppLib32InstallDir);
derivedAbi.first.applyTo(parsedPackage);
derivedAbi.second.applyTo(parsedPackage);
} catch (PackageManagerException pme) {
@@ -18321,11 +18384,11 @@
"replacePackageLI: new=" + parsedPackage + ", old=" + oldPackage);
}
- ps = mSettings.mPackages.get(pkgName11);
+ ps = mSettings.getPackageLPr(pkgName11);
disabledPs = mSettings.getDisabledSystemPkgLPr(ps);
// verify signatures are valid
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ final KeySetManagerService ksms = mSettings.getKeySetManagerService();
if (ksms.shouldCheckUpgradeKeySetLocked(ps, scanFlags)) {
if (!ksms.checkUpgradeKeySetLocked(ps, parsedPackage)) {
throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
@@ -18528,7 +18591,7 @@
ArrayMap<String, String> fsverityCandidates = new ArrayMap<>();
if (legacyMode) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName());
+ final PackageSetting ps = mSettings.getPackageLPr(pkg.getPackageName());
if (ps != null && ps.isPrivileged()) {
fsverityCandidates.put(pkg.getBaseApkPath(), null);
if (pkg.getSplitCodePaths() != null) {
@@ -18946,7 +19009,7 @@
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(() -> {
int returnCode;
- final PackageSetting ps = mSettings.mPackages.get(internalPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(internalPackageName);
boolean doDeletePackage = true;
if (ps != null) {
final boolean targetIsInstantApp =
@@ -19224,7 +19287,7 @@
int[] allUsers;
/** enabled state of the uninstalled application */
synchronized (mLock) {
- uninstalledPs = mSettings.mPackages.get(packageName);
+ uninstalledPs = mSettings.getPackageLPr(packageName);
if (uninstalledPs == null) {
Slog.w(TAG, "Not removing non-existent package " + packageName);
return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
@@ -19523,7 +19586,7 @@
synchronized (mLock) {
clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL, true);
clearDefaultBrowserIfNeeded(packageName);
- mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
+ mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
mAppsFilter.removePackage(getPackageSetting(packageName));
removedAppId = mSettings.removePackageLPw(packageName);
if (outInfo != null) {
@@ -19673,7 +19736,7 @@
// We've re-installed the stub; make sure it's disabled here. If package was
// originally enabled, we'll install the compressed version of the application
// and re-enable it afterward.
- final PackageSetting stubPs = mSettings.mPackages.get(deletedPkg.getPackageName());
+ final PackageSetting stubPs = mSettings.getPackageLPr(deletedPkg.getPackageName());
if (stubPs != null) {
int userId = action.user == null
? UserHandle.USER_ALL : action.user.getIdentifier();
@@ -19729,7 +19792,7 @@
// writer
synchronized (mLock) {
- PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName());
+ PackageSetting ps = mSettings.getPackageLPr(pkg.getPackageName());
final boolean applyUserRestrictions = origUserHandles != null;
if (applyUserRestrictions) {
@@ -19822,7 +19885,7 @@
@Override
public boolean getBlockUninstallForUser(String packageName, int userId) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null || shouldFilterApplicationLocked(ps, Binder.getCallingUid(), userId)) {
return false;
}
@@ -19834,7 +19897,7 @@
public boolean setRequiredForSystemUser(String packageName, boolean systemUserApp) {
enforceSystemOrRoot("setRequiredForSystemUser can only be run by the system or root");
synchronized (mLock) {
- PackageSetting ps = mSettings.mPackages.get(packageName);
+ PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
Log.w(TAG, "Package doesn't exist: " + packageName);
return false;
@@ -19902,7 +19965,7 @@
ParsedPackage replacingPackage) {
final DeletePackageAction action;
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps);
action = mayDeletePackageLocked(outInfo, ps, disabledPs, flags, user);
}
@@ -20192,7 +20255,7 @@
PackageSetting ps;
synchronized (mLock) {
pkg = mPackages.get(packageName);
- ps = mSettings.mPackages.get(packageName);
+ ps = mSettings.getPackageLPr(packageName);
if (pkg == null) {
if (ps != null) {
pkg = ps.pkg;
@@ -20329,7 +20392,7 @@
private boolean getPackageSizeInfoLI(String packageName, int userId, PackageStats stats) {
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(packageName);
+ ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
Slog.w(TAG, "Failed to find settings for " + packageName);
return false;
@@ -21505,7 +21568,7 @@
public void setUpdateAvailable(String packageName, boolean updateAvailable) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
synchronized (mLock) {
- final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+ final PackageSetting pkgSetting = mSettings.getPackageLPr(packageName);
if (pkgSetting != null) {
pkgSetting.setUpdateAvailable(updateAvailable);
}
@@ -21630,7 +21693,7 @@
// reader
synchronized (mLock) {
- pkgSetting = mSettings.mPackages.get(packageName);
+ pkgSetting = mSettings.getPackageLPr(packageName);
if (pkgSetting == null) {
if (!isCallerInstantApp) {
if (className == null) {
@@ -21894,7 +21957,7 @@
return;
}
broadcastAllowList = isInstantApp ? null : mAppsFilter.getVisibilityAllowList(setting,
- userIds, mSettings.mPackages);
+ userIds, mSettings.getPackagesLocked());
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null,
userIds, instantUserIds, broadcastAllowList);
@@ -21914,7 +21977,7 @@
true /* checkShell */, "stop package");
// writer
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (!shouldFilterApplicationLocked(ps, callingUid, userId)
&& mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
allowedByPermission, callingUid, userId)) {
@@ -21933,7 +21996,7 @@
}
String installerPackageName = installSource.installerPackageName;
if (installerPackageName != null) {
- final PackageSetting ps = mSettings.mPackages.get(installerPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(installerPackageName);
if (ps == null || shouldFilterApplicationLocked(ps, callingUid,
UserHandle.getUserId(callingUid))) {
installerPackageName = null;
@@ -21962,7 +22025,7 @@
installerPackageName = installSource.installerPackageName;
if (installerPackageName != null) {
- final PackageSetting ps = mSettings.mPackages.get(installerPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(installerPackageName);
if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) {
installerPackageName = null;
}
@@ -21987,7 +22050,7 @@
initiatingPackageName = installerPackageName;
} else {
initiatingPackageName = installSource.initiatingPackageName;
- final PackageSetting ps = mSettings.mPackages.get(initiatingPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(initiatingPackageName);
if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) {
initiatingPackageName = null;
}
@@ -21996,7 +22059,7 @@
originatingPackageName = installSource.originatingPackageName;
if (originatingPackageName != null) {
- final PackageSetting ps = mSettings.mPackages.get(originatingPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(originatingPackageName);
if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) {
originatingPackageName = null;
}
@@ -22029,7 +22092,7 @@
@GuardedBy("mLock")
@Nullable
private InstallSource getInstallSourceLocked(String packageName, int callingUid) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
// Installer info for Apex is not stored in PackageManager
if (ps == null && mApexManager.isApexPackage(packageName)) {
@@ -22692,13 +22755,14 @@
&& dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)
&& packageName == null) {
pw.println();
- int count = mSettings.mPackages.size();
+ int count = mSettings.getPackagesLocked().size();
if (count == 0) {
pw.println("No applications!");
pw.println();
} else {
final String prefix = " ";
- Collection<PackageSetting> allPackageSettings = mSettings.mPackages.values();
+ Collection<PackageSetting> allPackageSettings =
+ mSettings.getPackagesLocked().values();
if (allPackageSettings.size() == 0) {
pw.println("No domain preferred apps!");
pw.println();
@@ -22755,7 +22819,7 @@
}
if (!checkin && dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
- mSettings.mKeySetManagerService.dumpLPr(pw, packageName, dumpState);
+ mSettings.getKeySetManagerService().dumpLPr(pw, packageName, dumpState);
}
if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
@@ -22886,7 +22950,7 @@
if (ArrayUtils.isEmpty(apkList)) {
return;
}
- String sku = mInjector.getSystemWrapper().getProperty("ro.boot.hardware.sku");
+ String sku = SystemProperties.get("ro.boot.hardware.sku");
if (!TextUtils.isEmpty(sku) && ArrayUtils.contains(skuArray, sku)) {
return;
}
@@ -22982,7 +23046,7 @@
ipw.increaseIndent();
Collection<PackageSetting> pkgSettings;
if (packageName != null) {
- PackageSetting targetPkgSetting = mSettings.mPackages.get(packageName);
+ PackageSetting targetPkgSetting = mSettings.getPackageLPr(packageName);
if (targetPkgSetting != null) {
pkgSettings = Collections.singletonList(targetPkgSetting);
} else {
@@ -22990,7 +23054,7 @@
return;
}
} else {
- pkgSettings = mSettings.mPackages.values();
+ pkgSettings = mSettings.getPackagesLocked().values();
}
for (PackageSetting pkgSetting : pkgSettings) {
@@ -23291,7 +23355,7 @@
// Normalize package name to handle renamed packages
packageName = normalizePackageNameLPr(packageName);
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
throw new PackageManagerException("Package " + packageName + " is unknown");
} else if (!TextUtils.equals(volumeUuid, ps.volumeUuid)) {
@@ -23308,9 +23372,9 @@
private List<String> collectAbsoluteCodePaths() {
synchronized (mLock) {
List<String> codePaths = new ArrayList<>();
- final int packageCount = mSettings.mPackages.size();
+ final int packageCount = mSettings.getPackagesLocked().size();
for (int i = 0; i < packageCount; i++) {
- final PackageSetting ps = mSettings.mPackages.valueAt(i);
+ final PackageSetting ps = mSettings.getPackagesLocked().valueAt(i);
codePaths.add(ps.getPath().getAbsolutePath());
}
return codePaths;
@@ -23512,7 +23576,7 @@
private void prepareAppDataAfterInstallLIF(AndroidPackage pkg) {
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(pkg.getPackageName());
+ ps = mSettings.getPackageLPr(pkg.getPackageName());
mSettings.writeKernelMappingLPr(ps);
}
@@ -23589,7 +23653,7 @@
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(pkg.getPackageName());
+ ps = mSettings.getPackageLPr(pkg.getPackageName());
}
final String volumeUuid = pkg.getVolumeUuid();
final String packageName = pkg.getPackageName();
@@ -23784,7 +23848,7 @@
mPackageName = packageName;
mWeFroze = mFrozenPackages.add(mPackageName);
- final PackageSetting ps = mSettings.mPackages.get(mPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(mPackageName);
if (ps != null) {
killApplication(ps.name, ps.appId, userId, killReason);
}
@@ -23866,7 +23930,7 @@
// reader
synchronized (mLock) {
final AndroidPackage pkg = mPackages.get(packageName);
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (pkg == null
|| ps == null
|| shouldFilterApplicationLocked(ps, callingUid, user.getIdentifier())) {
@@ -24197,9 +24261,9 @@
private void removeUnusedPackagesLPw(UserManagerService userManager, final int userId) {
final boolean DEBUG_CLEAN_APKS = false;
int [] users = userManager.getUserIds();
- final int numPackages = mSettings.mPackages.size();
+ final int numPackages = mSettings.getPackagesLocked().size();
for (int index = 0; index < numPackages; index++) {
- final PackageSetting ps = mSettings.mPackages.valueAt(index);
+ final PackageSetting ps = mSettings.getPackagesLocked().valueAt(index);
if (ps.pkg == null) {
continue;
}
@@ -24368,7 +24432,7 @@
Slog.w(TAG, "KeySet requested for filtered package: " + packageName);
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ final KeySetManagerService ksms = mSettings.getKeySetManagerService();
return new KeySet(ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias));
}
}
@@ -24397,7 +24461,7 @@
&& Process.SYSTEM_UID != callingUid) {
throw new SecurityException("May not access signing KeySet of other apps.");
}
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ final KeySetManagerService ksms = mSettings.getKeySetManagerService();
return new KeySet(ksms.getSigningKeySetByPackageNameLPr(packageName));
}
}
@@ -24421,7 +24485,7 @@
}
IBinder ksh = ks.getToken();
if (ksh instanceof KeySetHandle) {
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ final KeySetManagerService ksms = mSettings.getKeySetManagerService();
return ksms.packageIsSignedByLPr(packageName, (KeySetHandle) ksh);
}
return false;
@@ -24447,7 +24511,7 @@
}
IBinder ksh = ks.getToken();
if (ksh instanceof KeySetHandle) {
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ final KeySetManagerService ksms = mSettings.getKeySetManagerService();
return ksms.packageIsSignedByExactlyLPr(packageName, (KeySetHandle) ksh);
}
return false;
@@ -24456,7 +24520,7 @@
@GuardedBy("mLock")
private void deletePackageIfUnusedLPr(final String packageName) {
- PackageSetting ps = mSettings.mPackages.get(packageName);
+ PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
return;
}
@@ -24792,7 +24856,7 @@
@Override
public boolean isPlatformSigned(String packageName) {
- PackageSetting packageSetting = mSettings.mPackages.get(packageName);
+ PackageSetting packageSetting = mSettings.getPackageLPr(packageName);
if (packageSetting == null) {
return false;
}
@@ -25081,7 +25145,7 @@
@Override
public long getCeDataInode(String packageName, int userId) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null) {
return ps.getCeDataInode(userId);
}
@@ -25092,7 +25156,7 @@
@Override
public Bundle getSuspendedPackageLauncherExtras(String packageName, int userId) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
final Bundle allExtras = new Bundle();
if (ps != null) {
final PackageUserState pus = ps.readUserState(userId);
@@ -25114,7 +25178,7 @@
@Override
public boolean isPackageSuspended(String packageName, int userId) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
return (ps != null) ? ps.getSuspended(userId) : false;
}
}
@@ -25159,7 +25223,7 @@
@Override
public String getSuspendingPackage(String suspendedPackage, int userId) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(suspendedPackage);
+ final PackageSetting ps = mSettings.getPackageLPr(suspendedPackage);
if (ps != null) {
final PackageUserState pus = ps.readUserState(userId);
if (pus.suspended) {
@@ -25181,7 +25245,7 @@
public SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage,
String suspendingPackage, int userId) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(suspendedPackage);
+ final PackageSetting ps = mSettings.getPackageLPr(suspendedPackage);
if (ps != null) {
final PackageUserState pus = ps.readUserState(userId);
if (pus.suspended) {
@@ -25197,7 +25261,7 @@
@Override
public int getDistractingPackageRestrictions(String packageName, int userId) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
return (ps != null) ? ps.getDistractionFlags(userId) : RESTRICTION_NONE;
}
}
@@ -25293,7 +25357,7 @@
@Override
public boolean isPackageEphemeral(int userId, String packageName) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
return ps != null ? ps.getInstantApp(userId) : false;
}
}
@@ -25484,7 +25548,7 @@
continue;
}
for (VersionedPackage dependent : dependents) {
- final PackageSetting ps = mSettings.mPackages.get(
+ final PackageSetting ps = mSettings.getPackageLPr(
dependent.getPackageName());
if (ps == null) {
continue;
@@ -25495,7 +25559,7 @@
}
}
- final PackageSetting ps = mSettings.mPackages.get(targetPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(targetPackageName);
ps.setOverlayPaths(overlayPaths, userId);
outUpdatedPackageNames.add(targetPackageName);
@@ -25565,7 +25629,7 @@
@Override
public boolean canAccessComponent(int callingUid, ComponentName component, int userId) {
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+ final PackageSetting ps = mSettings.getPackageLPr(component.getPackageName());
return ps != null && !PackageManagerService.this.shouldFilterApplicationLocked(
ps, callingUid, component, TYPE_UNKNOWN, userId);
}
@@ -25631,8 +25695,8 @@
@Override
public void forEachPackageSetting(Consumer<PackageSetting> actionLocked) {
synchronized (mLock) {
- for (int index = 0; index < mSettings.mPackages.size(); index++) {
- actionLocked.accept(mSettings.mPackages.valueAt(index));
+ for (int index = 0; index < mSettings.getPackagesLocked().size(); index++) {
+ actionLocked.accept(mSettings.getPackagesLocked().valueAt(index));
}
}
}
@@ -25808,7 +25872,7 @@
return false;
}
final PackageSetting installerPackageSetting =
- mSettings.mPackages.get(packageSetting.installSource.installerPackageName);
+ mSettings.getPackageLPr(packageSetting.installSource.installerPackageName);
return installerPackageSetting != null
&& UserHandle.isSameApp(installerPackageSetting.appId, callingUid);
}
@@ -25909,7 +25973,7 @@
PackageManagerInternal.InstalledLoadingProgressCallback callback) {
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(packageName);
+ ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
Slog.w(TAG, "Failed unregistering loading progress callback. Package "
+ packageName + " is not installed");
@@ -25972,7 +26036,7 @@
@GuardedBy("mLock")
@NonNull
private String[] getSharedUserPackagesForPackageLocked(String packageName, int userId) {
- final PackageSetting packageSetting = mSettings.mPackages.get(packageName);
+ final PackageSetting packageSetting = mSettings.getPackageLPr(packageName);
if (packageSetting == null || !packageSetting.isSharedUser()) {
return EmptyArray.STRING;
}
@@ -26049,7 +26113,7 @@
synchronized (mLock) {
packageName = resolveInternalPackageNameInternalLocked(
packageName, PackageManager.VERSION_CODE_HIGHEST, callingUid);
- return mSettings.mPackages.get(packageName);
+ return mSettings.getPackageLPr(packageName);
}
}
@@ -26140,7 +26204,7 @@
enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */,
false /* checkShell */, "get install reason");
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
return PackageManager.INSTALL_REASON_UNKNOWN;
}
@@ -26313,7 +26377,7 @@
long currentTimeInMillis = System.currentTimeMillis();
synchronized (mLock) {
for (AndroidPackage pkg : mPackages.values()) {
- PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName());
+ PackageSetting ps = mSettings.getPackageLPr(pkg.getPackageName());
if (ps == null) {
continue;
}
@@ -26425,7 +26489,7 @@
@Override
public void setMimeGroup(String packageName, String mimeGroup, List<String> mimeTypes) {
- boolean changed = mSettings.mPackages.get(packageName)
+ boolean changed = mSettings.getPackageLPr(packageName)
.setMimeGroup(mimeGroup, mimeTypes);
if (changed) {
@@ -26435,7 +26499,7 @@
@Override
public List<String> getMimeGroup(String packageName, String mimeGroup) {
- return mSettings.mPackages.get(packageName).getMimeGroup(mimeGroup);
+ return mSettings.getPackageLPr(packageName).getMimeGroup(mimeGroup);
}
/**
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f47b4b4..38c6481 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -475,6 +475,14 @@
return mPackages.get(pkgName);
}
+ ArrayMap<String, PackageSetting> getPackagesLocked() {
+ return mPackages;
+ }
+
+ KeySetManagerService getKeySetManagerService() {
+ return mKeySetManagerService;
+ }
+
String getRenamedPackageLPr(String pkgName) {
return mRenamedPackages.get(pkgName);
}
@@ -5554,7 +5562,8 @@
return mPreferredActivities.get(userId);
}
- CrossProfileIntentResolver getCrossProfileIntentResolvers(int userId) {
+ @Nullable
+ CrossProfileIntentResolver getCrossProfileIntentResolver(int userId) {
return mCrossProfileIntentResolvers.get(userId);
}
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index 7d48d0a..e913829 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -30,6 +30,14 @@
]
},
{
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.pm."
+ }
+ ]
+ },
+ {
"name": "CtsContentTestCases",
"options": [
{
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 8fc5c08..03083c1 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -15,7 +15,7 @@
android_test {
name: "FrameworksMockingServicesTests",
- srcs: ["src/**/*.java"],
+ srcs: ["src/**/*.java", "src/**/*.kt"],
static_libs: [
"services.core",
@@ -29,6 +29,10 @@
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
"truth-prebuilt",
+ "hamcrest-library",
+ "servicestests-utils-mockito-extended",
+ "mockingservicestests-utils-mockito",
+ "servicestests-core-utils",
"testables",
// TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows
"testng",
@@ -54,3 +58,17 @@
enabled: false,
},
}
+
+java_library {
+ name: "mockingservicestests-utils-mockito",
+ srcs: [
+ "utils-mockito/**/*.kt",
+ ],
+ static_libs: [
+ "junit",
+ "mockito-target-extended-minus-junit4",
+ ],
+ libs: [
+ "android.test.runner",
+ ],
+}
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
new file mode 100644
index 0000000..edae08a3
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -0,0 +1,662 @@
+/*
+ * Copyright (C) 2020 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 android.content.Context
+import android.content.Intent
+import android.content.pm.ActivityInfo
+import android.content.pm.ApplicationInfo
+import android.content.pm.FallbackCategoryProvider
+import android.content.pm.FeatureInfo
+import android.content.pm.PackageParser.SigningDetails
+import android.content.pm.ResolveInfo
+import android.content.pm.ServiceInfo
+import android.content.pm.Signature
+import android.content.pm.UserInfo
+import android.content.pm.parsing.ParsingPackage
+import android.content.pm.parsing.ParsingPackageUtils
+import android.content.res.Resources
+import android.hardware.display.DisplayManager
+import android.os.Build
+import android.os.Environment
+import android.os.SystemProperties
+import android.os.UserHandle
+import android.os.UserManager
+import android.os.incremental.IncrementalManager
+import android.permission.IPermissionManager
+import android.util.ArrayMap
+import android.util.DisplayMetrics
+import android.util.EventLog
+import android.view.Display
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.dx.mockito.inline.extended.ExtendedMockito.any
+import com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean
+import com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt
+import com.android.dx.mockito.inline.extended.ExtendedMockito.anyString
+import com.android.dx.mockito.inline.extended.ExtendedMockito.argThat
+import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
+import com.android.dx.mockito.inline.extended.ExtendedMockito.eq
+import com.android.dx.mockito.inline.extended.ExtendedMockito.spy
+import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder
+import com.android.internal.R
+import com.android.server.LocalServices
+import com.android.server.LockGuard
+import com.android.server.SystemConfig
+import com.android.server.SystemServerInitThreadPool
+import com.android.server.compat.PlatformCompat
+import com.android.server.extendedtestutils.wheneverStatic
+import com.android.server.pm.dex.DexManager
+import com.android.server.pm.parsing.PackageParser2
+import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.PackageImpl
+import com.android.server.pm.parsing.pkg.ParsedPackage
+import com.android.server.pm.permission.PermissionManagerServiceInternal
+import com.android.server.testutils.mock
+import com.android.server.testutils.nullable
+import com.android.server.testutils.whenever
+import org.junit.Assert
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+import org.mockito.AdditionalMatchers.or
+import org.mockito.invocation.InvocationOnMock
+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
+ *
+ * Create one of these and call [stageNominalSystemState] as a basis for additional behavior in most
+ * tests.
+ */
+class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
+ private val random = Random()
+ val mocks = Mocks()
+ val packageCacheDirectory: File =
+ Files.createTempDirectory("packageCache").toFile()
+ val rootDirectory: File =
+ Files.createTempDirectory("root").toFile()
+ val dataAppDirectory: File =
+ File(Files.createTempDirectory("data").toFile(), "app")
+ val frameworkSignature: SigningDetails = SigningDetails(arrayOf(generateSpySignature()), 3)
+ val systemPartitions: List<PackageManagerService.ScanPartition> =
+ redirectScanPartitions(PackageManagerService.SYSTEM_PARTITIONS)
+ val session: StaticMockitoSession
+
+ /** Tracks temporary files created by this class during the running of a test. */
+ private val createdFiles = ArrayList<File>()
+
+ /** Settings that are expected to be added as part of the test */
+ private val mPendingPackageAdds: MutableList<Pair<String, PackageSetting>> = ArrayList()
+
+ /** Settings simulated to be stored on disk */
+ private val mPreExistingSettings = ArrayMap<String, PackageSetting>()
+
+ /** The active map simulating the in memory storage of Settings */
+ private val mSettingsMap = ArrayMap<String, PackageSetting>()
+
+ init {
+ val apply = ExtendedMockito.mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .mockStatic(SystemProperties::class.java)
+ .mockStatic(SystemConfig::class.java)
+ .mockStatic(SELinuxMMAC::class.java)
+ .mockStatic(FallbackCategoryProvider::class.java)
+ .mockStatic(PackageManagerServiceUtils::class.java)
+ .mockStatic(Environment::class.java)
+ .mockStatic(SystemServerInitThreadPool::class.java)
+ .mockStatic(ParsingPackageUtils::class.java)
+ .mockStatic(LockGuard::class.java)
+ .mockStatic(EventLog::class.java)
+ .mockStatic(LocalServices::class.java)
+ .apply(withSession)
+ session = apply.startMocking()
+ whenever(mocks.settings.insertPackageSettingLPw(
+ any(PackageSetting::class.java), any(AndroidPackage::class.java))) {
+ val name: String = (getArgument<Any>(0) as PackageSetting).name
+ val pendingAdd =
+ mPendingPackageAdds.firstOrNull { it.first == name } ?: return@whenever null
+ mPendingPackageAdds.remove(pendingAdd)
+ mSettingsMap[name] = pendingAdd.second
+ null
+ }
+ whenever(mocks.settings.addPackageLPw(nullable(), nullable(), nullable(), nullable(),
+ nullable(), nullable(), nullable(), nullable(), nullable(), nullable(), nullable(),
+ nullable(), nullable(), nullable())) {
+ val name: String = getArgument(0)
+ val pendingAdd = mPendingPackageAdds.firstOrNull { it.first == name }
+ ?: return@whenever null
+ mPendingPackageAdds.remove(pendingAdd)
+ mSettingsMap[name] = pendingAdd.second
+ pendingAdd.second
+ }
+ whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap)
+ whenever(mocks.settings.getPackageLPr(anyString())) { mSettingsMap[getArgument<Any>(0)] }
+ whenever(mocks.settings.readLPw(nullable())) {
+ mSettingsMap.putAll(mPreExistingSettings)
+ !mPreExistingSettings.isEmpty()
+ }
+ }
+
+ /** Collection of mocks used for PackageManagerService tests. */
+
+ class Mocks {
+ val lock = Any()
+ val installLock = Any()
+ val injector: PackageManagerService.Injector = mock()
+ val systemWrapper: PackageManagerService.SystemWrapper = mock()
+ val context: Context = mock()
+ val userManagerService: UserManagerService = mock()
+ val componentResolver: ComponentResolver = mock()
+ val permissionManagerInternal: PermissionManagerServiceInternal = mock()
+ val incrementalManager: IncrementalManager = mock()
+ val platformCompat: PlatformCompat = mock()
+ val settings: Settings = mock()
+ val resources: Resources = mock()
+ val systemConfig: SystemConfig = mock()
+ val apexManager: ApexManager = mock()
+ val userManagerInternal: UserManagerInternal = mock()
+ val packageParser: PackageParser2 = mock()
+ val keySetManagerService: KeySetManagerService = mock()
+ val packageAbiHelper: PackageAbiHelper = mock()
+ val appsFilter: AppsFilter = mock()
+ val dexManager: DexManager = mock()
+ val installer: Installer = mock()
+ val displayMetrics: DisplayMetrics = mock()
+ val permissionManager: IPermissionManager = mock()
+ }
+
+ companion object {
+ private const val DEVICE_PROVISIONING_PACKAGE_NAME =
+ "com.example.android.device.provisioning"
+ private val DEFAULT_AVAILABLE_FEATURES_MAP = ArrayMap<String, FeatureInfo>()
+ private val DEFAULT_ACTIVE_APEX_INFO_LIST = emptyList<ApexManager.ActiveApexInfo>()
+ private val DEFAULT_SHARED_LIBRARIES_LIST =
+ ArrayMap<String, SystemConfig.SharedLibraryEntry>()
+ private val DEFAULT_USERS = Arrays.asList(
+ UserInfo(UserHandle.USER_SYSTEM, "primary", "",
+ UserInfo.FLAG_PRIMARY or UserInfo.FLAG_SYSTEM or UserInfo.FLAG_FULL,
+ UserManager.USER_TYPE_FULL_SYSTEM))
+ public val DEFAULT_VERSION_INFO = Settings.VersionInfo()
+
+ init {
+ DEFAULT_VERSION_INFO.fingerprint = "abcdef"
+ DEFAULT_VERSION_INFO.sdkVersion = Build.VERSION_CODES.R
+ DEFAULT_VERSION_INFO.databaseVersion = Settings.CURRENT_DATABASE_VERSION
+ }
+ }
+
+ /**
+ * Clean up any potentially dangling state. This should be run at the end of every test to
+ * account for changes to static memory, such as [LocalServices]
+ */
+ fun cleanup() {
+ createdFiles.forEach(File::delete)
+ createdFiles.clear()
+ mSettingsMap.clear()
+ mPendingPackageAdds.clear()
+ mPreExistingSettings.clear()
+ session.finishMocking()
+ }
+
+ /**
+ * Run this method to ensure that all expected actions were executed, such as pending
+ * [Settings] adds.
+ */
+ fun validateFinalState() {
+ if (mPendingPackageAdds.isNotEmpty()) {
+ Assert.fail(
+ "Not all expected settings were added: ${mPendingPackageAdds.map { it.first }}")
+ }
+ }
+
+ /**
+ * This method stages enough of system startup to execute the PackageManagerService constructor
+ * successfullly.
+ */
+ @Throws(Exception::class)
+ fun stageNominalSystemState() {
+ whenever(mocks.injector.context).thenReturn(mocks.context)
+ whenever(mocks.injector.lock).thenReturn(mocks.lock)
+ whenever(mocks.injector.installLock).thenReturn(mocks.installLock)
+ whenever(mocks.injector.systemWrapper).thenReturn(mocks.systemWrapper)
+ whenever(mocks.injector.userManagerService).thenReturn(mocks.userManagerService)
+ whenever(mocks.injector.componentResolver).thenReturn(mocks.componentResolver)
+ whenever(mocks.injector.permissionManagerServiceInternal) {
+ mocks.permissionManagerInternal
+ }
+ whenever(mocks.injector.permissionManagerService).thenReturn(mocks.permissionManager)
+ whenever(mocks.injector.incrementalManager).thenReturn(mocks.incrementalManager)
+ whenever(mocks.injector.compatibility).thenReturn(mocks.platformCompat)
+ whenever(mocks.injector.settings).thenReturn(mocks.settings)
+ whenever(mocks.injector.dexManager).thenReturn(mocks.dexManager)
+ whenever(mocks.injector.systemConfig).thenReturn(mocks.systemConfig)
+ whenever(mocks.injector.apexManager).thenReturn(mocks.apexManager)
+ whenever(mocks.injector.scanningCachingPackageParser).thenReturn(mocks.packageParser)
+ whenever(mocks.injector.scanningPackageParser).thenReturn(mocks.packageParser)
+ whenever(mocks.injector.systemPartitions).thenReturn(systemPartitions)
+ whenever(mocks.injector.appsFilter).thenReturn(mocks.appsFilter)
+ whenever(mocks.injector.abiHelper).thenReturn(mocks.packageAbiHelper)
+ whenever(mocks.injector.userManagerInternal).thenReturn(mocks.userManagerInternal)
+ whenever(mocks.injector.installer).thenReturn(mocks.installer)
+ whenever(mocks.injector.displayMetrics).thenReturn(mocks.displayMetrics)
+ wheneverStatic { SystemConfig.getInstance() }.thenReturn(mocks.systemConfig)
+ whenever(mocks.systemConfig.availableFeatures).thenReturn(DEFAULT_AVAILABLE_FEATURES_MAP)
+ whenever(mocks.systemConfig.sharedLibraries).thenReturn(DEFAULT_SHARED_LIBRARIES_LIST)
+ wheneverStatic { SystemProperties.getBoolean("fw.free_cache_v2", true) }.thenReturn(true)
+ wheneverStatic { Environment.getPackageCacheDirectory() }.thenReturn(packageCacheDirectory)
+ wheneverStatic { SystemProperties.digestOf("ro.build.fingerprint") }.thenReturn("cacheName")
+ wheneverStatic { Environment.getRootDirectory() }.thenReturn(rootDirectory)
+ wheneverStatic { SystemServerInitThreadPool.submit(any(Runnable::class.java), anyString())}
+ .thenAnswer { FutureTask<Any?>(it.getArgument(0), null) }
+
+ wheneverStatic { Environment.getDataDirectory() }.thenReturn(dataAppDirectory.parentFile)
+ wheneverStatic { Environment.getDataSystemDirectory() }
+ .thenReturn(File(dataAppDirectory.parentFile, "system"))
+ whenever(mocks.context.resources).thenReturn(mocks.resources)
+ whenever(mocks.resources.getString(R.string.config_deviceProvisioningPackage)) {
+ DEVICE_PROVISIONING_PACKAGE_NAME
+ }
+ whenever(mocks.apexManager.activeApexInfos).thenReturn(DEFAULT_ACTIVE_APEX_INFO_LIST)
+ whenever(mocks.settings.packagesLocked).thenReturn(mSettingsMap)
+ whenever(mocks.settings.internalVersion).thenReturn(DEFAULT_VERSION_INFO)
+ whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService)
+ whenever(mocks.settings.keySetManagerService).thenReturn(mocks.keySetManagerService)
+ whenever(mocks.packageAbiHelper.derivePackageAbi(
+ any(AndroidPackage::class.java), anyBoolean(), nullable(), any(File::class.java))) {
+ android.util.Pair(PackageAbiHelper.Abis("", ""),
+ PackageAbiHelper.NativeLibraryPaths("", false, "", ""))
+ }
+ whenever(mocks.userManagerInternal.getUsers(true, false, false)).thenReturn(DEFAULT_USERS)
+ whenever(mocks.userManagerService.userIds).thenReturn(intArrayOf(0))
+ whenever(mocks.userManagerService.exists(0)).thenReturn(true)
+ whenever(mocks.packageAbiHelper.deriveNativeLibraryPaths(
+ any(AndroidPackage::class.java), anyBoolean(), any(File::class.java))) {
+ PackageAbiHelper.NativeLibraryPaths("", false, "", "")
+ }
+ // everything visible by default
+ whenever(mocks.appsFilter.shouldFilterApplication(
+ anyInt(), nullable(), nullable(), anyInt())) { false }
+
+ val displayManager: DisplayManager = mock()
+ whenever(mocks.context.getSystemService(DisplayManager::class.java))
+ .thenReturn(displayManager)
+ val display: Display = mock()
+ whenever(displayManager.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(display)
+
+ stageFrameworkScan()
+ stageInstallerScan()
+ stageServicesExtensionScan()
+ stageSystemSharedLibraryScan()
+ stagePermissionsControllerScan()
+ stageInstantAppResolverScan()
+ }
+
+ /**
+ * This method will stage the parsing and scanning of a package as well as add it to the
+ * [PackageSetting]s read from disk.
+ */
+ @Throws(Exception::class)
+ fun stageScanExistingPackage(
+ packageName: String,
+ versionCode: Long,
+ parent: File?,
+ withPackage: (PackageImpl) -> PackageImpl = { it },
+ withSetting:
+ (PackageSettingBuilder) -> PackageSettingBuilder = { it },
+ withExistingSetting:
+ (PackageSettingBuilder) -> PackageSettingBuilder = { it }
+ ) {
+ val existingSettingBuilderRef = arrayOfNulls<PackageSettingBuilder>(1)
+ stageScanNewPackage(packageName, versionCode, parent, withPackage,
+ withSetting = { settingBuilder ->
+ withSetting(settingBuilder)
+ existingSettingBuilderRef[0] = settingBuilder
+ settingBuilder
+ })
+ existingSettingBuilderRef[0]?.setPackage(null)
+ val packageSetting = existingSettingBuilderRef[0]?.let { withExistingSetting(it) }!!.build()
+ addPreExistingSetting(packageName, packageSetting)
+ }
+
+ /**
+ * This method will stage a [PackageSetting] read from disk, but does not stage any scanning
+ * or parsing of the package.
+ */
+ fun addPreExistingSetting(packageName: String, packageSetting: PackageSetting) {
+ mPreExistingSettings[packageName] = packageSetting
+ }
+
+ /**
+ * This method will stage the parsing and scanning of a package but will not add it to the set
+ * of [PackageSetting]s read from disk.
+ */
+ @Throws(Exception::class)
+ fun stageScanNewPackage(
+ packageName: String,
+ versionCode: Long,
+ parent: File?,
+ withPackage: (PackageImpl) -> PackageImpl = { it },
+ withSetting: (PackageSettingBuilder) -> PackageSettingBuilder = { it }
+ ) {
+ val pair = createBasicAndroidPackage(parent, packageName, versionCode)
+ val apkPath = pair.first
+ val pkg = withPackage(pair.second)
+ stageParse(apkPath, pkg)
+ val parentFile = apkPath.parentFile
+ val settingBuilder = withSetting(createBasicSettingBuilder(parentFile, pkg))
+ stageSettingInsert(packageName, settingBuilder.build())
+ }
+
+ /**
+ * Creates a simple package that should reasonably parse for scan operations. This can be used
+ * as a basis for more complicated packages.
+ */
+ fun createBasicAndroidPackage(
+ parent: File?,
+ packageName: String,
+ versionCode: Long,
+ signingDetails: SigningDetails =
+ createRandomSigningDetails()
+ ): Pair<File, PackageImpl> {
+ val apkPath = File(File(parent, packageName), "base.apk")
+ val pkg = PackageImpl.forTesting(packageName, apkPath.parentFile.path) as PackageImpl
+ pkg.signingDetails = signingDetails
+ wheneverStatic { ParsingPackageUtils.getSigningDetails(eq(pkg), anyBoolean()) }
+ .thenReturn(signingDetails)
+ pkg.versionCode = versionCode.toInt()
+ pkg.versionCodeMajor = (versionCode shr 32).toInt()
+ pkg.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT
+ return Pair(apkPath, pkg)
+ }
+
+ /**
+ * This method will create a spy of a [SigningDetails] object to be used when simulating the
+ * collection of signatures.
+ */
+ fun createRandomSigningDetails(): SigningDetails {
+ val signingDetails = spy(SigningDetails(arrayOf(generateSpySignature()),
+ SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3))
+ doReturn(true).whenever(signingDetails).checkCapability(
+ anyString(), anyInt())
+ doReturn(true).whenever(signingDetails).checkCapability(
+ any(SigningDetails::class.java), anyInt())
+ return signingDetails
+ }
+
+ /**
+ * This method will create a basic [PackageSettingBuilder] from an [AndroidPackage] with all of
+ * the necessary parameters to be returned by a simple scan. This can be used as a basis for
+ * more complicated settings.
+ */
+ fun createBasicSettingBuilder(parentFile: File, pkg: AndroidPackage): PackageSettingBuilder {
+ return createBasicSettingBuilder(parentFile, pkg.packageName, pkg.longVersionCode,
+ pkg.signingDetails)
+ .setPackage(pkg)
+ }
+
+ /**
+ * This method will create a basic [PackageSettingBuilder] with all of the necessary parameters
+ * to be returned by a simple scan. This can be used as a basis for more complicated settings.
+ */
+ fun createBasicSettingBuilder(
+ parentFile: File,
+ packageName: String,
+ versionCode: Long,
+ signingDetails: SigningDetails
+ ): PackageSettingBuilder {
+ return PackageSettingBuilder()
+ .setCodePath(parentFile.path)
+ .setName(packageName)
+ .setPVersionCode(versionCode)
+ .setSigningDetails(signingDetails)
+ }
+
+ fun createBasicApplicationInfo(pkg: ParsingPackage): ApplicationInfo {
+ val applicationInfo: ApplicationInfo = mock()
+ applicationInfo.packageName = pkg.packageName
+ return applicationInfo
+ }
+
+ fun createBasicActivityInfo(
+ pkg: ParsingPackage,
+ applicationInfo: ApplicationInfo?,
+ className: String?
+ ):
+ ActivityInfo {
+ val activityInfo = ActivityInfo()
+ activityInfo.applicationInfo = applicationInfo
+ activityInfo.packageName = pkg.packageName
+ activityInfo.name = className
+ return activityInfo
+ }
+
+ fun createBasicServiceInfo(
+ pkg: ParsingPackage,
+ applicationInfo: ApplicationInfo?,
+ className: String?
+ ):
+ ServiceInfo {
+ val serviceInfo = ServiceInfo()
+ serviceInfo.applicationInfo = applicationInfo
+ serviceInfo.packageName = pkg.packageName
+ serviceInfo.name = className
+ return serviceInfo
+ }
+
+ /** Finds the appropriate partition, if available, based on a scan flag unique to it. */
+ fun getPartitionFromFlag(scanFlagMask: Int): PackageManagerService.ScanPartition =
+ systemPartitions.first { (it.scanFlag and scanFlagMask) != 0 }
+
+ @Throws(Exception::class)
+ private fun stageParse(path: File, parseResult: ParsingPackage): ParsedPackage {
+ val basePath = path.parentFile
+ basePath.mkdirs()
+ path.createNewFile()
+ createdFiles.add(path)
+ val parsedPackage = parseResult.hideAsParsed() as ParsedPackage
+ whenever(mocks.packageParser.parsePackage(
+ or(eq(path), eq(basePath)), anyInt(), anyBoolean())) { parsedPackage }
+ return parsedPackage
+ }
+
+ private fun stageSettingInsert(name: String, setting: PackageSetting): PackageSetting {
+ mPendingPackageAdds.add(Pair(name, setting))
+ return setting
+ }
+
+ @Throws(Exception::class)
+ private fun stageFrameworkScan() {
+ val apk = File(File(rootDirectory, "framework"), "framework-res.apk")
+ val frameworkPkg = PackageImpl.forTesting("android",
+ apk.parentFile.path) as PackageImpl
+ wheneverStatic { ParsingPackageUtils.getSigningDetails(frameworkPkg, true) }
+ .thenReturn(frameworkSignature)
+ stageParse(apk, frameworkPkg)
+ stageSettingInsert("android",
+ PackageSettingBuilder().setCodePath(apk.path).setName(
+ "android").setPackage(frameworkPkg).build())
+ }
+
+ @Throws(Exception::class)
+ private fun stageInstantAppResolverScan() {
+ whenever(mocks.resources.getStringArray(R.array.config_ephemeralResolverPackage)) {
+ arrayOf("com.android.test.ephemeral.resolver")
+ }
+ stageScanNewPackage("com.android.test.ephemeral.resolver",
+ 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_PRODUCT).privAppFolder,
+ withPackage = { pkg: PackageImpl ->
+ val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg)
+ whenever(applicationInfo.isPrivilegedApp).thenReturn(true)
+ mockQueryServices(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE,
+ createBasicServiceInfo(pkg, applicationInfo, "test.EphemeralService"))
+ mockQueryActivities(Intent.ACTION_INSTANT_APP_RESOLVER_SETTINGS,
+ createBasicActivityInfo(pkg, applicationInfo, "test.SettingsActivity"))
+ pkg
+ },
+ withSetting = { setting: PackageSettingBuilder ->
+ setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
+ })
+ }
+
+ @Throws(Exception::class)
+ private fun stagePermissionsControllerScan() {
+ stageScanNewPackage("com.android.permissions.controller",
+ 1L, systemPartitions[0].privAppFolder,
+ withPackage = { pkg: PackageImpl ->
+ val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg)
+ whenever(applicationInfo.isPrivilegedApp).thenReturn(true)
+ mockQueryActivities(Intent.ACTION_MANAGE_PERMISSIONS,
+ createBasicActivityInfo(
+ pkg, applicationInfo, "test.PermissionActivity"))
+ pkg
+ },
+ withSetting = { setting: PackageSettingBuilder ->
+ setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
+ })
+ }
+
+ @Throws(Exception::class)
+ private fun stageSystemSharedLibraryScan() {
+ stageScanNewPackage("android.ext.shared",
+ 1L, systemPartitions[0].appFolder,
+ withPackage = { it.addLibraryName("android.ext.shared") as PackageImpl },
+ withSetting = { setting: PackageSettingBuilder ->
+ setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
+ }
+ )
+ }
+
+ @Throws(Exception::class)
+ private fun stageServicesExtensionScan() {
+ whenever(mocks.context.getString(R.string.config_servicesExtensionPackage)) {
+ "com.android.test.services.extension"
+ }
+ stageScanNewPackage("com.android.test.services.extension",
+ 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_SYSTEM_EXT).privAppFolder,
+ withSetting = { setting: PackageSettingBuilder ->
+ setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
+ })
+ }
+
+ @Throws(Exception::class)
+ private fun stageInstallerScan() {
+ stageScanNewPackage(
+ "com.android.test.installer",
+ 1L, getPartitionFromFlag(PackageManagerService.SCAN_AS_PRODUCT).privAppFolder,
+ withPackage = { pkg: PackageImpl ->
+ val applicationInfo: ApplicationInfo = createBasicApplicationInfo(pkg)
+ whenever(applicationInfo.isPrivilegedApp).thenReturn(true)
+ val installerActivity: ActivityInfo = createBasicActivityInfo(
+ pkg, applicationInfo, "test.InstallerActivity")
+ mockQueryActivities(Intent.ACTION_INSTALL_PACKAGE, installerActivity)
+ mockQueryActivities(Intent.ACTION_UNINSTALL_PACKAGE, installerActivity)
+ mockQueryActivities(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE,
+ installerActivity)
+ pkg
+ },
+ withSetting = { setting: PackageSettingBuilder ->
+ setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
+ }
+ )
+ }
+
+ private fun mockQueryActivities(action: String, vararg activities: ActivityInfo) {
+ whenever(mocks.componentResolver.queryActivities(
+ argThat { intent: Intent? -> intent != null && (action == intent.action) },
+ nullable(), anyInt(), anyInt())) {
+ ArrayList(activities.asList().map { info: ActivityInfo? ->
+ ResolveInfo().apply { activityInfo = info }
+ })
+ }
+ }
+
+ private fun mockQueryServices(action: String, vararg services: ServiceInfo) {
+ whenever(mocks.componentResolver.queryServices(
+ argThat { intent: Intent? -> intent != null && (action == intent.action) },
+ nullable(), anyInt(), anyInt())) {
+ ArrayList(services.asList().map { info ->
+ ResolveInfo().apply { serviceInfo = info }
+ })
+ }
+ }
+
+ fun generateSpySignature(): Signature {
+ val bytes = ByteArray(32)
+ random.nextBytes(bytes)
+ val signature = spy(Signature(bytes))
+ try {
+ val mockPublicKey: PublicKey = mock()
+ doReturn(mockPublicKey).whenever(signature).getPublicKey()
+ } catch (e: CertificateException) {
+ throw RuntimeException(e)
+ }
+ return signature
+ }
+
+ /** Override get*Folder methods to point to temporary local directories */
+
+ @Throws(IOException::class)
+ private fun redirectScanPartitions(partitions: List<PackageManagerService.ScanPartition>):
+ List<PackageManagerService.ScanPartition> {
+ val spiedPartitions: MutableList<PackageManagerService.ScanPartition> =
+ ArrayList(partitions.size)
+ for (partition: PackageManagerService.ScanPartition in partitions) {
+ val spy = spy(partition)
+ val newRoot = Files.createTempDirectory(partition.folder.name).toFile()
+ whenever(spy.overlayFolder).thenReturn(File(newRoot, "overlay"))
+ whenever(spy.appFolder).thenReturn(File(newRoot, "app"))
+ whenever(spy.privAppFolder).thenReturn(File(newRoot, "priv-app"))
+ whenever(spy.folder).thenReturn(newRoot)
+ spiedPartitions.add(spy)
+ }
+ return spiedPartitions
+ }
+}
+
+/**
+ * Sets up a basic [MockSystem] for use in a test method. This will create a MockSystem before the
+ * test method and any [org.junit.Before] annotated methods. It can then be used to access the
+ * MockSystem via the [system] method or the mocks directly via [mocks].
+ */
+class MockSystemRule : TestRule {
+ var mockSystem: MockSystem? = null
+ override fun apply(base: Statement?, description: Description?) = object : Statement() {
+ @Throws(Throwable::class)
+ override fun evaluate() {
+ mockSystem = MockSystem()
+ try {
+ base!!.evaluate()
+ } finally {
+ mockSystem?.cleanup()
+ mockSystem = null
+ }
+ }
+ }
+
+ /** Fetch the [MockSystem] instance prepared for this test */
+ fun system(): MockSystem = mockSystem!!
+ /** Fetch the [MockSystem.Mocks] prepared for this test */
+ fun mocks(): MockSystem.Mocks = mockSystem!!.mocks
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt
new file mode 100644
index 0000000..bd44c36
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2020 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 android.content.pm.ApplicationInfo.FLAG_SYSTEM
+import android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
+import android.content.pm.PackageManager
+import android.content.pm.PackageParser
+import android.os.Build
+import android.os.Process
+import android.util.Log
+import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.testutils.whenever
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers.equalTo
+import org.hamcrest.Matchers.notNullValue
+import org.hamcrest.collection.IsMapContaining.hasKey
+import org.hamcrest.core.IsNot.not
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.argThat
+import org.mockito.Mockito
+import org.mockito.Mockito.verify
+import java.io.File
+
+@RunWith(JUnit4::class)
+class PackageManagerServiceBootTest {
+
+ @Rule
+ @JvmField
+ val rule = MockSystemRule()
+
+ @Before
+ @Throws(Exception::class)
+ fun setup() {
+ Log.i("system.out", "setup", Exception())
+ rule.system().stageNominalSystemState()
+ }
+
+ private fun createPackageManagerService(): PackageManagerService {
+ return PackageManagerService(rule.mocks().injector,
+ false /*coreOnly*/,
+ false /*factoryTest*/,
+ MockSystem.DEFAULT_VERSION_INFO.fingerprint,
+ false /*isEngBuild*/,
+ false /*isUserDebugBuild*/,
+ Build.VERSION_CODES.CUR_DEVELOPMENT,
+ Build.VERSION.INCREMENTAL)
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun simpleConstruction() {
+ val pm = createPackageManagerService()
+ verify(rule.mocks().injector).bootstrap(pm)
+ verify(rule.mocks().settings).addSharedUserLPw("android.uid.system",
+ Process.SYSTEM_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+ verify(rule.mocks().settings).addSharedUserLPw("android.uid.phone",
+ Process.PHONE_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+ verify(rule.mocks().settings).addSharedUserLPw("android.uid.log",
+ Process.LOG_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+ verify(rule.mocks().settings).addSharedUserLPw("android.uid.nfc",
+ Process.NFC_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+ verify(rule.mocks().settings).addSharedUserLPw("android.uid.bluetooth",
+ Process.BLUETOOTH_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+ verify(rule.mocks().settings).addSharedUserLPw("android.uid.shell",
+ Process.SHELL_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+ verify(rule.mocks().settings).addSharedUserLPw("android.uid.se",
+ Process.SE_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+ verify(rule.mocks().settings).addSharedUserLPw("android.uid.networkstack",
+ Process.NETWORK_STACK_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+ rule.system().validateFinalState()
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun existingDataPackage_remains() {
+ rule.system().stageScanExistingPackage("a.data.package", 1L, rule.system().dataAppDirectory)
+ val pm = createPackageManagerService()
+ rule.system().validateFinalState()
+ assertThat(pm.mPackages, hasKey("a.data.package"))
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun unexpectedDataPackage_isRemoved() {
+ rule.system().stageScanNewPackage(
+ "a.data.package", 1L, rule.system().dataAppDirectory)
+ val pm = createPackageManagerService()
+ verify(rule.mocks().settings, Mockito.never()).insertPackageSettingLPw(
+ argThat { setting: PackageSetting -> setting.name == "a.data.package" },
+ argThat { pkg: AndroidPackage -> pkg.packageName == "a.data.package" })
+ assertThat(pm.mPackages, not(hasKey("a.data.package")))
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun expectedPackageMissing_doesNotReplace() {
+ // setup existing package
+ rule.system().stageScanExistingPackage("a.data.package", 1L,
+ rule.system().dataAppDirectory)
+ // simulate parsing failure for any path containing the package name.
+ whenever(rule.mocks().packageParser.parsePackage(
+ argThat { path: File -> path.path.contains("a.data.package") },
+ anyInt(),
+ anyBoolean()))
+ .thenThrow(PackageParser.PackageParserException(
+ PackageManager.INSTALL_FAILED_INVALID_APK, "Oh no!"))
+ val pm = createPackageManagerService()
+ verify(rule.mocks().settings, Mockito.never()).insertPackageSettingLPw(
+ argThat { setting: PackageSetting -> setting.name == "a.data.package" },
+ argThat { pkg: AndroidPackage -> pkg.packageName == "a.data.package" })
+ assertThat(pm.mPackages, not(hasKey("a.data.package")))
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun expectingBetter_updateStillBetter() {
+ // Debug.waitForDebugger()
+ val systemAppPackageName = "com.android.test.updated.system.app"
+ val systemAppSigningDetails = rule.system().createRandomSigningDetails()
+ val systemVersionParent = rule.system()
+ .getPartitionFromFlag(PackageManagerService.SCAN_AS_PRODUCT).privAppFolder
+
+ // system app v1 is disabled
+ whenever(rule.mocks().settings.isDisabledSystemPackageLPr(systemAppPackageName)) {
+ true
+ }
+ whenever(rule.mocks().settings.getDisabledSystemPkgLPr(systemAppPackageName)) {
+ rule.system().createBasicSettingBuilder(
+ File(systemVersionParent, systemAppPackageName),
+ systemAppPackageName, 1, systemAppSigningDetails).build()
+ }
+
+ // system app v3 is on data/app
+ rule.system().stageScanExistingPackage(
+ systemAppPackageName,
+ 3,
+ rule.system().dataAppDirectory,
+ withPackage = { it.apply { signingDetails = systemAppSigningDetails } },
+ withExistingSetting = { it.setPkgFlags(FLAG_SYSTEM) })
+
+ // system app v2 is scanned from system
+ rule.system().stageScanNewPackage(systemAppPackageName, 2, systemVersionParent,
+ withPackage = { it.apply { signingDetails = systemAppSigningDetails } },
+ withSetting = { it.setPkgFlags(FLAG_SYSTEM) })
+
+ val pm = createPackageManagerService()
+
+ assertThat("system package should exist after boot",
+ pm.mPackages[systemAppPackageName], notNullValue())
+ assertThat("system package should remain at version on data/app",
+ pm.mPackages[systemAppPackageName]!!.longVersionCode, equalTo(3))
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..72ae77e
--- /dev/null
+++ b/services/tests/mockingservicestests/utils-mockito/com/android/server/extendedtestutils/ExtendedMockitoUtils.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 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.extendedtestutils
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.dx.mockito.inline.extended.MockedMethod
+import com.android.dx.mockito.inline.extended.StaticCapableStubber
+import org.mockito.stubbing.Answer
+
+fun <T> StaticCapableStubber.wheneverStatic(methodCall: MockedMethod<T>) {
+ this.`when`(methodCall)
+}
+
+fun <T> wheneverStatic(mockedMethod: MockedMethod<T>) = object : CustomStaticStubber<T> {
+ override fun thenAnswer(answer: Answer<T>) {
+ ExtendedMockito.doAnswer(answer).wheneverStatic(mockedMethod)
+ }
+
+ override fun thenReturn(value: T) {
+ ExtendedMockito.doReturn(value).wheneverStatic(mockedMethod)
+ }
+}
+
+interface CustomStaticStubber<T> {
+ fun thenAnswer(answer: Answer<T>)
+ fun thenReturn(value: T)
+}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 343b156..89770fe 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -111,6 +111,16 @@
}
java_library {
+ name: "servicestests-core-utils",
+ srcs: [
+ "src/com/android/server/pm/PackageSettingBuilder.java",
+ ],
+ static_libs: [
+ "services.core",
+ ],
+}
+
+java_library {
name: "servicestests-utils",
srcs: [
"utils/**/*.java",
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index f8e92ad..84551c5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -22,6 +22,7 @@
import android.util.SparseArray;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
import java.io.File;
import java.util.Map;
@@ -38,14 +39,14 @@
private int mPkgFlags;
private int mPrivateFlags;
private int mSharedUserId;
+ private String mVolumeUuid;
+ private int mAppId;
+ private SparseArray<PackageUserState> mUserStates = new SparseArray<>();
+ private AndroidPackage mPkg;
+ private InstallSource mInstallSource;
private String[] mUsesStaticLibraries;
private long[] mUsesStaticLibrariesVersions;
private Map<String, ArraySet<String>> mMimeGroups;
- private String mVolumeUuid;
- private SparseArray<PackageUserState> mUserStates = new SparseArray<>();
- private AndroidPackage mPkg;
- private int mAppId;
- private InstallSource mInstallSource;
private PackageParser.SigningDetails mSigningDetails;
public PackageSettingBuilder setPackage(AndroidPackage pkg) {
@@ -143,6 +144,14 @@
return this;
}
+ public PackageSettingBuilder setInstallState(int userId, boolean installed) {
+ if (mUserStates.indexOfKey(userId) < 0) {
+ mUserStates.put(userId, new PackageUserState());
+ }
+ mUserStates.get(userId).installed = installed;
+ return this;
+ }
+
public PackageSettingBuilder setInstallSource(InstallSource installSource) {
mInstallSource = installSource;
return this;
@@ -173,6 +182,5 @@
packageSetting.setUserState(mUserStates.keyAt(i), mUserStates.valueAt(i));
}
return packageSetting;
-
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index fcbb5ed..d8c3979 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -101,7 +101,8 @@
@Before
public void setupDefaultAbiBehavior() throws Exception {
when(mMockPackageAbiHelper.derivePackageAbi(
- any(AndroidPackage.class), anyBoolean(), nullable(String.class)))
+ any(AndroidPackage.class), anyBoolean(), nullable(String.class),
+ any(File.class)))
.thenReturn(new Pair<>(
new PackageAbiHelper.Abis("derivedPrimary", "derivedSecondary"),
new PackageAbiHelper.NativeLibraryPaths(
diff --git a/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt b/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt
index 59cbd1c..4c82818 100644
--- a/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt
+++ b/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt
@@ -17,6 +17,7 @@
package com.android.server.testutils
import org.mockito.Answers
+import org.mockito.ArgumentMatchers
import org.mockito.Mockito
import org.mockito.invocation.InvocationOnMock
import org.mockito.stubbing.Answer
@@ -53,7 +54,7 @@
fun <T> spy(value: T, block: T.() -> Unit = {}) = Mockito.spy(value).apply(block)
-fun <Type> Stubber.whenever(mock: Type) = Mockito.`when`(mock)
+fun <Type> Stubber.whenever(mock: Type) = this.`when`(mock)
fun <Type : Any?> whenever(mock: Type) = Mockito.`when`(mock)
@Suppress("UNCHECKED_CAST")
@@ -81,3 +82,5 @@
inline fun <reified T> mockThrowOnUnmocked(block: T.() -> Unit = {}) =
spyThrowOnUnmocked<T>(null, block)
+
+inline fun <reified T : Any> nullable() = ArgumentMatchers.nullable(T::class.java)
\ No newline at end of file