diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java index e86a42c284b6d..f497f114c05fa 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.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 providerList = null; - - // Map from a package name to the corresponding app info. - ArrayMap 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 outNames, List 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; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4eac79cff8b55..f714af03336f7 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 @@ 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; 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 f5ce0804236d1..4ab1f39663d0b 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.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 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 f99791a28f464..d561b9c1ffdd8 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 @@ 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;