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

Commit bc939bbe authored by Makoto Onuki's avatar Makoto Onuki Committed by android-build-merger
Browse files

Merge "Reduce duplicate strings due to the package cache." into oc-mr1-dev

am: bb77e6c6

Change-Id: Ia47cf7d0832ef6ca99b4f4991c2e2624bdf03742
parents 8ca301dc bb77e6c6
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageParserCacheHelper.ReadHelper;
import android.content.pm.PackageParserCacheHelper.WriteHelper;
import android.content.pm.split.DefaultSplitAssetLoader;
import android.content.pm.split.SplitAssetDependencyLoader;
import android.content.pm.split.SplitAssetLoader;
@@ -1024,11 +1026,17 @@ public class PackageParser {

    @VisibleForTesting
    protected Package fromCacheEntry(byte[] bytes) throws IOException {
        Parcel p = Parcel.obtain();
        final ReadHelper helper = new ReadHelper();

        final Parcel p = Parcel.obtain();
        p.setReadWriteHelper(helper);

        p.unmarshall(bytes, 0, bytes.length);
        p.setDataPosition(0);

        helper.start(p);
        PackageParser.Package pkg = new PackageParser.Package(p);

        p.recycle();

        return pkg;
@@ -1036,8 +1044,15 @@ public class PackageParser {

    @VisibleForTesting
    protected byte[] toCacheEntry(Package pkg) throws IOException {
        Parcel p = Parcel.obtain();
        final WriteHelper helper = new WriteHelper();

        final Parcel p = Parcel.obtain();
        p.setReadWriteHelper(helper);

        pkg.writeToParcel(p, 0 /* flags */);

        helper.finish(p);

        byte[] serialized = p.marshall();
        p.recycle();

+114 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.content.pm;

import android.os.Parcel;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Helper classes to read from and write to Parcel with pooled strings.
 *
 * @hide
 */
public class PackageParserCacheHelper {
    private PackageParserCacheHelper() {
    }

    /**
     * Parcel read helper with a string pool.
     */
    public static class ReadHelper extends Parcel.ReadWriteHelper {
        private final ArrayList<String> mStrings = new ArrayList<>();

        public ReadHelper() {
        }

        /**
         * Prepare a parcel.
         */
        public void start(Parcel p) {
            mStrings.clear();

            final int poolPosition = p.readInt();
            final int startPosition = p.dataPosition();

            // The pool is at the end of the parcel.
            p.setDataPosition(poolPosition);
            p.readStringList(mStrings);

            // Then move back.
            p.setDataPosition(startPosition);
        }

        /**
         * Read an string index from a parcel, and returns the corresponding string from the pool.
         */
        @Override
        public String readString(Parcel p) {
            return mStrings.get(p.readInt());
        }
    }

    /**
     * Parcel write helper with a string pool.
     */
    public static class WriteHelper extends Parcel.ReadWriteHelper {
        private final ArrayList<String> mStrings = new ArrayList<>();

        private final HashMap<String, Integer> mIndexes = new HashMap<>();

        public WriteHelper() {
        }

        /**
         * Instead of writing a string directly to a parcel, this method adds it to the pool,
         * and write the index in the pool to the parcel.
         */
        @Override
        public void writeString(Parcel p, String s) {
            final Integer cur = mIndexes.get(s);
            if (cur != null) {
                // String already in the pool. Just write the index.
                p.writeInt(cur); // Already in the pool.
            } else {
                // Note in the pool. Add to the pool, and write the index.
                final int index = mStrings.size();
                mIndexes.put(s, index);
                mStrings.add(s);

                p.writeInt(index);
            }
        }

        /**
         * Closes a parcel by appending the string pool at the end and updating the pool offset,
         * which it assumes is at the first byte.
         */
        public void finish(Parcel p) {
            final int poolPosition = p.readInt();
            p.writeStringList(mStrings);

            p.setDataPosition(0);
            p.writeInt(poolPosition);

            // Move back to the end.
            p.setDataPosition(p.dataSize());
        }
    }
}
+64 −2
Original line number Diff line number Diff line
@@ -291,7 +291,7 @@ public final class Parcel {
    private static native void nativeWriteFloat(long nativePtr, float val);
    @FastNative
    private static native void nativeWriteDouble(long nativePtr, double val);
    private static native void nativeWriteString(long nativePtr, String val);
    static native void nativeWriteString(long nativePtr, String val);
    private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
    private static native long nativeWriteFileDescriptor(long nativePtr, FileDescriptor val);

@@ -306,7 +306,7 @@ public final class Parcel {
    private static native float nativeReadFloat(long nativePtr);
    @CriticalNative
    private static native double nativeReadDouble(long nativePtr);
    private static native String nativeReadString(long nativePtr);
    static native String nativeReadString(long nativePtr);
    private static native IBinder nativeReadStrongBinder(long nativePtr);
    private static native FileDescriptor nativeReadFileDescriptor(long nativePtr);

@@ -338,6 +338,33 @@ public final class Parcel {
        }
    };

    /**
     * @hide
     */
    public static class ReadWriteHelper {
        public static final ReadWriteHelper DEFAULT = new ReadWriteHelper();

        /**
         * Called when writing a string to a parcel. Subclasses wanting to write a string
         * must use {@link #writeStringNoHelper(String)} to avoid
         * infinity recursive calls.
         */
        public void writeString(Parcel p, String s) {
            nativeWriteString(p.mNativePtr, s);
        }

        /**
         * Called when reading a string to a parcel. Subclasses wanting to read a string
         * must use {@link #readStringNoHelper()} to avoid
         * infinity recursive calls.
         */
        public String readString(Parcel p) {
            return nativeReadString(p.mNativePtr);
        }
    }

    private ReadWriteHelper mReadWriteHelper = ReadWriteHelper.DEFAULT;

    /**
     * Retrieve a new Parcel object from the pool.
     */
@@ -352,6 +379,7 @@ public final class Parcel {
                    if (DEBUG_RECYCLE) {
                        p.mStack = new RuntimeException();
                    }
                    p.mReadWriteHelper = ReadWriteHelper.DEFAULT;
                    return p;
                }
            }
@@ -385,6 +413,16 @@ public final class Parcel {
        }
    }

    /**
     * Set a {@link ReadWriteHelper}, which can be used to avoid having duplicate strings, for
     * example.
     *
     * @hide
     */
    public void setReadWriteHelper(ReadWriteHelper helper) {
        mReadWriteHelper = helper != null ? helper : ReadWriteHelper.DEFAULT;
    }

    /** @hide */
    public static native long getGlobalAllocSize();

@@ -625,6 +663,17 @@ public final class Parcel {
     * growing dataCapacity() if needed.
     */
    public final void writeString(String val) {
        mReadWriteHelper.writeString(this, val);
    }

    /**
     * Write a string without going though a {@link ReadWriteHelper}.  Subclasses of
     * {@link ReadWriteHelper} must use this method instead of {@link #writeString} to avoid
     * infinity recursive calls.
     *
     * @hide
     */
    public void writeStringNoHelper(String val) {
        nativeWriteString(mNativePtr, val);
    }

@@ -1996,6 +2045,17 @@ public final class Parcel {
     * Read a string value from the parcel at the current dataPosition().
     */
    public final String readString() {
        return mReadWriteHelper.readString(this);
    }

    /**
     * Read a string without going though a {@link ReadWriteHelper}.  Subclasses of
     * {@link ReadWriteHelper} must use this method instead of {@link #readString} to avoid
     * infinity recursive calls.
     *
     * @hide
     */
    public String readStringNoHelper() {
        return nativeReadString(mNativePtr);
    }

@@ -2996,6 +3056,7 @@ public final class Parcel {
        if (mOwnsNativeParcelObject) {
            updateNativeSize(nativeFreeBuffer(mNativePtr));
        }
        mReadWriteHelper = ReadWriteHelper.DEFAULT;
    }

    private void destroy() {
@@ -3006,6 +3067,7 @@ public final class Parcel {
            }
            mNativePtr = 0;
        }
        mReadWriteHelper = null;
    }

    @Override