Add parcel exceptions to BaseParceledListSlice
Test: atest ParceledListSliceTest Bug: 215106618 Change-Id: Ieaee31a0cb2debe08a91b1dd60e42fb97f710806
This commit is contained in:
@@ -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,18 +93,20 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
|
||||
data.writeInt(i);
|
||||
try {
|
||||
retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
|
||||
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) {
|
||||
Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
|
||||
return;
|
||||
throw new BadParcelableException(
|
||||
"Failure retrieving array; only received " + i + " of " + N, e);
|
||||
} finally {
|
||||
reply.recycle();
|
||||
data.recycle();
|
||||
}
|
||||
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++;
|
||||
}
|
||||
reply.recycle();
|
||||
data.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,22 +204,29 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
|
||||
+ Binder.getCallingPid() + ", sender=" + this);
|
||||
}
|
||||
|
||||
while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
|
||||
reply.writeInt(1);
|
||||
try {
|
||||
reply.writeNoException();
|
||||
while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
|
||||
reply.writeInt(1);
|
||||
|
||||
final T parcelable = mList.get(i);
|
||||
verifySameType(listElementClass, parcelable.getClass());
|
||||
writeElement(parcelable, reply, callFlags);
|
||||
final T parcelable = mList.get(i);
|
||||
verifySameType(listElementClass, parcelable.getClass());
|
||||
writeElement(parcelable, reply, callFlags);
|
||||
|
||||
if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
|
||||
i++;
|
||||
}
|
||||
if (i < N) {
|
||||
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, "Wrote extra #" + i + ": " + mList.get(i));
|
||||
i++;
|
||||
}
|
||||
if (i < N) {
|
||||
if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
|
||||
reply.writeInt(0);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user