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

Unverified Commit e6a443ac authored by Marvin W.'s avatar Marvin W. 🐿️
Browse files

Move SafeParcel into play-services-basement

- Cache reflection-retrieved data to boost performance
- Foundation for compile-time generated Safe-Parcelable Creators (via annotation processor)
parent 03385435
Loading
Loading
Loading
Loading
+0 −10
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@

buildscript {
    ext.cronetVersion = '102.5005.125'
    ext.safeParcelVersion = '1.7.1'
    ext.wearableVersion = '0.1.1'

    ext.kotlinVersion = '1.7.10'
@@ -108,14 +107,5 @@ subprojects {
        mavenCentral()
        google()
    }
    afterEvaluate {
        // Temporary hack for Android Studio
        if (project.plugins.hasPlugin('com.android.base')) {
            dependencies {
                compileOnly "org.microg:safe-parcel:$safeParcelVersion"
                testCompileOnly "org.microg:safe-parcel:$safeParcelVersion"
            }
        }
    }
}
+0 −3
Original line number Diff line number Diff line
@@ -17,11 +17,8 @@
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: 'com.kezong.fat-aar'

dependencies {
    embed "org.microg:safe-parcel:$safeParcelVersion"

    // Dependencies from play-services-basement:18.1.0
    api "androidx.collection:collection:1.0.0"
    api "androidx.core:core:1.2.0"
+24 −0
Original line number Diff line number Diff line
/*
 * SPDX-FileCopyrightText: 2023 microG Project Team
 * SPDX-License-Identifier: Apache-2.0
 */

package com.google.android.gms.common.internal.safeparcel;

public abstract class AbstractSafeParcelable implements SafeParcelable {

    @SuppressWarnings("unchecked")
    public static <T extends AbstractSafeParcelable> SafeParcelableCreatorAndWriter<T> findCreator(java.lang.Class<T> tClass) {
        String creatorClassName = tClass.getName() + "$000Creator";
        try {
            return (SafeParcelableCreatorAndWriter<T>) java.lang.Class.forName(creatorClassName).newInstance();
        } catch (Exception e) {
            throw new RuntimeException("No Creator found for " + tClass.getName(), e);
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }
}
+328 −0
Original line number Diff line number Diff line
/*
 * SPDX-FileCopyrightText: 2015, microG Project Team
 * SPDX-License-Identifier: Apache-2.0
 */

package com.google.android.gms.common.internal.safeparcel;

import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;

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

@SuppressWarnings("MagicNumber")
public final class SafeParcelReader {

    private SafeParcelReader() {
    }

    @Deprecated
    public static int halfOf(int i) {
        return i & 0xFFFF;
    }

    public static int getFieldId(int header) {
        return header & 0xFFFF;
    }

    @Deprecated
    public static int readSingleInt(Parcel parcel) {
        return parcel.readInt();
    }

    public static int readHeader(Parcel parcel) {
        return parcel.readInt();
    }

    private static int readSize(Parcel parcel, int header) {
        if ((header & 0xFFFF0000) != 0xFFFF0000)
            return header >> 16 & 0xFFFF;
        return parcel.readInt();
    }

    private static void readExpectedSize(Parcel parcel, int header, int expectedSize) {
        int i = readSize(parcel, header);
        if (i != expectedSize)
            throw new ReadException("Expected size " + expectedSize + " got " + i + " (0x" + Integer.toHexString(i) + ")", parcel);
    }

    @Deprecated
    public static int readStart(Parcel parcel) {
        return readObjectHeader(parcel);
    }

    public static int readObjectHeader(Parcel parcel) {
        int header = readHeader(parcel);
        int size = readSize(parcel, header);
        int start = parcel.dataPosition();
        if (getFieldId(header) != SafeParcelable.SAFE_PARCEL_OBJECT_MAGIC)
            throw new ReadException("Expected object header. Got 0x" + Integer.toHexString(header), parcel);
        int end = start + size;
        if ((end < start) || (end > parcel.dataSize()))
            throw new ReadException("Size read is invalid start=" + start + " end=" + end, parcel);
        return end;
    }

    public static int readInt(Parcel parcel, int header) {
        readExpectedSize(parcel, header, 4);
        return parcel.readInt();
    }

    public static byte readByte(Parcel parcel, int header) {
        readExpectedSize(parcel, header, 4);
        return (byte) parcel.readInt();
    }

    public static short readShort(Parcel parcel, int header) {
        readExpectedSize(parcel, header, 4);
        return (short) parcel.readInt();
    }

    public static boolean readBool(Parcel parcel, int header) {
        readExpectedSize(parcel, header, 4);
        return parcel.readInt() != 0;
    }

    public static long readLong(Parcel parcel, int header) {
        readExpectedSize(parcel, header, 8);
        return parcel.readLong();
    }

    public static float readFloat(Parcel parcel, int header) {
        readExpectedSize(parcel, header, 4);
        return parcel.readFloat();
    }

    public static double readDouble(Parcel parcel, int header) {
        readExpectedSize(parcel, header, 8);
        return parcel.readDouble();
    }

    public static String readString(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        String string = parcel.readString();
        parcel.setDataPosition(start + size);
        return string;
    }

    public static IBinder readBinder(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        IBinder binder = parcel.readStrongBinder();
        parcel.setDataPosition(start + size);
        return binder;
    }

    public static <T extends Parcelable> T readParcelable(Parcel parcel, int header, Parcelable.Creator<T> creator) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        T t = creator.createFromParcel(parcel);
        parcel.setDataPosition(start + size);
        return t;
    }

    public static ArrayList readList(Parcel parcel, int header, ClassLoader classLoader) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        ArrayList list = parcel.readArrayList(classLoader);
        parcel.setDataPosition(start + size);
        return list;
    }

    public static HashMap readMap(Parcel parcel, int header, ClassLoader classLoader) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        HashMap map = parcel.readHashMap(classLoader);
        parcel.setDataPosition(start + size);
        return map;
    }

    public static <T extends Parcelable> ArrayList<T> readParcelableList(Parcel parcel, int header, Parcelable.Creator<T> creator) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        ArrayList<T> list = parcel.createTypedArrayList(creator);
        parcel.setDataPosition(start + size);
        return list;
    }

    public static ArrayList<String> readStringList(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        ArrayList<String> list = parcel.createStringArrayList();
        parcel.setDataPosition(start + size);
        return list;
    }

    public static ArrayList<Integer> readIntegerList(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        int length = parcel.readInt();
        ArrayList<Integer> list = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            list.add(parcel.readInt());
        }
        parcel.setDataPosition(start + size);
        return list;
    }

    public static ArrayList<Long> readLongList(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        int length = parcel.readInt();
        ArrayList<Long> list = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            list.add(parcel.readLong());
        }
        parcel.setDataPosition(start + size);
        return list;
    }

    public static ArrayList<Float> readFloatList(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        int length = parcel.readInt();
        ArrayList<Float> list = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            list.add(parcel.readFloat());
        }
        parcel.setDataPosition(start + size);
        return list;
    }

    public static ArrayList<Double> readDoubleList(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        int length = parcel.readInt();
        ArrayList<Double> list = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            list.add(parcel.readDouble());
        }
        parcel.setDataPosition(start + size);
        return list;
    }

    public static ArrayList<Boolean> readBooleanList(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        int length = parcel.readInt();
        ArrayList<Boolean> list = new ArrayList<>(length);
        for (int i = 0; i < length; i++) {
            list.add(parcel.readInt() != 0);
        }
        parcel.setDataPosition(start + size);
        return list;
    }

    public static <T extends Parcelable> T[] readParcelableArray(Parcel parcel, int header, Parcelable.Creator<T> creator) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        T[] arr = parcel.createTypedArray(creator);
        parcel.setDataPosition(start + size);
        return arr;
    }

    public static String[] readStringArray(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        String[] arr = parcel.createStringArray();
        parcel.setDataPosition(start + size);
        return arr;
    }

    public static byte[] readByteArray(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        byte[] arr = parcel.createByteArray();
        parcel.setDataPosition(start + size);
        return arr;
    }

    public static byte[][] readByteArrayArray(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        int length = parcel.readInt();
        byte[][] arr = new byte[length][];
        for (int i = 0; i < length; i++) {
            arr[i] = parcel.createByteArray();
        }
        parcel.setDataPosition(start + size);
        return arr;
    }

    public static float[] readFloatArray(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        float[] arr = parcel.createFloatArray();
        parcel.setDataPosition(start + size);
        return arr;
    }

    public static int[] readIntArray(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        int[] arr = parcel.createIntArray();
        parcel.setDataPosition(start + size);
        return arr;
    }

    public static Bundle readBundle(Parcel parcel, int header, ClassLoader classLoader) {
        int size = readSize(parcel, header);
        if (size == 0)
            return null;
        int start = parcel.dataPosition();
        Bundle bundle = parcel.readBundle(classLoader);
        parcel.setDataPosition(start + size);
        return bundle;
    }

    public static void skip(Parcel parcel, int header) {
        int size = readSize(parcel, header);
        parcel.setDataPosition(parcel.dataPosition() + size);
    }

    public static class ReadException extends RuntimeException {
        public ReadException(String message, Parcel parcel) {
            super(message);
        }
    }
}
 No newline at end of file
+384 −0
Original line number Diff line number Diff line
/*
 * SPDX-FileCopyrightText: 2015, microG Project Team
 * SPDX-License-Identifier: Apache-2.0
 */

package com.google.android.gms.common.internal.safeparcel;

import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.List;
import java.util.Map;

@SuppressWarnings("MagicNumber")
public final class SafeParcelWriter {

    private SafeParcelWriter() {
    }

    private static void writeHeader(Parcel parcel, int fieldId, int size) {
        if (size >= 0xFFFF) {
            parcel.writeInt(0xFFFF0000 | fieldId);
            parcel.writeInt(size);
        } else {
            parcel.writeInt(size << 16 | fieldId);
        }
    }

    @Deprecated
    public static int writeStart(Parcel parcel) {
        return writeObjectHeader(parcel);
    }

    public static int writeObjectHeader(Parcel parcel) {
        writeHeader(parcel, SafeParcelable.SAFE_PARCEL_OBJECT_MAGIC, 0xFFFF);
        return parcel.dataPosition();
    }

    private static int writeObjectHeader(Parcel parcel, int fieldId) {
        writeHeader(parcel, fieldId, 0xFFFF);
        return parcel.dataPosition();
    }

    @Deprecated
    public static void writeEnd(Parcel parcel, int start) {
        finishObjectHeader(parcel, start);
    }

    public static void finishObjectHeader(Parcel parcel, int start) {
        int end = parcel.dataPosition();
        int length = end - start;
        parcel.setDataPosition(start - 4);
        parcel.writeInt(length);
        parcel.setDataPosition(end);
    }

    public static void write(Parcel parcel, int fieldId, Boolean val) {
        if (val == null) return;
        writeHeader(parcel, fieldId, 4);
        parcel.writeInt(val ? 1 : 0);
    }

    public static void write(Parcel parcel, int fieldId, Byte val) {
        if (val == null) return;
        writeHeader(parcel, fieldId, 4);
        parcel.writeInt(val);
    }

    public static void write(Parcel parcel, int fieldId, Short val) {
        if (val == null) return;
        writeHeader(parcel, fieldId, 4);
        parcel.writeInt(val);
    }

    public static void write(Parcel parcel, int fieldId, Integer val) {
        if (val == null) return;
        writeHeader(parcel, fieldId, 4);
        parcel.writeInt(val);
    }

    public static void write(Parcel parcel, int fieldId, Long val) {
        if (val == null) return;
        writeHeader(parcel, fieldId, 8);
        parcel.writeLong(val);
    }

    public static void write(Parcel parcel, int fieldId, Float val) {
        if (val == null) return;
        writeHeader(parcel, fieldId, 4);
        parcel.writeFloat(val);
    }

    public static void write(Parcel parcel, int fieldId, Double val) {
        if (val == null) return;
        writeHeader(parcel, fieldId, 8);
        parcel.writeDouble(val);
    }

    public static void write(Parcel parcel, int fieldId, String val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeString(val);
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, Parcelable val, int flags, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            val.writeToParcel(parcel, flags);
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, Bundle val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeBundle(val);
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, byte[] val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeByteArray(val);
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, byte[][] val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeInt(val.length);
            for (byte[] arr : val) {
                parcel.writeByteArray(arr);
            }
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, float[] val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeFloatArray(val);
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, int[] val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeIntArray(val);
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, String[] val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeStringArray(val);
            finishObjectHeader(parcel, start);
        }
    }

    public static void writeStringList(Parcel parcel, int fieldId, List<String> val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeStringList(val);
            finishObjectHeader(parcel, start);
        }
    }

    public static void writeIntegerList(Parcel parcel, int fieldId, List<Integer> val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeInt(val.size());
            for (Integer i : val) {
                parcel.writeInt(i);
            }
            finishObjectHeader(parcel, start);
        }
    }

    public static void writeLongList(Parcel parcel, int fieldId, List<Long> val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeInt(val.size());
            for (Long l : val) {
                parcel.writeLong(l);
            }
            finishObjectHeader(parcel, start);
        }
    }

    public static void writeFloatList(Parcel parcel, int fieldId, List<Float> val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeInt(val.size());
            for (Float f : val) {
                parcel.writeFloat(f);
            }
            finishObjectHeader(parcel, start);
        }
    }

    public static void writeDoubleList(Parcel parcel, int fieldId, List<Double> val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeInt(val.size());
            for (Double d : val) {
                parcel.writeDouble(d);
            }
            finishObjectHeader(parcel, start);
        }
    }

    public static void writeBooleanList(Parcel parcel, int fieldId, List<Boolean> val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeInt(val.size());
            for (Boolean b : val) {
                parcel.writeInt(b ? 1 : 0);
            }
            finishObjectHeader(parcel, start);
        }
    }

    private static <T extends Parcelable> void writeArrayPart(Parcel parcel, T val, int flags) {
        int before = parcel.dataPosition();
        parcel.writeInt(1);
        int start = parcel.dataPosition();
        val.writeToParcel(parcel, flags);
        int end = parcel.dataPosition();
        parcel.setDataPosition(before);
        parcel.writeInt(end - start);
        parcel.setDataPosition(end);
    }

    public static <T extends Parcelable> void write(Parcel parcel, int fieldId, T[] val, int flags, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeInt(val.length);
            for (T t : val) {
                if (t == null) {
                    parcel.writeInt(0);
                } else {
                    writeArrayPart(parcel, t, flags);
                }
            }
            finishObjectHeader(parcel, start);
        }
    }

    public static <T extends Parcelable> void write(Parcel parcel, int fieldId, List<T> val, int flags, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeInt(val.size());
            for (T t : val) {
                if (t == null) {
                    parcel.writeInt(0);
                } else {
                    writeArrayPart(parcel, t, flags);
                }
            }
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, Parcel val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.appendFrom(val, 0, val.dataSize());
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, List val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeList(val);
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, Map val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeMap(val);
            finishObjectHeader(parcel, start);
        }
    }

    public static void write(Parcel parcel, int fieldId, IBinder val, boolean mayNull) {
        if (val == null) {
            if (mayNull) {
                writeHeader(parcel, fieldId, 0);
            }
        } else {
            int start = writeObjectHeader(parcel, fieldId);
            parcel.writeStrongBinder(val);
            finishObjectHeader(parcel, start);
        }
    }

}
 No newline at end of file
Loading