Save overlay paths as user state
Instead of maintaining a separate structure just for overlay
paths, store them as user state in the package setting. Also
centralize updating the overlay paths to avoid issues with
inconsistent updates.
Fixes: 36561125
Test: Manual
Change-Id: Iac1c987e8650074dbc564e332d5da1950fad6ac5
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 9b0bab4..fdb0f2ba 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6852,7 +6852,7 @@
ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
}
ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
- ai.resourceDirs = state.resourceDirs;
+ ai.resourceDirs = state.overlayPaths;
}
public static ApplicationInfo generateApplicationInfo(Package p, int flags,
@@ -7000,6 +7000,7 @@
return null;
}
if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
+ updateApplicationInfo(a.info.applicationInfo, flags, state);
return a.info;
}
// Make shallow copies so we can store the metadata safely
@@ -7088,6 +7089,7 @@
return null;
}
if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
+ updateApplicationInfo(s.info.applicationInfo, flags, state);
return s.info;
}
// Make shallow copies so we can store the metadata safely
@@ -7183,6 +7185,7 @@
if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
&& ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
|| p.info.uriPermissionPatterns == null)) {
+ updateApplicationInfo(p.info.applicationInfo, flags, state);
return p.info;
}
// Make shallow copies so we can store the metadata safely
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 4e53914..470336c 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -55,7 +55,7 @@
public ArraySet<String> disabledComponents;
public ArraySet<String> enabledComponents;
- public String[] resourceDirs;
+ public String[] overlayPaths;
public PackageUserState() {
installed = true;
@@ -83,8 +83,8 @@
installReason = o.installReason;
disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
- resourceDirs =
- o.resourceDirs == null ? null : Arrays.copyOf(o.resourceDirs, o.resourceDirs.length);
+ overlayPaths =
+ o.overlayPaths == null ? null : Arrays.copyOf(o.overlayPaths, o.overlayPaths.length);
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e62b107..3bbbde0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -675,13 +675,6 @@
@GuardedBy("mPackages")
final SparseIntArray mIsolatedOwners = new SparseIntArray();
- // List of APK paths to load for each user and package. This data is never
- // persisted by the package manager. Instead, the overlay manager will
- // ensure the data is up-to-date in runtime.
- @GuardedBy("mPackages")
- final SparseArray<ArrayMap<String, ArrayList<String>>> mEnabledOverlayPaths =
- new SparseArray<ArrayMap<String, ArrayList<String>>>();
-
/**
* Tracks new system packages [received in an OTA] that we expect to
* find updated user-installed versions. Keys are package name, values
@@ -3583,8 +3576,6 @@
return null;
}
- rebaseEnabledOverlays(packageInfo.applicationInfo, userId);
-
packageInfo.packageName = packageInfo.applicationInfo.packageName =
resolveExternalPackageNameLPr(p);
@@ -4096,7 +4087,6 @@
ApplicationInfo ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
ps.readUserState(userId), userId);
if (ai != null) {
- rebaseEnabledOverlays(ai, userId);
ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
}
return ai;
@@ -4145,7 +4135,6 @@
ApplicationInfo ai = PackageParser.generateApplicationInfo(
p, flags, ps.readUserState(userId), userId);
if (ai != null) {
- rebaseEnabledOverlays(ai, userId);
ai.packageName = resolveExternalPackageNameLPr(p);
}
return ai;
@@ -4162,26 +4151,6 @@
return null;
}
- private void rebaseEnabledOverlays(@NonNull ApplicationInfo ai, int userId) {
- List<String> paths = new ArrayList<>();
- ArrayMap<String, ArrayList<String>> userSpecificOverlays =
- mEnabledOverlayPaths.get(userId);
- if (userSpecificOverlays != null) {
- if (!"android".equals(ai.packageName)) {
- ArrayList<String> frameworkOverlays = userSpecificOverlays.get("android");
- if (frameworkOverlays != null) {
- paths.addAll(frameworkOverlays);
- }
- }
-
- ArrayList<String> appOverlays = userSpecificOverlays.get(ai.packageName);
- if (appOverlays != null) {
- paths.addAll(appOverlays);
- }
- }
- ai.resourceDirs = paths.size() > 0 ? paths.toArray(new String[paths.size()]) : null;
- }
-
private String normalizePackageNameLPr(String packageName) {
String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
return normalizedPackageName != null ? normalizedPackageName : packageName;
@@ -4566,24 +4535,6 @@
return updateFlagsForComponent(flags, userId, intent /*cookie*/);
}
- private ActivityInfo generateActivityInfo(ActivityInfo ai, int flags, PackageUserState state,
- int userId) {
- ActivityInfo ret = PackageParser.generateActivityInfo(ai, flags, state, userId);
- if (ret != null) {
- rebaseEnabledOverlays(ret.applicationInfo, userId);
- }
- return ret;
- }
-
- private ActivityInfo generateActivityInfo(PackageParser.Activity a, int flags,
- PackageUserState state, int userId) {
- ActivityInfo ai = PackageParser.generateActivityInfo(a, flags, state, userId);
- if (ai != null) {
- rebaseEnabledOverlays(ai.applicationInfo, userId);
- }
- return ai;
- }
-
@Override
public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
return getActivityInfoInternal(component, flags, Binder.getCallingUid(), userId);
@@ -4611,11 +4562,12 @@
if (filterAppAccessLPr(ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) {
return null;
}
- return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
+ return PackageParser.generateActivityInfo(
+ a, flags, ps.readUserState(userId), userId);
}
if (mResolveComponentName.equals(component)) {
- return generateActivityInfo(mResolveActivity, flags, new PackageUserState(),
- userId);
+ return PackageParser.generateActivityInfo(
+ mResolveActivity, flags, new PackageUserState(), userId);
}
}
return null;
@@ -4669,7 +4621,8 @@
if (filterAppAccessLPr(ps, callingUid, component, TYPE_RECEIVER, userId)) {
return null;
}
- return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
+ return PackageParser.generateActivityInfo(
+ a, flags, ps.readUserState(userId), userId);
}
}
return null;
@@ -4805,12 +4758,8 @@
if (filterAppAccessLPr(ps, callingUid, component, TYPE_SERVICE, userId)) {
return null;
}
- ServiceInfo si = PackageParser.generateServiceInfo(s, flags,
- ps.readUserState(userId), userId);
- if (si != null) {
- rebaseEnabledOverlays(si.applicationInfo, userId);
- }
- return si;
+ return PackageParser.generateServiceInfo(
+ s, flags, ps.readUserState(userId), userId);
}
}
return null;
@@ -4833,12 +4782,8 @@
if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
return null;
}
- ProviderInfo pi = PackageParser.generateProviderInfo(p, flags,
- ps.readUserState(userId), userId);
- if (pi != null) {
- rebaseEnabledOverlays(pi.applicationInfo, userId);
- }
- return pi;
+ return PackageParser.generateProviderInfo(
+ p, flags, ps.readUserState(userId), userId);
}
}
return null;
@@ -8264,7 +8209,6 @@
ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
ps.readUserState(userId), userId);
if (ai != null) {
- rebaseEnabledOverlays(ai, userId);
ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
}
} else {
@@ -8291,7 +8235,6 @@
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
- rebaseEnabledOverlays(ai, userId);
ai.packageName = resolveExternalPackageNameLPr(p);
list.add(ai);
}
@@ -8445,7 +8388,6 @@
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
ps.readUserState(userId), userId);
if (ai != null) {
- rebaseEnabledOverlays(ai, userId);
finalList.add(ai);
}
}
@@ -13308,7 +13250,8 @@
return null;
}
final PackageUserState userState = ps.readUserState(userId);
- ActivityInfo ai = generateActivityInfo(activity, mFlags, userState, userId);
+ ActivityInfo ai =
+ PackageParser.generateActivityInfo(activity, mFlags, userState, userId);
if (ai == null) {
return null;
}
@@ -22277,11 +22220,6 @@
dumpCompilerStatsLPr(pw, packageName);
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_ENABLED_OVERLAYS)) {
- if (dumpState.onTitlePrinted()) pw.println();
- dumpEnabledOverlaysLPr(pw);
- }
-
if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
if (dumpState.onTitlePrinted()) pw.println();
mSettings.dumpReadMessagesLPr(pw, dumpState);
@@ -22478,23 +22416,6 @@
}
}
- private void dumpEnabledOverlaysLPr(PrintWriter pw) {
- pw.println("Enabled overlay paths:");
- final int N = mEnabledOverlayPaths.size();
- for (int i = 0; i < N; i++) {
- final int userId = mEnabledOverlayPaths.keyAt(i);
- pw.println(String.format(" User %d:", userId));
- final ArrayMap<String, ArrayList<String>> userSpecificOverlays =
- mEnabledOverlayPaths.valueAt(i);
- final int M = userSpecificOverlays.size();
- for (int j = 0; j < M; j++) {
- final String targetPackageName = userSpecificOverlays.keyAt(j);
- final ArrayList<String> overlayPackagePaths = userSpecificOverlays.valueAt(j);
- pw.println(String.format(" %s: %s", targetPackageName, overlayPackagePaths));
- }
- }
- }
-
private String dumpDomainString(String packageName) {
List<IntentFilterVerificationInfo> iviList = getIntentFilterVerifications(packageName)
.getList();
@@ -24669,11 +24590,10 @@
Slog.e(TAG, "failed to find package " + targetPackageName);
return false;
}
-
- ArrayList<String> paths = null;
- if (overlayPackageNames != null) {
+ ArrayList<String> overlayPaths = null;
+ if (overlayPackageNames != null && overlayPackageNames.size() > 0) {
final int N = overlayPackageNames.size();
- paths = new ArrayList<>(N);
+ overlayPaths = new ArrayList<>(N);
for (int i = 0; i < N; i++) {
final String packageName = overlayPackageNames.get(i);
final PackageParser.Package pkg = mPackages.get(packageName);
@@ -24681,22 +24601,17 @@
Slog.e(TAG, "failed to find package " + packageName);
return false;
}
- paths.add(pkg.baseCodePath);
+ overlayPaths.add(pkg.baseCodePath);
}
}
- ArrayMap<String, ArrayList<String>> userSpecificOverlays =
- mEnabledOverlayPaths.get(userId);
- if (userSpecificOverlays == null) {
- userSpecificOverlays = new ArrayMap<>();
- mEnabledOverlayPaths.put(userId, userSpecificOverlays);
+ final PackageSetting ps = mSettings.mPackages.get(targetPackageName);
+ String[] frameworkOverlayPaths = null;
+ if (!"android".equals(targetPackageName)) {
+ frameworkOverlayPaths =
+ mSettings.mPackages.get("android").getOverlayPaths(userId);
}
-
- if (paths != null && paths.size() > 0) {
- userSpecificOverlays.put(targetPackageName, paths);
- } else {
- userSpecificOverlays.remove(targetPackageName);
- }
+ ps.setOverlayPaths(overlayPaths, frameworkOverlayPaths, userId);
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 14f65eb..d17267f 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -31,6 +31,7 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
+import com.google.android.collect.Lists;
import java.io.File;
import java.util.ArrayList;
@@ -329,6 +330,27 @@
modifyUserState(userId).installReason = installReason;
}
+ void setOverlayPaths(List<String> overlayPaths, String[] frameworkOverlayPaths, int userId) {
+ if (overlayPaths == null && frameworkOverlayPaths == null) {
+ modifyUserState(userId).overlayPaths = null;
+ return;
+ }
+ final List<String> paths;
+ if (frameworkOverlayPaths == null) {
+ paths = overlayPaths;
+ } else {
+ paths = Lists.newArrayList(frameworkOverlayPaths);
+ if (overlayPaths != null) {
+ paths.addAll(overlayPaths);
+ }
+ }
+ modifyUserState(userId).overlayPaths = paths.toArray(new String[paths.size()]);
+ }
+
+ String[] getOverlayPaths(int userId) {
+ return readUserState(userId).overlayPaths;
+ }
+
/** Only use for testing. Do NOT use in production code. */
@VisibleForTesting
SparseArray<PackageUserState> getUserState() {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 24cbdbf..b006c2d 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4858,6 +4858,15 @@
pw.print(ps.getEnabled(user.id));
pw.print(" instant=");
pw.println(ps.getInstantApp(user.id));
+
+ String[] overlayPaths = ps.getOverlayPaths(user.id);
+ if (overlayPaths != null && overlayPaths.length > 0) {
+ pw.println("Overlay paths:");
+ for (String path : overlayPaths) {
+ pw.println(path);
+ }
+ }
+
String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
if (lastDisabledAppCaller != null) {
pw.print(prefix); pw.print(" lastDisabledCaller: ");