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

Commit bb77e6c6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents 0cd8a31c e86a29c6
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