Make sure always reuse ApplicationInfo when generating ProviderInfo
Bug: 148588589
Test: atest CtsContentTestCases (modulo preexisting failures)
Change-Id: If81f3b343fb018ba52127d038d02e62ca516c18f
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index e86a42c..f497f11 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -57,6 +57,7 @@
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 @@
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 @@
&& (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();
}
- // At this point, appInfo != null.
+ final PackageUserState state = ps.readUserState(userId);
+ final ApplicationInfo appInfo =
+ appInfoGenerator.generate(pkg, flags, state, userId, ps);
+ if (appInfo == null) {
+ continue;
+ }
final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
pkg, p, flags, state, appInfo, userId, ps);
@@ -355,14 +343,20 @@
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 @@
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 @@
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;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index eb742e9..d84e920 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5459,7 +5459,13 @@
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;
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index f5ce080..4ab1f396 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -48,7 +48,7 @@
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 java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
@@ -72,6 +73,7 @@
* @hide
**/
public class PackageInfoUtils {
+ private static final String TAG = PackageParser2.TAG;
/**
* @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
@@ -312,35 +314,22 @@
/**
* @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 @@
| 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;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/parsing/PackageParser2.java b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
index f99791a..d561b9c 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageParser2.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
@@ -42,7 +42,7 @@
*/
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;