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

Commit adc72351 authored by Robin Lee's avatar Robin Lee Committed by Android (Google) Code Review
Browse files

Merge "Add parcel exceptions to BaseParceledListSlice"

parents 899d2fe8 f02395e1
Loading
Loading
Loading
Loading
+35 −25
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.content.pm;

import android.compat.annotation.UnsupportedAppUsage;
import android.os.BadParcelableException;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
@@ -92,20 +93,22 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
            data.writeInt(i);
            try {
                retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
            } catch (RemoteException e) {
                Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
                return;
            }
                reply.readException();
                while (i < N && reply.readInt() != 0) {
                    listElementClass = readVerifyAndAddElement(creator, reply, loader,
                            listElementClass);
                    if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
                    i++;
                }
            } catch (RemoteException e) {
                throw new BadParcelableException(
                        "Failure retrieving array; only received " + i + " of " + N, e);
            } finally {
                reply.recycle();
                data.recycle();
            }
        }
    }

    private Class<?> readVerifyAndAddElement(Parcelable.Creator<?> creator, Parcel p,
            ClassLoader loader, Class<?> listElementClass) {
@@ -201,6 +204,8 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
                                    + Binder.getCallingPid() + ", sender=" + this);
                        }

                        try {
                            reply.writeNoException();
                            while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
                                reply.writeInt(1);

@@ -215,8 +220,13 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
                                if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
                                reply.writeInt(0);
                            } else {
                            if (DEBUG) Log.d(TAG, "Transfer complete, clearing mList reference");
                                if (DEBUG) Log.d(TAG, "Transfer done, clearing mList reference");
                                mList = null;
                            }
                        } catch (RuntimeException e) {
                            if (DEBUG) Log.d(TAG, "Transfer failed, clearing mList reference");
                            mList = null;
                            throw e;
                        }
                        return true;
                    }
+65 −0
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@

package android.content.pm;

import static org.junit.Assert.assertThrows;

import android.os.Parcel;
import android.os.Parcelable;
import android.os.ServiceSpecificException;
import android.platform.test.annotations.Presubmit;

import androidx.test.filters.LargeTest;
@@ -114,6 +117,34 @@ public class ParceledListSliceTest extends TestCase {
        }
    }

    /**
     * Test that exceptions created when parcelling data in the service are really
     * sent to the client and re-thrown.
     */
    public void testThrownException() throws Exception {
        final List<ThrowingObject> throwers = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            throwers.add(new ThrowingObject(/* throws= */ false));
        }
        throwers.add(new ThrowingObject(/* throws= */ true));

        final ParceledListSlice<ThrowingObject> src = new ParceledListSlice<>(throwers);
        src.setInlineCountLimit(1);

        Parcel parcel = Parcel.obtain();
        try {
            parcel.writeParcelable(src, 0);
            parcel.setDataPosition(0);

            assertThrows(ServiceSpecificException.class, () -> {
                final ParceledListSlice<ThrowingObject> dst =
                        parcel.readParcelable(getClass().getClassLoader());
            });
        } finally {
            parcel.recycle();
        }
    }

    private void sendParcelStringList(List<String> list) {
        StringParceledListSlice slice;
        Parcel parcel = Parcel.obtain();
@@ -236,6 +267,40 @@ public class ParceledListSliceTest extends TestCase {
        };
    }

    public static class ThrowingObject implements Parcelable {

        private final boolean mShouldThrow;

        public ThrowingObject(boolean shouldThrow) {
            mShouldThrow = shouldThrow;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            if (mShouldThrow) {
                throw new ServiceSpecificException(1234);
            }
            dest.writeBoolean(mShouldThrow);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        public static final Creator<ThrowingObject> CREATOR = new Creator<ThrowingObject>() {
            @Override
            public ThrowingObject createFromParcel(Parcel source) {
                return new ThrowingObject(source.readBoolean());
            }

            @Override
            public ThrowingObject[] newArray(int size) {
                return new ThrowingObject[size];
            }
        };
    }

    public static class SmallObject extends BaseObject {
        public int mFieldA;
        public int mFieldB;