Make sure always reuse ApplicationInfo when generating ProviderInfo

Bug: 148588589
Test: atest CtsContentTestCases (modulo preexisting failures)
Change-Id: If81f3b343fb018ba52127d038d02e62ca516c18f
This commit is contained in:
Makoto Onuki
2020-02-21 10:28:08 -08:00
parent 9577cd78ff
commit db91e18075
4 changed files with 79 additions and 51 deletions

View File

@@ -57,6 +57,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.server.IntentResolver;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.PackageInfoUtils.CachedApplicationInfoGenerator;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.io.PrintWriter;
@@ -273,9 +274,7 @@ public class ComponentResolver {
return null;
}
List<ProviderInfo> providerList = null;
// Map from a package name to the corresponding app info.
ArrayMap<String, ApplicationInfo> appInfos = null;
CachedApplicationInfoGenerator appInfoGenerator = null;
synchronized (mLock) {
for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) {
final ParsedProvider p = mProviders.mProviders.valueAt(i);
@@ -304,26 +303,15 @@ public class ComponentResolver {
&& (p.getMetaData() == null || !p.getMetaData().containsKey(metaDataKey))) {
continue;
}
// Make sure we have AppInfo for this provider.
final PackageUserState state = ps.readUserState(userId);
ApplicationInfo appInfo =
(appInfos == null) ? null : appInfos.get(pkg.getPackageName());
if (appInfo == null) {
appInfo = PackageInfoUtils.generateApplicationInfo(
pkg, flags, state, userId, ps);
if (appInfo == null) {
// In this case, we should avoid calling generateApplicationInfo() for
// the same package in subsequent iterations, but appInfo shouldn't be null
// here, so we don't bother.
continue;
}
if (appInfos == null) {
appInfos = new ArrayMap<>(4);
}
appInfos.put(pkg.getPackageName(), appInfo);
if (appInfoGenerator == null) {
appInfoGenerator = new CachedApplicationInfoGenerator();
}
final PackageUserState state = ps.readUserState(userId);
final ApplicationInfo appInfo =
appInfoGenerator.generate(pkg, flags, state, userId, ps);
if (appInfo == null) {
continue;
}
// At this point, appInfo != null.
final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
pkg, p, flags, state, appInfo, userId, ps);
@@ -355,14 +343,20 @@ public class ComponentResolver {
if (pkg == null) {
return null;
}
return PackageInfoUtils.generateProviderInfo(pkg, p, flags,
ps.readUserState(userId), userId, ps);
final PackageUserState state = ps.readUserState(userId);
ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
pkg, flags, state, userId, ps);
if (appInfo == null) {
return null;
}
return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, appInfo, userId, ps);
}
}
void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo, boolean safeMode,
int userId) {
synchronized (mLock) {
CachedApplicationInfoGenerator appInfoGenerator = null;
for (int i = mProvidersByAuthority.size() - 1; i >= 0; --i) {
final ParsedProvider p = mProvidersByAuthority.valueAt(i);
if (!p.isSyncable()) {
@@ -384,9 +378,18 @@ public class ComponentResolver {
if (safeMode && !pkg.isSystem()) {
continue;
}
final ProviderInfo info =
PackageInfoUtils.generateProviderInfo(pkg, p, 0,
ps.readUserState(userId), userId, ps);
if (appInfoGenerator == null) {
appInfoGenerator = new CachedApplicationInfoGenerator();
}
final PackageUserState state = ps.readUserState(userId);
final ApplicationInfo appInfo =
appInfoGenerator.generate(pkg, 0, state, userId, ps);
if (appInfo == null) {
continue;
}
final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
pkg, p, 0, state, appInfo, userId, ps);
if (info == null) {
continue;
}
@@ -1731,8 +1734,13 @@ public class ComponentResolver {
if (userState.instantApp && ps.isUpdateAvailable()) {
return null;
}
final ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
pkg, mFlags, userState, userId, ps);
if (appInfo == null) {
return null;
}
ProviderInfo pi = PackageInfoUtils.generateProviderInfo(pkg, provider, mFlags,
userState, userId, ps);
userState, appInfo, userId, ps);
if (pi == null) {
return null;
}

View File

@@ -5459,7 +5459,13 @@ public class PackageManagerService extends IPackageManager.Stub
return null;
}
PackageUserState state = ps.readUserState(userId);
return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, userId, ps);
final ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
pkg, flags, state, userId, ps);
if (appInfo == null) {
return null;
}
return PackageInfoUtils.generateProviderInfo(
pkg, p, flags, state, appInfo, userId, ps);
}
}
return null;

View File

@@ -48,7 +48,7 @@ import android.content.pm.parsing.component.ParsedService;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import com.android.internal.util.ArrayUtils;
import com.android.server.pm.PackageSetting;
@@ -61,6 +61,7 @@ import libcore.util.EmptyArray;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -72,6 +73,7 @@ import java.util.Set;
* @hide
**/
public class PackageInfoUtils {
private static final String TAG = PackageParser2.TAG;
/**
* @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
@@ -310,37 +312,24 @@ public class PackageInfoUtils {
return info;
}
/**
* @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
*
* @deprecated use {@link #generateProviderInfo(
* AndroidPackage, ParsedProvider, int, PackageUserState, ApplicationInfo, int, PackageSetting)}
* instead and pass {@link ApplicationInfo} explicitly to avoid generating duplicate instances
* of it.
*/
@Nullable
@Deprecated
public static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
@PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId,
@Nullable PackageSetting pkgSetting) {
return generateProviderInfo(pkg, p, flags, state, null, userId, pkgSetting);
}
/**
* @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
*/
@Nullable
public static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
@PackageManager.ComponentInfoFlags int flags, PackageUserState state,
@Nullable ApplicationInfo applicationInfo, int userId,
@NonNull ApplicationInfo applicationInfo, int userId,
@Nullable PackageSetting pkgSetting) {
if (p == null) return null;
if (applicationInfo == null || !pkg.getPackageName().equals(applicationInfo.packageName)) {
Slog.wtf(TAG, "AppInfo's package name is different. Expected=" + pkg.getPackageName()
+ " actual=" + (applicationInfo == null ? "(null AppInfo)"
: applicationInfo.packageName));
applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
}
if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
return null;
}
if (applicationInfo == null) {
applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
}
ProviderInfo info = PackageInfoWithoutStateUtils.generateProviderInfo(pkg, p, flags, state,
applicationInfo, userId);
if (info == null) {
@@ -486,4 +475,29 @@ public class PackageInfoUtils {
| flag(pkg.isSignedWithPlatformKey(), ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY);
// @formatter:on
}
/**
* Wraps {@link PackageInfoUtils#generateApplicationInfo} with a cache.
*/
public static class CachedApplicationInfoGenerator {
// Map from a package name to the corresponding app info.
private ArrayMap<String, ApplicationInfo> mCache = new ArrayMap<>();
/**
* {@link PackageInfoUtils#generateApplicationInfo} with a cache.
*/
@Nullable
public ApplicationInfo generate(AndroidPackage pkg,
@PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
@Nullable PackageSetting pkgSetting) {
ApplicationInfo appInfo = mCache.get(pkg.getPackageName());
if (appInfo != null) {
return appInfo;
}
appInfo = PackageInfoUtils.generateApplicationInfo(
pkg, flags, state, userId, pkgSetting);
mCache.put(pkg.getPackageName(), appInfo);
return appInfo;
}
}
}

View File

@@ -42,7 +42,7 @@ import java.io.File;
*/
public class PackageParser2 {
private static final String TAG = "PackageParser2";
static final String TAG = "PackageParser2";
private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;