Avoid parceling redundant ApplicationInfo objects within PackageInfo
Two benefits:
1) marshaling one flattened ApplicationInfo as part of a PackageInfo parcel
rather than one per included ComponentInfo; and
2) producing one ApplicationInfo at unmarshaling time and sharing the
reference to it among all included ComponentInfo instances, rather
than the previous implementation that generated a separate
ApplicationInfo instance for each ComponentInfo.
In some cases there can be many hundreds of ComponentInfo objects embedded
in a single PackageInfo, so coalescing duplicates is a significant win
for both payload size and object pressure.
Bug 19519502
Bug 20453802
Change-Id: Ib888810dad4471084fab9ead1ebb5e0b932905f1
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 9e6c6b5..d40bab5 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -305,10 +305,10 @@
dest.writeLong(firstInstallTime);
dest.writeLong(lastUpdateTime);
dest.writeIntArray(gids);
- dest.writeTypedArray(activities, parcelableFlags);
- dest.writeTypedArray(receivers, parcelableFlags);
- dest.writeTypedArray(services, parcelableFlags);
- dest.writeTypedArray(providers, parcelableFlags);
+ dest.writeTypedArray(activities, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
+ dest.writeTypedArray(receivers, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
+ dest.writeTypedArray(services, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
+ dest.writeTypedArray(providers, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
dest.writeTypedArray(instrumentation, parcelableFlags);
dest.writeTypedArray(permissions, parcelableFlags);
dest.writeStringArray(requestedPermissions);
@@ -372,5 +372,22 @@
restrictedAccountType = source.readString();
requiredAccountType = source.readString();
overlayTarget = source.readString();
+
+ // The component lists were flattened with the redundant ApplicationInfo
+ // instances omitted. Distribute the canonical one here as appropriate.
+ if (applicationInfo != null) {
+ propagateApplicationInfo(applicationInfo, activities);
+ propagateApplicationInfo(applicationInfo, receivers);
+ propagateApplicationInfo(applicationInfo, services);
+ propagateApplicationInfo(applicationInfo, providers);
+ }
+ }
+
+ private void propagateApplicationInfo(ApplicationInfo appInfo, ComponentInfo[] components) {
+ if (components != null) {
+ for (ComponentInfo ci : components) {
+ ci.applicationInfo = appInfo;
+ }
+ }
}
}