Make sure always reuse ApplicationInfo when generating ProviderInfo
Bug: 148588589 Test: atest CtsContentTestCases (modulo preexisting failures) Change-Id: If81f3b343fb018ba52127d038d02e62ca516c18f
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user