Loading core/java/android/content/pm/BaseParceledListSlice.java +35 −25 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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; } Loading core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java +65 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading
core/java/android/content/pm/BaseParceledListSlice.java +35 −25 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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; } Loading
core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java +65 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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; Loading