Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9116762 authored by Christopher Tate's avatar Christopher Tate
Browse files

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
parent 75e38f4e
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.content.pm;

import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Printer;

/**
@@ -160,7 +161,12 @@ public class ComponentInfo extends PackageItemInfo {
    
    public void writeToParcel(Parcel dest, int parcelableFlags) {
        super.writeToParcel(dest, parcelableFlags);
        if ((parcelableFlags & Parcelable.PARCELABLE_ELIDE_DUPLICATES) != 0) {
            dest.writeInt(0);
        } else {
            dest.writeInt(1);
            applicationInfo.writeToParcel(dest, parcelableFlags);
        }
        dest.writeString(processName);
        dest.writeInt(descriptionRes);
        dest.writeInt(enabled ? 1 : 0);
@@ -169,7 +175,10 @@ public class ComponentInfo extends PackageItemInfo {
    
    protected ComponentInfo(Parcel source) {
        super(source);
        final boolean hasApplicationInfo = (source.readInt() != 0);
        if (hasApplicationInfo) {
            applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
        }
        processName = source.readString();
        descriptionRes = source.readInt();
        enabled = (source.readInt() != 0);
+21 −4
Original line number Diff line number Diff line
@@ -305,10 +305,10 @@ public class PackageInfo implements Parcelable {
        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 @@ public class PackageInfo implements Parcelable {
        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;
            }
        }
    }
}
+11 −1
Original line number Diff line number Diff line
@@ -63,6 +63,16 @@ public interface Parcelable {
     */
    public static final int PARCELABLE_WRITE_RETURN_VALUE = 0x0001;

    /**
     * Flag for use with {@link #writeToParcel}: a parent object will take
     * care of managing duplicate state/data that is nominally replicated
     * across its inner data members.  This flag instructs the inner data
     * types to omit that data during marshaling.  Exact behavior may vary
     * on a case by case basis.
     * @hide
     */
    public static final int PARCELABLE_ELIDE_DUPLICATES = 0x0002;

    /**
     * Bit masks for use with {@link #describeContents}: each bit represents a
     * kind of object considered to have potential special significance when