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

Commit 4762e7e8 authored by Stanislav Zholnin's avatar Stanislav Zholnin
Browse files

Fix bug in BaseParceledListSlice implementation.

Under specific conditions, parceled list can be written in such a
way that writing of new list starts when destination parcel is
just above MAX_IPC_SIZE. In that case "0" is written to parcel to
indicate that there will be no inline items written and writing of
the list will start with extra items.

When unparcelling such list, listElementClass is not determined and
stays equal to null, because it only can be determined if there
were some inline items read first, before switching to extra.

This leads to random unparcelling failures with the following
error message:

Can't unparcel type <typename> in list of type null.

Test: manually verified
Bug: 186193371
Fix: 151481291
Bug: 156514418
Fix: 169191099
Change-Id: I849bf46158b6d9b109139b19b93a6a1ba16ecc77
parent a7e8d89a
Loading
Loading
Loading
Loading
+15 −15
Original line number Diff line number Diff line
@@ -75,16 +75,7 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
            if (p.readInt() == 0) {
                break;
            }

            final T parcelable = readCreator(creator, p, loader);
            if (listElementClass == null) {
                listElementClass = parcelable.getClass();
            } else {
                verifySameType(listElementClass, parcelable.getClass());
            }

            mList.add(parcelable);

            listElementClass = readVerifyAndAddElement(creator, p, loader, listElementClass);
            if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
            i++;
        }
@@ -104,11 +95,8 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
                return;
            }
            while (i < N && reply.readInt() != 0) {
                final T parcelable = readCreator(creator, reply, loader);
                verifySameType(listElementClass, parcelable.getClass());

                mList.add(parcelable);

                listElementClass = readVerifyAndAddElement(creator, reply, loader,
                        listElementClass);
                if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
                i++;
            }
@@ -117,6 +105,18 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
        }
    }

    private Class<?> readVerifyAndAddElement(Parcelable.Creator<?> creator, Parcel p,
            ClassLoader loader, Class<?> listElementClass) {
        final T parcelable = readCreator(creator, p, loader);
        if (listElementClass == null) {
            listElementClass = parcelable.getClass();
        } else {
            verifySameType(listElementClass, parcelable.getClass());
        }
        mList.add(parcelable);
        return listElementClass;
    }

    private T readCreator(Parcelable.Creator<?> creator, Parcel p, ClassLoader loader) {
        if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
            Parcelable.ClassLoaderCreator<?> classLoaderCreator =